minc-2.2.00/0000755000265600003100000000000012030114724007511 500000000000000minc-2.2.00/ac_config_aux/0000755000265600003100000000000012030114722012274 500000000000000minc-2.2.00/ac_config_aux/compile0000755000265600003100000000717312027132657013617 00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2005-05-14.22 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` # Create the lock directory. # Note: use `[/.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: minc-2.2.00/ac_config_aux/config.guess0000755000265600003100000012753412027132657014565 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. timestamp='2008-01-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[456]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:[3456]*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; EM64T | authenticamd) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else echo ${UNAME_MACHINE}-unknown-linux-gnueabi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^LIBC/{ s: ::g p }'`" test x"${LIBC}" != x && { echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: minc-2.2.00/ac_config_aux/config.sub0000755000265600003100000010115312027132657014215 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. timestamp='2008-01-16' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | score \ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tile*) basic_machine=tile-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: minc-2.2.00/ac_config_aux/depcomp0000755000265600003100000004271312027132657013615 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2007-03-29.01 # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software # Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: minc-2.2.00/ac_config_aux/install-sh0000755000265600003100000003246412027132657014246 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2006-12-25.00 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: minc-2.2.00/ac_config_aux/ltmain.sh0000755000265600003100000073341512027132657014071 00000000000000# Generated from ltmain.m4sh. # ltmain.sh (GNU libtool) 2.2.6b # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print informational messages (default) # --version print version information # -h, --help print short or long help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . PROGRAM=ltmain.sh PACKAGE=libtool VERSION="2.2.6b Debian-2.2.6b-2ubuntu1" TIMESTAMP="" package_revision=1.3017 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # NLS nuisances: We save the old values to restore during execute mode. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done $lt_unset CDPATH : ${CP="cp -f"} : ${ECHO="echo"} : ${EGREP="/bin/grep -E"} : ${FGREP="/bin/grep -F"} : ${GREP="/bin/grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="/bin/sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # Generated shell functions inserted here. # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" # The name of this program: # In the unlikely event $progname began with a '-', it would play havoc with # func_echo (imagine progname=-n), so we prepend ./ in that case: func_dirname_and_basename "$progpath" progname=$func_basename_result case $progname in -*) progname=./$progname ;; esac # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname${mode+: }$mode: $*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` done my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "X$my_tmpdir" | $Xsed } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "X$1" | $Xsed \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_version # Echo version message to standard output and exit. func_version () { $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $SED -n '/^# Usage:/,/# -h/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" $ECHO $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help # Echo long help message to standard output and exit. func_help () { $SED -n '/^# Usage:/,/# Report bugs to/ { s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p }' < "$progpath" exit $? } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { func_error "missing argument for $1" exit_cmd=exit } exit_cmd=: # Check that we have a working $ECHO. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then # Yippee, $ECHO works! : else # Restart under the correct shell, and then maybe $ECHO will work. exec $SHELL "$progpath" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # Parse options once, thoroughly. This comes as soon as possible in # the script to make things like `libtool --version' happen quickly. { # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Parse non-mode specific arguments: while test "$#" -gt 0; do opt="$1" shift case $opt in --config) func_config ;; --debug) preserve_args="$preserve_args $opt" func_echo "enabling shell trace mode" opt_debug='set -x' $opt_debug ;; -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break execute_dlfiles="$execute_dlfiles $1" shift ;; --dry-run | -n) opt_dry_run=: ;; --features) func_features ;; --finish) mode="finish" ;; --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break case $1 in # Valid mode arguments: clean) ;; compile) ;; execute) ;; finish) ;; install) ;; link) ;; relink) ;; uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac mode="$1" shift ;; --preserve-dup-deps) opt_duplicate_deps=: ;; --quiet|--silent) preserve_args="$preserve_args $opt" opt_silent=: ;; --verbose| -v) preserve_args="$preserve_args $opt" opt_silent=false ;; --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break preserve_args="$preserve_args $opt $1" func_enable_tag "$1" # tagname is set here shift ;; # Separate optargs to long options: -dlopen=*|--mode=*|--tag=*) func_opt_split "$opt" set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} shift ;; -\?|-h) func_usage ;; --help) opt_help=: ;; --version) func_version ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) nonopt="$opt" break ;; esac done case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_duplicate_deps ;; esac # Having warned about all mis-specified options, bail out if # anything was wrong. $exit_cmd $EXIT_FAILURE } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } ## ----------- ## ## Main. ## ## ----------- ## $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi test -z "$mode" && func_fatal_error "error: you must specify a MODE." # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$mode' for more information." } # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_ltwrapper_scriptname_result="" if func_ltwrapper_executable_p "$1"; then func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" fi } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case "$@ " in " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T <?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi removelist="$removelist $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist removelist="$removelist $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir command="$command -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$mode'" ;; esac $ECHO $ECHO "Try \`$progname --help' for more information about other modes." exit $? } # Now that we've collected a possible --mode arg, show help if necessary $opt_help && func_mode_help # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $execute_dlfiles; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_quote_for_eval "$file" args="$args $func_quote_for_eval_result" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" $ECHO "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS $ECHO "X----------------------------------------------------------------------" | $Xsed $ECHO "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done $ECHO $ECHO "If you ever happen to want to link against installed libraries" $ECHO "in a given directory, LIBDIR, you must either use libtool, and" $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" $ECHO "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" $ECHO " during execution" fi if test -n "$runpath_var"; then $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" $ECHO " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $ECHO $ECHO "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" $ECHO "pages." ;; *) $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac $ECHO "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS } test "$mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $ECHO "X$nonopt" | $GREP shtool >/dev/null; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" install_prog="$install_prog$func_quote_for_eval_result" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) case " $install_prog " in *[\\\ /]cp\ *) ;; *) prev=$arg ;; esac ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" install_prog="$install_prog $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for progfile in $progfiles; do func_verbose "extracting global C symbols from \`$progfile'" $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" } done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" fi $ECHO >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; " case $host in *cygwin* | *mingw* | *cegcc* ) $ECHO >> "$output_objdir/$my_dlsyms" "\ /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */" lt_dlsym_const= ;; *osf5*) echo >> "$output_objdir/$my_dlsyms" "\ /* This system does not cope well with relocations in const data */" lt_dlsym_const= ;; *) lt_dlsym_const=const ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ extern $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) symtab_cflags="$symtab_cflags $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper_part1 [arg=no] # # Emit the first part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part1 () { func_emit_wrapper_part1_arg1=no if test -n "$1" ; then func_emit_wrapper_part1_arg1=$1 fi $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then ECHO=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then # Yippee, \$ECHO works! : else # Restart under the correct shell, and then maybe \$ECHO will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $ECHO "\ # Find the directory that this script lives in. thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done " } # end: func_emit_wrapper_part1 # func_emit_wrapper_part2 [arg=no] # # Emit the second part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part2 () { func_emit_wrapper_part2_arg1=no if test -n "$1" ; then func_emit_wrapper_part2_arg1=$1 fi $ECHO "\ # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # end: func_emit_wrapper_part2 # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=no if test -n "$1" ; then func_emit_wrapper_arg1=$1 fi # split this up so that func_emit_cwrapperexe_src # can call each part independently. func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" } # func_to_host_path arg # # Convert paths to host format when used with build tools. # Intended for use with "native" mingw (where libtool itself # is running under the msys shell), or in the following cross- # build environments: # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # where wine is equipped with the `winepath' executable. # In the native mingw case, the (msys) shell automatically # converts paths for any non-msys applications it launches, # but that facility isn't available from inside the cwrapper. # Similar accommodations are necessary for $host mingw and # $build cygwin. Calling this function does no harm for other # $host/$build combinations not listed above. # # ARG is the path (on $build) that should be converted to # the proper representation for $host. The result is stored # in $func_to_host_path_result. func_to_host_path () { func_to_host_path_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' case $build in *mingw* ) # actually, msys # awkward: cmd appends spaces to result lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_path_tmp1=`( cmd //c echo "$1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_path_tmp1=`cygpath -w "$1"` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # Unfortunately, winepath does not exit with a non-zero # error code, so we are forced to check the contents of # stdout. On the other hand, if the command is not # found, the shell will set an exit code of 127 and print # *an error message* to stdout. So we must check for both # error code of zero AND non-empty stdout, which explains # the odd construction: func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` else # Allow warning below. func_to_host_path_result="" fi ;; esac if test -z "$func_to_host_path_result" ; then func_error "Could not determine host path corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_path_result="$1" fi ;; esac fi } # end: func_to_host_path # func_to_host_pathlist arg # # Convert pathlists to host format when used with build tools. # See func_to_host_path(), above. This function supports the # following $build/$host combinations (but does no harm for # combinations not listed here): # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # # Path separators are also converted from $build format to # $host format. If ARG begins or ends with a path separator # character, it is preserved (but converted to $host format) # on output. # # ARG is a pathlist (on $build) that should be converted to # the proper representation on $host. The result is stored # in $func_to_host_pathlist_result. func_to_host_pathlist () { func_to_host_pathlist_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_to_host_pathlist_tmp2="$1" # Once set for this call, this variable should not be # reassigned. It is used in tha fallback case. func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e 's|^:*||' -e 's|:*$||'` case $build in *mingw* ) # Actually, msys. # Awkward: cmd appends spaces to result. lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # unfortunately, winepath doesn't convert pathlists func_to_host_pathlist_result="" func_to_host_pathlist_oldIFS=$IFS IFS=: for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do IFS=$func_to_host_pathlist_oldIFS if test -n "$func_to_host_pathlist_f" ; then func_to_host_path "$func_to_host_pathlist_f" if test -n "$func_to_host_path_result" ; then if test -z "$func_to_host_pathlist_result" ; then func_to_host_pathlist_result="$func_to_host_path_result" else func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" fi fi fi IFS=: done IFS=$func_to_host_pathlist_oldIFS ;; esac if test -z "$func_to_host_pathlist_result" ; then func_error "Could not determine the host path(s) corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This may break if $1 contains DOS-style drive # specifications. The fix is not to complicate the expression # below, but for the user to provide a working wine installation # with winepath so that path translation in the cross-to-mingw # case works properly. lt_replace_pathsep_nix_to_dos="s|:|;|g" func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_replace_pathsep_nix_to_dos"` fi # Now, add the leading and trailing path separators back case "$1" in :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" ;; esac case "$1" in *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" ;; esac ;; esac fi } # end: func_to_host_pathlist # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include # define setmode _setmode #else # include # include # ifdef __CYGWIN__ # include # define HAVE_SETENV # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif # endif #endif #include #include #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif #ifdef _MSC_VER # define S_IXUSR _S_IEXEC # define stat _stat # ifndef _INTPTR_T_DEFINED # define intptr_t int # endif #endif #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifdef __CYGWIN__ # define FOPEN_WB "wb" #endif #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #undef LTWRAPPER_DEBUGPRINTF #if defined DEBUGWRAPPER # define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args static void ltwrapper_debugprintf (const char *fmt, ...) { va_list args; va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } #else # define LTWRAPPER_DEBUGPRINTF(args) #endif const char *program_name = NULL; void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_fatal (const char *message, ...); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_opt_process_env_set (const char *arg); void lt_opt_process_env_prepend (const char *arg); void lt_opt_process_env_append (const char *arg); int lt_split_name_value (const char *arg, char** name, char** value); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); static const char *script_text_part1 = EOF func_emit_wrapper_part1 yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ "/' -e 's/$/\\n"/' echo ";" cat <"))); for (i = 0; i < newargc; i++) { LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); } EOF case $host_os in mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); return 127; } return rval; EOF ;; *) cat <<"EOF" execv (lt_argv_zero, newargz); return rval; /* =127, but avoids unused variable warning */ EOF ;; esac cat <<"EOF" } void * xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char) name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable (const char *path) { struct stat st; LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", tmp_pathspec)); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { char *errstr = strerror (errno); lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal ("Could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } void lt_setenv (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", (name ? name : ""), (value ? value : ""))); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } int lt_split_name_value (const char *arg, char** name, char** value) { const char *p; int len; if (!arg || !*arg) return 1; p = strchr (arg, (int)'='); if (!p) return 1; *value = xstrdup (++p); len = strlen (arg) - strlen (*value); *name = XMALLOC (char, len); strncpy (*name, arg, len-1); (*name)[len - 1] = '\0'; return 0; } void lt_opt_process_env_set (const char *arg) { char *name = NULL; char *value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); } lt_setenv (name, value); XFREE (name); XFREE (value); } void lt_opt_process_env_prepend (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); } new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_opt_process_env_append (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); } new_value = lt_extend_str (getenv (name), value, 1); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_update_exe_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF } # end: func_emit_cwrapperexe_src # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) deplibs="$deplibs $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) weak_libs="$weak_libs $arg" prev= continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname '-L' '' "$arg" dir=$func_stripname_result if test -z "$dir"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" linker_flags="$linker_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # -64, -mips[0-9] enable 64-bit mode on the SGI compiler # -r[0-9][0-9]* specifies the processor on the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler # +DA*, +DD* enable 64-bit mode on the HP compiler # -q* pass through compiler args for the IBM compiler # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC # -F/path gives path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC # @file GCC response files -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" compiler_flags="$compiler_flags $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_duplicate_deps ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= case $lib in *.la) func_source "$lib" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` case " $weak_libs " in *" $deplib_base "*) ;; *) deplibs="$deplibs $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else compiler_flags="$compiler_flags $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" dir=$func_stripname_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then $ECHO $ECHO "*** Warning: Trying to link with static lib archive $deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because the file extensions .$libext of this argument makes me believe" $ECHO "*** that it is just a static archive that I should not use here." else $ECHO $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) temp_rpath="$temp_rpath$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded notinst_deplibs="$notinst_deplibs $lib" need_relink=no ;; *) if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then $ECHO if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $ECHO $ECHO "*** And there doesn't seem to be a static archive available" $ECHO "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $ECHO $ECHO "*** Warning: This system can not link to static lib archive $lib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $ECHO "*** But as you try to build a module library, libtool will still create " $ECHO "*** a static module, that should work as long as the dlopening application" $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_dirname "$deplib" "" "." dir="$func_dirname_result" # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else $ECHO $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" libobjs="$libobjs $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi removelist="$removelist $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` done fi if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | $GREP . >/dev/null; then $ECHO if test "X$deplibs_check_method" = "Xnone"; then $ECHO "*** Warning: inter-library dependencies are not supported in this platform." else $ECHO "*** Warning: inter-library dependencies are not known to be supported." fi $ECHO "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $ECHO $ECHO "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" $ECHO "*** a static module, that should work as long as the dlopening" $ECHO "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $ECHO "*** The inter-library dependencies that have been dropped here will be" $ECHO "*** automatically added whenever a program is linked with this library" $ECHO "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $ECHO $ECHO "*** Since this library must not contain undefined symbols," $ECHO "*** because either the platform does not support them or" $ECHO "*** it was explicitly requested with -no-undefined," $ECHO "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" delfiles="$delfiles $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" func_len " $cmd" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then func_show_eval "$cmd" 'exit $?' skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $convenience libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output output_la=`$ECHO "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" $ECHO 'INPUT (' > $output for obj in $save_libobjs do $ECHO "$obj" >> $output done $ECHO ')' >> $output delfiles="$delfiles $output" elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do $ECHO "$obj" >> $output done delfiles="$delfiles $output" output=$firstobj\"$file_list_spec$output\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=$obj func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi delfiles="$delfiles $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done compile_deplibs="$new_libs" compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *cegcc) # Disable wrappers for cegcc, we are cross compiling anyway. wrappers_required=no ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $ECHO for shipping. if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then case $progpath in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; esac qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then oldobjs="$oldobjs $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $addlibs oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles oldobjs="$oldobjs $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else $ECHO "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" oldobjs="$oldobjs $gentop/$newobj" ;; *) oldobjs="$oldobjs $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlfiles="$newdlfiles $libdir/$name" ;; *) newdlfiles="$newdlfiles $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlprefiles="$newdlprefiles $libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$mode" = link || test "$mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) RM="$RM $arg"; rmforce=yes ;; -*) RM="$RM $arg" ;; *) files="$files $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= origobjdir="$objdir" for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then objdir="$origobjdir" else objdir="$dir/$origobjdir" fi func_basename "$file" name="$func_basename_result" test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" case "$mode" in clean) case " $library_names " in # " " in the beginning catches empty $dlname *" $dlname "*) ;; *) rmfiles="$rmfiles $objdir/$dlname" ;; esac test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result rmfiles="$rmfiles $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$mode" = uninstall || test "$mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 minc-2.2.00/ac_config_aux/missing0000755000265600003100000002557712027132657013650 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2006-05-10.23 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). case $1 in lex|yacc) # Not GNU programs, they don't have --version. ;; tar) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $1 in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: minc-2.2.00/ac_config_aux/ylwrap0000755000265600003100000001407412027132657013503 00000000000000#! /bin/sh # ylwrap - wrapper for lex/yacc invocations. scriptversion=2007-11-22.22 # Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, # 2007 Free Software Foundation, Inc. # # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case "$1" in '') echo "$0: No files given. Try \`$0 --help' for more information." 1>&2 exit 1 ;; --basedir) basedir=$2 shift 2 ;; -h|--h*) cat <<\EOF Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... Wrapper for lex/yacc invocations, renaming files as desired. INPUT is the input file OUTPUT is one file PROG generates DESIRED is the file we actually want instead of OUTPUT PROGRAM is program to run ARGS are passed to PROG Any number of OUTPUT,DESIRED pairs may be used. Report bugs to . EOF exit $? ;; -v|--v*) echo "ylwrap $scriptversion" exit $? ;; esac # The input. input="$1" shift case "$input" in [\\/]* | ?:[\\/]*) # Absolute path; do nothing. ;; *) # Relative path. Make it absolute. input="`pwd`/$input" ;; esac pairlist= while test "$#" -ne 0; do if test "$1" = "--"; then shift break fi pairlist="$pairlist $1" shift done # The program to run. prog="$1" shift # Make any relative path in $prog absolute. case "$prog" in [\\/]* | ?:[\\/]*) ;; *[\\/]*) prog="`pwd`/$prog" ;; esac # FIXME: add hostname here for parallel makes that run commands on # other machines. But that might take us over the 14-char limit. dirname=ylwrap$$ trap "cd '`pwd`'; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15 mkdir $dirname || exit 1 cd $dirname case $# in 0) "$prog" "$input" ;; *) "$prog" "$@" "$input" ;; esac ret=$? if test $ret -eq 0; then set X $pairlist shift first=yes # Since DOS filename conventions don't allow two dots, # the DOS version of Bison writes out y_tab.c instead of y.tab.c # and y_tab.h instead of y.tab.h. Test to see if this is the case. y_tab_nodot="no" if test -f y_tab.c || test -f y_tab.h; then y_tab_nodot="yes" fi # The directory holding the input. input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'` # Quote $INPUT_DIR so we can use it in a regexp. # FIXME: really we should care about more than `.' and `\'. input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'` while test "$#" -ne 0; do from="$1" # Handle y_tab.c and y_tab.h output by DOS if test $y_tab_nodot = "yes"; then if test $from = "y.tab.c"; then from="y_tab.c" else if test $from = "y.tab.h"; then from="y_tab.h" fi fi fi if test -f "$from"; then # If $2 is an absolute path name, then just use that, # otherwise prepend `../'. case "$2" in [\\/]* | ?:[\\/]*) target="$2";; *) target="../$2";; esac # We do not want to overwrite a header file if it hasn't # changed. This avoid useless recompilations. However the # parser itself (the first file) should always be updated, # because it is the destination of the .y.c rule in the # Makefile. Divert the output of all other files to a temporary # file so we can compare them to existing versions. if test $first = no; then realtarget="$target" target="tmp-`echo $target | sed s/.*[\\/]//g`" fi # Edit out `#line' or `#' directives. # # We don't want the resulting debug information to point at # an absolute srcdir; it is better for it to just mention the # .y file with no path. # # We want to use the real output file name, not yy.lex.c for # instance. # # We want the include guards to be adjusted too. FROM=`echo "$from" | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` TARGET=`echo "$2" | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \ -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$? # Check whether header files must be updated. if test $first = no; then if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then echo "$2" is unchanged rm -f "$target" else echo updating "$2" mv -f "$target" "$realtarget" fi fi else # A missing file is only an error for the first file. This # is a blatant hack to let us support using "yacc -d". If -d # is not specified, we don't want an error when the header # file is "missing". if test $first = yes; then ret=1 fi fi shift shift first=no done else ret=$? fi # Remove the directory. cd .. rm -rf $dirname exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: minc-2.2.00/cmake-modules/0000755000265600003100000000000012030114723012236 500000000000000minc-2.2.00/cmake-modules/FindHDF5.cmake0000644000265600003100000000436512027132657014473 00000000000000# # this module look for HDF5 (http://hdf.ncsa.uiuc.edu) support # it will define the following values # # HDF5_INCLUDE_DIR = where hdf5.h can be found # HDF5_LIBRARY = the library to link against (hdf5 etc) # HDF5_FOUND = set to true after finding the library # IF(EXISTS ${PROJECT_CMAKE}/Hdf5Config.cmake) INCLUDE(${PROJECT_CMAKE}/Hdf5Config.cmake) ENDIF(EXISTS ${PROJECT_CMAKE}/Hdf5Config.cmake) IF(Hdf5_INCLUDE_DIRS) FIND_PATH(HDF5_INCLUDE_DIR hdf5.h ${Hdf5_INCLUDE_DIRS}) FIND_LIBRARY(HDF5_LIBRARY hdf5 ${Hdf5_LIBRARY_DIRS}) ELSE(Hdf5_INCLUDE_DIRS) SET(TRIAL_LIBRARY_PATHS $ENV{HDF5_HOME}/lib /usr/apps/lib /usr/lib /usr/local/lib /opt/lib /sw/lib ) SET(TRIAL_INCLUDE_PATHS $ENV{HDF5_HOME}/include /usr/apps/include /usr/include /opt/include /usr/local/include /sw/include ) IF($ENV{HDF5_DIR} MATCHES "hdf") MESSAGE(STATUS "Using environment variable HDF5_DIR.") SET(TRIAL_LIBRARY_PATHS $ENV{HDF5_DIR}/lib ${TRIAL_LIBRARY_PATHS} ) SET(TRIAL_INCLUDE_PATHS $ENV{HDF5_DIR}/include ${TRIAL_INCLUDE_PATHS} ) ENDIF($ENV{HDF5_DIR} MATCHES "hdf") FIND_LIBRARY(HDF5_LIBRARY hdf5 ${TRIAL_LIBRARY_PATHS}) FIND_PATH(HDF5_INCLUDE_DIR hdf5.h ${TRIAL_INCLUDE_PATHS} ) ENDIF(Hdf5_INCLUDE_DIRS) ## ----------------------------------------------------------------------------- ## Assign status of the search IF(HDF5_INCLUDE_DIR AND HDF5_LIBRARY) SET(HDF5_FOUND 1 CACHE BOOL "Found hdf5 library") ELSE(HDF5_INCLUDE_DIR AND HDF5_LIBRARY) SET(HDF5_FOUND 0 CACHE BOOL "Not fount hdf5 library") ENDIF(HDF5_INCLUDE_DIR AND HDF5_LIBRARY) ## ----------------------------------------------------------------------------- ## Feedback IF (HDF5_FOUND) IF (NOT HDF5_FIND_QUIETLY) MESSAGE (STATUS "Found components for HDF5") MESSAGE (STATUS "HDF5 library : ${HDF5_LIBRARY}") MESSAGE (STATUS "HDF5 headers : ${HDF5_INCLUDE_DIR}") ENDIF (NOT HDF5_FIND_QUIETLY) ELSE (HDF5_FOUND) IF (HDF5_FIND_REQUIRED) MESSAGE (FATAL_ERROR "Could not find HDF5!") ENDIF (HDF5_FIND_REQUIRED) ENDIF (HDF5_FOUND) ## ----------------------------------------------------------------------------- ## Variables marked as advanced MARK_AS_ADVANCED( HDF5_INCLUDE_DIR HDF5_LIBRARY HDF5_FOUND ) minc-2.2.00/cmake-modules/FindNETCDF.cmake0000644000265600003100000000127712027132657014747 00000000000000# FindNetCDF.cmake module FIND_PATH(NETCDF_INCLUDE_DIR netcdf.h /usr/include /usr/local/include /usr/local/bic/include) FIND_LIBRARY(NETCDF_LIBRARY NAMES netcdf PATHS /usr/lib /usr/local/lib /usr/local/bic/lib) IF (NETCDF_INCLUDE_DIR AND NETCDF_LIBRARY) SET(NETCDF_FOUND TRUE) ENDIF (NETCDF_INCLUDE_DIR AND NETCDF_LIBRARY) IF (NETCDF_FOUND) IF (NOT NETCDF_FIND_QUIETLY) MESSAGE(STATUS "Found NetCDF headers: ${NETCDF_INCLUDE_DIR}") MESSAGE(STATUS "Found NetCDF library: ${NETCDF_LIBRARY}") ENDIF (NOT NETCDF_FIND_QUIETLY) ELSE (NETCDF_FOUND) IF (NETCDF_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Cound not find NetCDF") ENDIF (NETCDF_FIND_REQUIRED) ENDIF (NETCDF_FOUND) minc-2.2.00/conversion/0000755000265600003100000000000012030114723011675 500000000000000minc-2.2.00/conversion/Acr_nema/0000755000265600003100000000000012030114723013402 500000000000000minc-2.2.00/conversion/Acr_nema/acr_nema/0000755000265600003100000000000012030114720015144 500000000000000minc-2.2.00/conversion/Acr_nema/acr_nema/acr_io.h0000644000265600003100000001726612027132657016524 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : acr_nema_io.h @DESCRIPTION: Header file for acr_nema_io code. @METHOD : @GLOBALS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : * $Log: acr_io.h,v $ * Revision 6.4 2008-08-12 05:00:23 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.3 2005/03/04 00:08:08 bert * Cleanup headers, mostly by getting rid of the infernal 'public' and using extern instead * * Revision 6.2 2000/04/28 15:03:11 neelin * Added support for ignoring non-fatal protocol errors (cases where redundant * information is inconsistent). In particular, it is possible to ignore * differences between the group length element and the true group length. * * Revision 6.1 1999/10/29 17:51:50 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.1 1997/09/08 21:53:31 neelin * Added status ACR_CONNECTION_TIMEDOUT. * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.1 1997/07/10 17:14:38 neelin * Added more status codes and function to return status string. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:07 neelin * Release of minc version 0.2 * * Revision 1.8 94/09/28 10:35:40 neelin * Pre-release * * Revision 1.7 94/05/18 08:48:17 neelin * Changed some ACR_OTHER_ERROR's to ACR_ABNORMAL_END_OF_OUTPUT. * * Revision 1.6 94/04/07 10:23:28 neelin * Added ACR_HIGH_LEVEL_ERROR. * * Revision 1.5 94/04/07 10:05:10 neelin * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs * to that or ACR_OTHER_ERROR. * Added #ifdef lint to DEFINE_ELEMENT. * * Revision 1.4 94/01/06 13:31:30 neelin * Changed acr_need_invert to a public function. * * Revision 1.3 93/11/25 10:37:26 neelin * Added byte-ordering test. * * Revision 1.2 93/11/24 11:26:22 neelin * Changed short to unsigned short. * * Revision 1.1 93/11/19 12:50:15 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Length of short and long for ACR-NEMA protocol */ #define ACR_SIZEOF_SHORT 2 #define ACR_SIZEOF_LONG 4 #define ACR_SIZEOF_FLOAT 4 #define ACR_SIZEOF_DOUBLE 8 /* Define the C data types for ACR-NEMA protocol. Note: "numeric" functions use the C double datatype directly. */ typedef unsigned short Acr_Short; typedef unsigned int Acr_Long; /* 4 bytes in both 32 and 64 bits */ typedef float Acr_Float; typedef double Acr_Double; typedef char * Acr_String; /* Undefined element length value for VRs of SQ, OB, OW */ #define ACR_UNDEFINED_ELEMENT_LENGTH 0xFFFFFFFFU /* Tags for sequence items */ #define ACR_ITEM_GROUP 0xfffe #define ACR_ITEM_TAG 0xe000 #define ACR_ITEM_DELIMITER 0xe00d #define ACR_SEQ_DELIMITER 0xe0dd /* Flag for data length to indicate variable length elements */ #define ACR_VARIABLE_LENGTH -1 /* Byte-ordering options */ typedef enum { ACR_UNKNOWN_ENDIAN = 0, ACR_LITTLE_ENDIAN, ACR_BIG_ENDIAN } Acr_byte_order; /* VR encoding options */ typedef enum { ACR_UNKNOWN_VR = 0, ACR_EXPLICIT_VR, ACR_IMPLICIT_VR } Acr_VR_encoding_type; /* Status for io */ typedef enum { ACR_OK, ACR_END_OF_INPUT, ACR_PROTOCOL_ERROR, ACR_OTHER_ERROR, ACR_ABNORMAL_END_OF_INPUT, ACR_HIGH_LEVEL_ERROR, ACR_ABNORMAL_END_OF_OUTPUT, ACR_REACHED_WATCHPOINT, ACR_IO_ERROR, ACR_NO_VR_SPECIFIED, ACR_PDU_UID_TOO_LONG, ACR_CONNECTION_TIMEDOUT } Acr_Status; /* Functions */ extern void acr_set_byte_order(Acr_File *afp, Acr_byte_order byte_order); extern Acr_byte_order acr_get_byte_order(Acr_File *afp); extern int acr_get_machine_byte_order(void); extern int acr_need_invert(Acr_byte_order byte_order); extern void acr_set_vr_encoding(Acr_File *afp, Acr_VR_encoding_type vr_encoding); extern Acr_VR_encoding_type acr_get_vr_encoding(Acr_File *afp); extern void acr_set_ignore_errors(Acr_File *afp, int ignore_nonfatal_protocol_errors); extern int acr_ignore_protocol_errors(Acr_File *afp); extern void acr_reverse_byte_order(long nvals, size_t value_size, void *input_values, void *output_values); extern void acr_get_short(Acr_byte_order byte_order, long nvals, void *input_value, Acr_Short *mach_value); extern void acr_get_long(Acr_byte_order byte_order, long nvals, void *input_value, Acr_Long *mach_value); extern void acr_get_float(Acr_byte_order byte_order, long nvals, void *input_value, Acr_Float *mach_value); extern void acr_get_double(Acr_byte_order byte_order, long nvals, void *input_value, Acr_Double *mach_value); extern void acr_put_short(Acr_byte_order byte_order, long nvals, Acr_Short *mach_value, void *output_value); extern void acr_put_long(Acr_byte_order byte_order, long nvals, Acr_Long *mach_value, void *output_value); extern void acr_put_float(Acr_byte_order byte_order, long nvals, Acr_Float *mach_value, void *output_value); extern void acr_put_double(Acr_byte_order byte_order, long nvals, Acr_Double *mach_value, void *output_value); extern Acr_Status acr_skip_input_data(Acr_File *afp, long nbytes_to_skip); extern Acr_Status acr_read_buffer(Acr_File *afp, unsigned char buffer[], long nbytes_to_read, long *nbytes_read); extern Acr_Status acr_unget_buffer(Acr_File *afp, unsigned char buffer[], long nbytes_to_unget); extern Acr_Status acr_write_buffer(Acr_File *afp, unsigned char buffer[], long nbytes_to_write, long *nbytes_written); extern Acr_Status acr_test_byte_order(Acr_File *afp); extern void acr_copy_file_encoding(Acr_File *afp1, Acr_File *afp2); extern int acr_get_element_header_size(char vr_name[2], Acr_VR_encoding_type vr_encoding); extern Acr_Status acr_peek_at_next_element_id(Acr_File *afp, int *group_id, int *element_id); extern Acr_Status acr_read_one_element(Acr_File *afp, int *group_id, int *element_id, char vr_name[], long *data_length, char **data_pointer); extern Acr_Status acr_write_one_element(Acr_File *afp, int group_id, int element_id, char vr_name[], long data_length, char *data_pointer); extern char *acr_status_string(Acr_Status status); minc-2.2.00/conversion/Acr_nema/acr_nema/dicom_client_routines.h0000644000265600003100000000741612027132657021645 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_client_routines.h @DESCRIPTION: Header for dicom_client_routines.c @GLOBALS : @CREATED : July 9, 1997 (Peter Neelin) @MODIFIED : * $Log: dicom_client_routines.h,v $ * Revision 6.6 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.5 1999/10/29 17:51:50 neelin * Fixed Log keyword * * Revision 6.4 1998/11/13 15:55:27 neelin * Modifications to support asynchronous transfers. * * Revision 6.3 1998/03/23 20:17:17 neelin * Removed some functions. * * Revision 6.2 1997/10/20 23:22:38 neelin * Added routine acr_dicom_close_no_release to close a connection that does * not have an association. * * Revision 6.1 1997/09/15 16:50:59 neelin * Separated out connection timeouts from i/o timeouts and added functions * to change them. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 1.1 1997/09/08 21:52:21 neelin * Initial revision * * Revision 1.3 1997/07/11 17:35:58 neelin * Changed around send and receive routines for data once again. * * Revision 1.2 1997/07/11 13:23:37 neelin * Made changes so that code will compile on sun OS. * Separated out receive_reply from send_group_list. * * Revision 1.1 1997/07/10 17:39:51 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Function prototypes */ public int acr_open_dicom_connection(char *host, char *port, char *called_ae, char *calling_ae, char *abstract_syntax, char *transfer_syntax, Acr_File **afpin, Acr_File **afpout); public void acr_close_dicom_no_release(Acr_File *afpin, Acr_File *afpout); public void acr_close_dicom_connection(Acr_File *afpin, Acr_File *afpout); public int acr_connect_to_host(char *host, char *port, FILE **fpin, FILE **fpout); public char *acr_make_dicom_association(Acr_File *afpin, Acr_File *afpout, char *called_ae, char *calling_ae, char *abstract_syntax_list[], char *transfer_syntax_list[]); public void acr_set_client_timeout(Acr_File *afp, double seconds); public void acr_set_client_initial_timeout(double seconds); public void acr_set_client_max_outstanding(Acr_File *afp, int max); public int acr_get_client_max_outstanding(Acr_File *afp); public void acr_dicom_error(Acr_Status status, char *string); public int acr_release_dicom_association(Acr_File *afpin, Acr_File *afpout); public int acr_send_group_list(Acr_File *afpin, Acr_File *afpout, Acr_Group group_list, char *sop_class_uid); public int acr_transmit_group_list(Acr_File *afpout, Acr_Group group_list, char *sop_class_uid, int message_id); public int acr_receive_reply(Acr_File *afpin); minc-2.2.00/conversion/Acr_nema/acr_nema/dicom_network.h0000644000265600003100000001404112027132657020120 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_network.h @DESCRIPTION: Header file for dicom network code @METHOD : @GLOBALS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : * $Log: dicom_network.h,v $ * Revision 6.7 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.6 2001/03/19 18:30:33 neelin * Added function to set implementation uid and changed name of function * that gets it. * * Revision 6.5 2000/05/17 20:17:48 neelin * Added mechanism to allow testing of input streams for more data through * function acr_file_ismore. * This is used in dicom_client_routines to allow asynchronous transfer * of data, with testing for more input done before sending new messages. * Previous use of select for this was misguided, since select may report that * no data is waiting on the file descriptor while data is store in the file * pointer buffer (or Acr file pointer buffer). * * Revision 6.4 1999/10/29 17:51:51 neelin * Fixed Log keyword * * Revision 6.3 1998/11/11 17:05:03 neelin * Added pointer for client data to dicom structure. * * Revision 6.2 1998/03/23 20:16:37 neelin * Added functions. * * Revision 6.1 1997/10/20 22:52:46 neelin * Added support for implementation user information in association request. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.1 1997/07/09 20:01:40 neelin * Added function acr_dicom_get_io_data. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 1.2 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 1.1 1997/02/20 16:38:17 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* PDU types */ #define ACR_PDU_ASSOC_RQ 0x01 #define ACR_PDU_ASSOC_AC 0x02 #define ACR_PDU_ASSOC_RJ 0x03 #define ACR_PDU_DATA_TF 0x04 #define ACR_PDU_REL_RQ 0x05 #define ACR_PDU_REL_RP 0x06 #define ACR_PDU_ABORT_RQ 0x07 /* Offset for unknown PDU item types */ #define ACR_UNKNOWN_PDU_ITEM_OFFSET 0xFF00 /* Element ids for PDU messages. These are artificial and are for internal use only, so they have negative group numbers. Unrecognized PDU items are stored with element id 0xffxx, where xx is the PDU item type */ #define DCM_PDU_GRPID (-1) #define DCM_PDU_ELEMENT(name, elid, vr) \ ACRLIB_GLOBAL_ELEMENT(name, DCM_PDU_GRPID, elid, vr) DCM_PDU_ELEMENT(DCM_PDU_Type, 0x0010, US); DCM_PDU_ELEMENT(DCM_PDU_Protocol_Version, 0x0020, US); DCM_PDU_ELEMENT(DCM_PDU_Called_Ap_title, 0x0030, UI); DCM_PDU_ELEMENT(DCM_PDU_Calling_Ap_title, 0x0040, UI); DCM_PDU_ELEMENT(DCM_PDU_Application_context, 0x0050, UI); DCM_PDU_ELEMENT(DCM_PDU_Presentation_context, 0x0060, SQ); DCM_PDU_ELEMENT(DCM_PDU_Presentation_context_reply, 0x0070, SQ); DCM_PDU_ELEMENT(DCM_PDU_Presentation_context_list, 0x0080, SQ); DCM_PDU_ELEMENT(DCM_PDU_Presentation_context_reply_list, 0x0090, SQ); DCM_PDU_ELEMENT(DCM_PDU_Presentation_context_id, 0x0100, US); DCM_PDU_ELEMENT(DCM_PDU_Abstract_syntax, 0x0120, UI); DCM_PDU_ELEMENT(DCM_PDU_Transfer_syntax, 0x0130, UI); DCM_PDU_ELEMENT(DCM_PDU_Maximum_length, 0x0140, UL); DCM_PDU_ELEMENT(DCM_PDU_Implementation_class_uid, 0x0141, UI); DCM_PDU_ELEMENT(DCM_PDU_Implementation_version_name, 0x0142, UI); DCM_PDU_ELEMENT(DCM_PDU_Result, 0x0150, US); DCM_PDU_ELEMENT(DCM_PDU_Source, 0x0160, US); DCM_PDU_ELEMENT(DCM_PDU_Reason, 0x0170, US); /* Function prototypes */ public int acr_uid_equal(char *uid1, char *uid2); public char *acr_create_uid(void); public void acr_set_implementation_uid(char *uid); public char *acr_get_implementation_uid(void); public Acr_Status acr_input_dicom_message(Acr_File *dicom_afp, Acr_Message *message); public Acr_Status acr_output_dicom_message(Acr_File *dicom_afp, Acr_Message message); public Acr_File *acr_initialize_dicom_input(void *io_data, int maxlength, Acr_Io_Routine io_routine); public void acr_dicom_set_ismore_function(Acr_File *afp, Acr_Ismore_Function ismore_function); public Acr_File *acr_initialize_dicom_output(void *io_data, int maxlength, Acr_Io_Routine io_routine); public void acr_close_dicom_file(Acr_File *afp); public void *acr_dicom_get_io_data(Acr_File *afp); public void acr_dicom_enable_trace(Acr_File *afp); public void acr_dicom_disable_trace(Acr_File *afp); public void acr_dicom_set_eof(Acr_File *afp); public void acr_set_dicom_maximum_length(Acr_File *afp, long maximum_length); public void acr_set_dicom_pres_context_id(Acr_File *afp, int presentation_context_id); public int acr_get_dicom_pres_context_id(Acr_File *afp); public void acr_set_dicom_client_data(Acr_File *afp, void *client_data); public void *acr_get_dicom_client_data(Acr_File *afp); minc-2.2.00/conversion/Acr_nema/acr_nema/element.h0000644000265600003100000002243212027132657016710 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : element.h @DESCRIPTION: Header file for acr-nema element code @METHOD : @GLOBALS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : * $Log: element.h,v $ * Revision 6.5 2008-08-12 05:00:23 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.4 2006/04/09 15:28:40 bert * Add functions acr_get_element_double_array and acr_create_element_double * * Revision 6.3 2005/03/04 00:08:08 bert * Cleanup headers, mostly by getting rid of the infernal 'public' and using extern instead * * Revision 6.2 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.1 1999/10/29 17:51:52 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.2 1997/09/02 22:51:52 neelin * Fixed padding of of UI strings and got rid of acr_string_pad_char * function. * * Revision 5.1 1997/08/22 15:08:34 neelin * Added routine acr_string_pad_char to set character used for padding * strings to an even number of bytes. * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:11 neelin * Release of minc version 0.2 * * Revision 1.7 94/09/28 10:35:51 neelin * Pre-release * * Revision 1.6 94/04/07 10:05:11 neelin * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs * to that or ACR_OTHER_ERROR. * Added #ifdef lint to DEFINE_ELEMENT. * * Revision 1.5 93/11/26 18:47:48 neelin * Added element copy routine. * * Revision 1.4 93/11/24 11:26:35 neelin * Changed short to unsigned short. * * Revision 1.3 93/11/23 11:36:21 neelin * Changed GLOBAL_ELEMENT macro to allow definition or declaration of * global variables. * * Revision 1.2 93/11/22 13:12:21 neelin * Added Acr_Element_Id code. * * Revision 1.1 93/11/19 12:50:24 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #ifndef _ACR_ELEMENT_H_ #define _ACR_ELEMENT_H_ /* Element type */ typedef struct Acr_Element { int group_id; int element_id; long data_length; char *data_pointer; struct Acr_Element *next; short vr_code; unsigned int is_sequence:1; unsigned int has_variable_length:1; unsigned int has_little_endian_order:1; unsigned int uses_explicit_vr:1; } *Acr_Element; /* Structure for specifying element id's */ typedef struct Acr_Element_Id { int group_id; int element_id; Acr_VR_Type vr_code; } *Acr_Element_Id; /* Macros for creating element id's (class should be nothing or static) */ #ifndef lint #define DEFINE_ELEMENT(class, name, group, element, vr) \ static struct Acr_Element_Id name##_struct = \ {group, element, ACR_VR_##vr}; \ class Acr_Element_Id name = &name##_struct #else #define DEFINE_ELEMENT(class, name, group, element, vr) \ class Acr_Element_Id name = (void *) 0 #endif /* Macro for creating global elements. If GLOBAL_ELEMENT_DEFINITION is defined then we define the variables, otherwise we just declare them */ #ifdef GLOBAL_ELEMENT_DEFINITION # define GLOBAL_ELEMENT(name, group, element, vr) \ DEFINE_ELEMENT(,name, group, element, vr) #else # define GLOBAL_ELEMENT(name, group, element, vr) \ extern Acr_Element_Id name #endif /* Macro for creating global elements for the ACR-NEMA library. If ACR_LIBRARY_GLOBAL_ELEMENT_DEFINITION is defined then we define the variables, otherwise we just declare them */ #ifdef ACR_LIBRARY_GLOBAL_ELEMENT_DEFINITION # define ACRLIB_GLOBAL_ELEMENT(name, group, element, vr) \ DEFINE_ELEMENT(,name, group, element, vr) #else # define ACRLIB_GLOBAL_ELEMENT(name, group, element, vr) \ extern Acr_Element_Id name #endif /* Global element definition for items */ ACRLIB_GLOBAL_ELEMENT(ACR_Sequence_Item, ACR_ITEM_GROUP, ACR_ITEM_TAG, UNKNOWN); /* Functions */ extern Acr_Element acr_create_element(int group_id, int element_id, Acr_VR_Type vr_code, long data_length, char *data_pointer); extern void acr_delete_element(Acr_Element element); extern void acr_delete_element_list(Acr_Element element_list); extern Acr_Element acr_element_list_add(Acr_Element element_list, Acr_Element element); extern void acr_set_element_id(Acr_Element element, int group_id, int element_id); extern void acr_set_element_vr(Acr_Element element, Acr_VR_Type vr_code); extern void acr_set_element_vr_encoding(Acr_Element element, Acr_VR_encoding_type vr_encoding); extern void acr_set_element_byte_order(Acr_Element element, Acr_byte_order byte_order); extern void acr_set_element_variable_length(Acr_Element element, int has_variable_length); extern void acr_set_element_data(Acr_Element element, long data_length, char *data_pointer); extern void acr_set_element_next(Acr_Element element, Acr_Element next); extern int acr_get_element_group(Acr_Element element); extern int acr_get_element_element(Acr_Element element); extern Acr_VR_Type acr_get_element_vr(Acr_Element element); extern Acr_VR_encoding_type acr_get_element_vr_encoding(Acr_Element element); extern int acr_element_is_sequence(Acr_Element element); extern Acr_byte_order acr_get_element_byte_order(Acr_Element element); extern int acr_element_has_variable_length(Acr_Element element); extern long acr_get_element_length(Acr_Element element); extern char *acr_get_element_data(Acr_Element element); extern long acr_get_element_total_length(Acr_Element element, Acr_VR_encoding_type vr_encoding); extern Acr_Element acr_get_element_next(Acr_Element element); extern Acr_Element acr_copy_element(Acr_Element element); extern Acr_Status acr_input_element(Acr_File *afp, Acr_Element *element); extern Acr_Status acr_output_element(Acr_File *afp, Acr_Element element); extern void acr_convert_element_byte_order(Acr_Element element, Acr_byte_order byte_order); extern int acr_match_element_id(Acr_Element_Id elid, Acr_Element element); extern Acr_Element acr_find_element_id(Acr_Element element_list, Acr_Element_Id elid); extern void *acr_memdup(size_t value_size, void *value); extern Acr_Element acr_create_element_short(Acr_Element_Id elid, Acr_Short value); extern Acr_Element acr_create_element_long(Acr_Element_Id elid, Acr_Long value); extern Acr_Element acr_create_element_double(Acr_Element_Id elid, int nvalues, Acr_Double *values); extern Acr_Element acr_create_element_numeric(Acr_Element_Id elid, double value); extern Acr_Element acr_create_element_string(Acr_Element_Id elid, Acr_String value); extern Acr_Element acr_create_element_sequence(Acr_Element_Id elid, Acr_Element itemlist); extern Acr_Short acr_get_element_short(Acr_Element element); extern Acr_Long acr_get_element_long(Acr_Element element); extern double acr_get_element_numeric(Acr_Element element); extern Acr_String acr_get_element_string(Acr_Element element); extern long acr_get_element_short_array(Acr_Element element, long max_values, Acr_Short values[]); extern long acr_get_element_double_array(Acr_Element element, long max_values, Acr_Double values[]); extern int *acr_element_numeric_array_separator(int character); extern int acr_get_element_numeric_array(Acr_Element element, int max_values, double values[]); extern void acr_dump_element_list(FILE *file_pointer, Acr_Element element_list); #endif /* _ACR_ELEMENT_H_ */ minc-2.2.00/conversion/Acr_nema/acr_nema/file_io.h0000644000265600003100000001252312027132657016665 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : file_io.h @DESCRIPTION: Header file for doing io from acr_nema code. @METHOD : @GLOBALS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : * $Log: file_io.h,v $ * Revision 6.4 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.3 2005/03/04 00:08:08 bert * Cleanup headers, mostly by getting rid of the infernal 'public' and using extern instead * * Revision 6.2 2000/05/17 20:17:48 neelin * Added mechanism to allow testing of input streams for more data through * function acr_file_ismore. * This is used in dicom_client_routines to allow asynchronous transfer * of data, with testing for more input done before sending new messages. * Previous use of select for this was misguided, since select may report that * no data is waiting on the file descriptor while data is store in the file * pointer buffer (or Acr file pointer buffer). * * Revision 6.1 1999/10/29 17:51:53 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:14 neelin * Release of minc version 0.2 * * Revision 1.4 94/09/28 10:35:43 neelin * Pre-release * * Revision 1.3 94/04/08 10:32:10 neelin * Fixed io tracing. * * Revision 1.2 93/11/25 10:37:43 neelin * Added file free and ungetc and trace. * * Revision 1.1 93/11/10 10:33:33 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Define constants */ #define ACR_NO_WATCHPOINT LONG_MAX /* Define io routine prototype */ typedef int (*Acr_Io_Routine) (void *io_data, void *buffer, int nbytes); /* Define prototype for io routine that tests for more input */ typedef int (*Acr_Ismore_Function) (void *io_data); /* Structure used for reading and writing in acr_nema routines */ typedef struct { void *io_data; Acr_Io_Routine io_routine; Acr_Ismore_Function ismore_function; int maxlength; /* Maximum length of read request */ unsigned char *start; unsigned char *end; unsigned char *ptr; int length; /* Length of actual data in buffer */ int buffer_length; /* Length of allocated buffer */ int stream_type; int reached_eof; /* TRUE if we have reached end of file */ int do_trace; /* TRUE if file should be traced */ FILE *tracefp; int watchpoint_set; /* TRUE if a watchpoint is set */ long bytes_to_watchpoint; /* number of bytes from start of buffer to watchpoint */ void *client_data; /* Data that can be set by calling routines */ } Acr_File; /* Macros for getting and putting a character */ #define acr_getc(afp) ( ((afp)->ptr < (afp)->end) ? \ *((afp)->ptr++) : \ acr_file_read_more(afp) ) #define acr_putc(c,afp) ( ((afp)->ptr < (afp)->end) ? \ (int) (*((afp)->ptr++) = (unsigned char) (c)) : \ acr_file_write_more(afp, c) ) /* Function definitions */ extern void acr_file_enable_trace(Acr_File *afp); extern void acr_file_disable_trace(Acr_File *afp); extern Acr_File *acr_file_initialize(void *io_data, int maxlength, Acr_Io_Routine io_routine); extern void acr_file_free(Acr_File *afp); extern void acr_file_reset(Acr_File *afp); extern void acr_file_set_ismore_function(Acr_File *afp, Acr_Ismore_Function ismore_function); extern void acr_file_set_eof(Acr_File *afp); extern void acr_file_set_client_data(Acr_File *afp, void *client_data); extern void *acr_file_get_client_data(Acr_File *afp); extern int acr_file_read_more(Acr_File *afp); extern int acr_file_write_more(Acr_File *afp, int character); extern int acr_file_flush(Acr_File *afp); extern int acr_ungetc(int c, Acr_File *afp); extern void *acr_file_get_io_data(Acr_File *afp); extern void acr_set_io_watchpoint(Acr_File *afp, long bytes_to_watchpoint); extern long acr_get_io_watchpoint(Acr_File *afp); extern int acr_file_ismore(Acr_File *afp); extern int acr_stdio_read(void *io_data, void *buffer, int nbytes); extern int acr_stdio_write(void *io_data, void *buffer, int nbytes); extern int acr_stdio_ismore(void *io_data); minc-2.2.00/conversion/Acr_nema/acr_nema/group.h0000644000265600003100000001547012027132657016417 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : group.h @DESCRIPTION: Header file for acr-nema group code @METHOD : @GLOBALS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : * $Log: group.h,v $ * Revision 6.7 2008-08-12 05:00:23 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.6 2006/04/09 15:29:43 bert * Add acr_insert_double() * * Revision 6.5 2005/03/11 22:05:29 bert * Implement _acr_name_proc to allow printing of field names in dump_acr_nema * * Revision 6.4 2005/03/04 00:08:08 bert * Cleanup headers, mostly by getting rid of the infernal 'public' and using extern instead * * Revision 6.3 2001/11/08 14:17:06 neelin * Added acr_test_dicom_file to allow reading of DICOM part 10 format * files. This function also calls acr_test_byte_order to set up the stream * properly and can be used as a direct replacement for that function. * This set of changes does NOT include the ability to write part 10 files. * * Revision 6.2 1999/10/29 17:51:53 neelin * Fixed Log keyword * * Revision 6.1 1998/11/06 19:41:06 neelin * Added functions acr_group_steal_element and acr_find_group. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.2 1997/08/21 13:24:55 neelin * Pre-release * * Revision 4.1 1997/06/17 23:49:08 neelin * Added routines for inserting elements into a group list. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:17 neelin * Release of minc version 0.2 * * Revision 1.6 94/09/28 10:35:52 neelin * Pre-release * * Revision 1.5 93/12/10 09:20:44 neelin * Added acr_find_ routines. * * Revision 1.4 93/11/26 18:48:04 neelin * Added group and group list copy routines. * * Revision 1.3 93/11/24 11:26:38 neelin * Added group list stuff (dump and input). * * Revision 1.2 93/11/22 13:12:41 neelin * Changed to use new Acr_Element_Id stuff. * * Revision 1.1 93/11/19 12:50:32 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #ifndef _ACR_GROUP_H_ #define _ACR_GROUP_H_ 1 /* Group type */ typedef struct Acr_Group { int group_id; int nelements; long implicit_total_length; long explicit_total_length; Acr_Element list_head; Acr_Element list_tail; struct Acr_Group *next; } *Acr_Group; /* Group length element id */ #define ACR_EID_GRPLEN 0 /* Functions */ extern Acr_Group acr_create_group(int group_id); extern void acr_delete_group(Acr_Group group); extern void acr_delete_group_list(Acr_Group group_list); extern Acr_Group acr_copy_group(Acr_Group group); extern Acr_Group acr_copy_group_list(Acr_Group group_list); extern Acr_Status acr_group_insert_element(Acr_Group group, Acr_Element element); extern Acr_Status acr_group_add_element(Acr_Group group, Acr_Element element); extern void acr_group_remove_element(Acr_Group group, int element_id); extern void acr_group_steal_element(Acr_Group group, Acr_Element element); extern void acr_set_group_next(Acr_Group group, Acr_Group next); extern int acr_get_group_group(Acr_Group group); extern Acr_Element acr_get_group_element_list(Acr_Group group); extern long acr_get_group_total_length(Acr_Group group, Acr_VR_encoding_type vr_encoding); extern int acr_get_group_nelements(Acr_Group group); extern Acr_Group acr_get_group_next(Acr_Group group); extern Acr_Status acr_input_group(Acr_File *afp, Acr_Group *group); extern Acr_Status acr_output_group(Acr_File *afp, Acr_Group group); extern Acr_Status acr_input_group_list(Acr_File *afp, Acr_Group *group_list, int max_group_id); extern Acr_Group acr_find_group(Acr_Group group_list, int group_id); extern Acr_Element acr_find_group_element(Acr_Group group_list, Acr_Element_Id elid); extern void acr_dump_group_list(FILE *file_pointer, Acr_Group group_list); extern Acr_Short acr_find_short(Acr_Group group_list, Acr_Element_Id elid, Acr_Short default_value); extern Acr_Long acr_find_long(Acr_Group group_list, Acr_Element_Id elid, Acr_Long default_value); extern int acr_find_int(Acr_Group group_list, Acr_Element_Id elid, int default_value); extern Acr_Double acr_find_double(Acr_Group group_list, Acr_Element_Id elid, Acr_Double default_value); extern Acr_String acr_find_string(Acr_Group group_list, Acr_Element_Id elid, Acr_String default_value); extern Acr_Status acr_insert_element_into_group_list(Acr_Group *group_list, Acr_Element element); extern Acr_Status acr_insert_short(Acr_Group *group_list, Acr_Element_Id elid, Acr_Short value); extern Acr_Status acr_insert_long(Acr_Group *group_list, Acr_Element_Id elid, Acr_Long value); extern Acr_Status acr_insert_double(Acr_Group *group_list, Acr_Element_Id elid, int nvalues, Acr_Double *values); extern Acr_Status acr_insert_numeric(Acr_Group *group_list, Acr_Element_Id elid, double value); extern Acr_Status acr_insert_string(Acr_Group *group_list, Acr_Element_Id elid, Acr_String value); extern Acr_Status acr_insert_sequence(Acr_Group *group_list, Acr_Element_Id elid, Acr_Element itemlist); extern Acr_Status acr_test_dicom_file(Acr_File *afp); typedef char *(*acr_name_proc_t)(unsigned int grp_id, unsigned int el_id); extern acr_name_proc_t _acr_name_proc; #endif /* _ACR_GROUP_H_ */ minc-2.2.00/conversion/Acr_nema/acr_nema/message.h0000644000265600003100000000601312027132657016700 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : message.h @DESCRIPTION: Header file for acr-nema message code @METHOD : @GLOBALS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : * $Log: message.h,v $ * Revision 6.2 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.1 1999/10/29 17:51:54 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:18 neelin * Release of minc version 0.2 * * Revision 1.4 94/09/28 10:35:53 neelin * Pre-release * * Revision 1.3 93/11/24 11:27:10 neelin * Added dump message routine./ * * Revision 1.2 93/11/22 13:12:55 neelin * Changed to use new Acr_Element_Id stuff. * * Revision 1.1 93/11/19 12:50:37 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Group type */ typedef struct Acr_Message { int ngroups; long implicit_total_length; long explicit_total_length; long message_implicit_offset; long message_explicit_offset; Acr_Element message_length_element; Acr_Group list_head; Acr_Group list_tail; } *Acr_Message; /* Functions */ public Acr_Message acr_create_message(void); public void acr_delete_message(Acr_Message message); public void acr_message_reset(Acr_Message message); public void acr_message_add_group(Acr_Message message, Acr_Group group); public void acr_message_add_group_list(Acr_Message message, Acr_Group group_list); public Acr_Group acr_get_message_group_list(Acr_Message message); public long acr_get_message_total_length(Acr_Message message, Acr_VR_encoding_type vr_encoding); public int acr_get_message_ngroups(Acr_Message message); public Acr_Status acr_input_message(Acr_File *afp, Acr_Message *message); public Acr_Status acr_output_message(Acr_File *afp, Acr_Message message); public void acr_dump_message(FILE *file_pointer, Acr_Message message); minc-2.2.00/conversion/Acr_nema/acr_nema/value_repr.h0000644000265600003100000000530412027132657017422 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : value_repr.h @DESCRIPTION: Header file for acr-nema VR code @METHOD : @GLOBALS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : * $Log: value_repr.h,v $ * Revision 6.4 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.3 2005/03/04 00:08:08 bert * Cleanup headers, mostly by getting rid of the infernal 'public' and using extern instead * * Revision 6.2 2000/08/16 15:53:46 neelin * Added VR type UN (unknown) which has a length field similar to OB. * * Revision 6.1 1999/10/29 17:51:55 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 1.2 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 1.1 1997/02/11 16:23:43 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ typedef enum { ACR_VR_UNKNOWN, ACR_VR_AE, ACR_VR_AS, ACR_VR_AT, ACR_VR_CS, ACR_VR_DA, ACR_VR_DS, ACR_VR_DT, ACR_VR_FL, ACR_VR_FD, ACR_VR_IS, ACR_VR_LO, ACR_VR_LT, ACR_VR_OB, ACR_VR_OW, ACR_VR_PN, ACR_VR_SH, ACR_VR_SL, ACR_VR_SQ, ACR_VR_SS, ACR_VR_ST, ACR_VR_TM, ACR_VR_UI, ACR_VR_UL, ACR_VR_US, ACR_VR_UN, ACR_VR_NUM_TYPES } Acr_VR_Type; /* Function prototypes */ extern char *acr_get_vr_name(Acr_VR_Type vr_code); extern int acr_test_vr_name(char *vr_name); extern Acr_VR_Type acr_lookup_vr_name(char *vr_name); extern double acr_get_numeric_vr(Acr_VR_Type vr_code, Acr_byte_order byte_order, char *data, long data_length); extern char *acr_get_string_vr(Acr_VR_Type vr_code, Acr_byte_order byte_order, char *data, long data_length); minc-2.2.00/conversion/Acr_nema/acr_nema.h0000644000265600003100000000624412027132657015262 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : acr_nema.h @DESCRIPTION: Header file for ACR-NEMA code. @METHOD : @GLOBALS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : * $Log: acr_nema.h,v $ * Revision 6.4 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.3 2005/02/16 19:22:32 bert * Autoconfiscation * * Revision 6.2 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.1 1999/10/29 17:51:50 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.1 1997/09/08 21:53:14 neelin * Added dicom_client_routines. * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:08 neelin * Release of minc version 0.2 * * Revision 1.6 94/09/28 10:35:51 neelin * Pre-release * * Revision 1.5 94/09/23 16:42:37 neelin * Changed acr_nema_io to acr_io and acr_nema_test to acr_test. * * Revision 1.4 94/01/06 13:31:27 neelin * Changed acr_need_invert to a public function. * * Revision 1.3 93/12/08 09:07:02 neelin * * Revision 1.2 93/11/24 11:26:09 neelin * Added TRUE and FALSE. * * Revision 1.1 93/11/19 12:49:34 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Define constants */ #ifndef public # define public #endif #ifndef private # define private static #endif #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif /* Include files */ #include #include #include #include #include #include #include #include /* these are pinched from minc_def.h */ #define MALLOC(size) ((void *) malloc(size)) #define FREE(ptr) free(ptr) #define REALLOC(ptr, size) ((void *) realloc(ptr, size)) #define CALLOC(nelem, elsize) ((void *) calloc(nelem, elsize)) minc-2.2.00/conversion/Acr_nema/acr_io.c0000644000265600003100000012406612027132657014747 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : acr_io.c @DESCRIPTION: Routines for doing basic acr_nema operations (reading and writing an element). @METHOD : @GLOBALS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : * $Log: acr_io.c,v $ * Revision 6.8 2008-08-12 05:00:22 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.7 2005/03/04 00:15:14 bert * Lose public and private keywords; change acr_read_one_element to assume implicit VR format for special sequence delimiters (group 0xfffe) * * Revision 6.6 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.5 2000/08/16 15:53:46 neelin * Added VR type UN (unknown) which has a length field similar to OB. * * Revision 6.4 2000/05/01 17:54:02 neelin * Improved testing of input stream to figure out byte order for both * implicit and expicit VR. * * Revision 6.3 2000/04/28 15:03:10 neelin * Added support for ignoring non-fatal protocol errors (cases where redundant * information is inconsistent). In particular, it is possible to ignore * differences between the group length element and the true group length. * * Revision 6.2 1999/10/29 17:51:49 neelin * Fixed Log keyword * * Revision 6.1 1999/10/27 20:13:15 neelin * Generalized acr_test_byte_order to recognize groups without a length element. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.1 1997/09/08 21:53:31 neelin * Added status ACR_CONNECTION_TIMEDOUT. * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.1 1997/07/10 17:14:38 neelin * Added more status codes and function to return status string. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.1 1995/02/08 21:16:06 neelin * Changes to make irix 5 lint happy. * * Revision 2.0 1994/09/28 10:36:06 neelin * Release of minc version 0.2 * * Revision 1.9 94/09/28 10:35:39 neelin * Pre-release * * Revision 1.8 94/09/23 16:42:35 neelin * Changed acr_nema_io to acr_io and acr_nema_test to acr_test. * * Revision 1.7 94/05/18 08:47:43 neelin * Changed some ACR_OTHER_ERROR's to ACR_ABNORMAL_END_OF_OUTPUT. * * Revision 1.6 94/04/07 10:03:40 neelin * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs * to that or ACR_OTHER_ERROR. * Added #ifdef lint to DEFINE_ELEMENT. * * Revision 1.5 94/01/06 13:30:57 neelin * Changed acr_need_invert to a public function. * * Revision 1.4 93/11/30 12:18:34 neelin * Handle MALLOC returning NULL because of extremely large data element length. * * Revision 1.3 93/11/25 10:34:34 neelin * Added routine to test byte-ordering of input. * * Revision 1.2 93/11/24 11:24:48 neelin * Changed short to unsigned short. * * Revision 1.1 93/11/19 12:47:35 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include /* Define constants */ #if (!defined(TRUE) || !defined(FALSE)) # define TRUE 1 # define FALSE 0 #endif #define ACR_BYTE_ORDER_DEFAULT ACR_LITTLE_ENDIAN #define ACR_VR_ENCODING_DEFAULT ACR_IMPLICIT_VR /* Define types */ typedef struct { Acr_byte_order byte_order; Acr_VR_encoding_type vr_encoding; int ignore_nonfatal_protocol_errors; } *Data_Info; /* Private functions */ static int test_vr(char vr_to_test[2], char *vr_list[]); static int is_sequence_vr(char vr_to_test[2]); static int is_special_vr(char vr_to_test[2]); static Data_Info get_data_info(Acr_File *afp); static void invert_values(Acr_byte_order byte_order, long nvals, size_t value_size, void *input_value, void *mach_value); /* Macros */ #define SIZEOF_ARRAY(a) (sizeof(a)/sizeof(a[0])) /* ----------------------------- MNI Header ----------------------------------- @NAME : is_sequence_vr is_special_vr @INPUT : vr_to_test - Two character array containing value representation @OUTPUT : (none) @RETURNS : TRUE if vr is in appropriate list @DESCRIPTION: These routines test VR against various lists. is_sequence_vr checks for a sequence and is_special_vr checks for a VR with different fields @METHOD : @GLOBALS : @CALLS : @CREATED : January 29, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int test_vr(char vr_to_test[2], char *vr_list[]) { int found_special, i; found_special = FALSE; for (i=0; vr_list[i] != NULL; i++) { if ((vr_to_test[0] == vr_list[i][0]) && (vr_to_test[1] == vr_list[i][1])) { found_special = TRUE; break; } } return found_special; } static int is_sequence_vr(char vr_to_test[2]) { static char *sequence_vrs[] = {"SQ", NULL}; return test_vr(vr_to_test, sequence_vrs); } static int is_special_vr(char vr_to_test[2]) { static char *special_vrs[] = {"OB", "OW", "SQ", "UN", NULL}; return test_vr(vr_to_test, special_vrs); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_data_info @INPUT : afp - i/o stream @OUTPUT : (none) @RETURNS : Pointer to data info @DESCRIPTION: Checks that the i/o stream has the appropriate structure as client data and returns a pointer to the structure. @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static Data_Info get_data_info(Acr_File *afp) { Data_Info data_info; data_info = acr_file_get_client_data(afp); if (data_info == NULL) { data_info = MALLOC(sizeof(*data_info)); data_info->byte_order = ACR_BYTE_ORDER_DEFAULT; data_info->vr_encoding = ACR_VR_ENCODING_DEFAULT; data_info->ignore_nonfatal_protocol_errors = FALSE; acr_file_set_client_data(afp, (void *) data_info); } return data_info; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_byte_order @INPUT : afp - i/o stream byte_order - ACR_LITTLE_ENDIAN or ACR_BIG_ENDIAN. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Allows a user to set the byte ordering for an i/o stream. @METHOD : @GLOBALS : @CALLS : @CREATED : January 29, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_byte_order(Acr_File *afp, Acr_byte_order byte_order) { Data_Info data_info; /* Get data info pointer */ data_info = get_data_info(afp); /* Set the byte ordering */ data_info->byte_order = byte_order; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_byte_order @INPUT : afp - i/o stream @OUTPUT : (none) @RETURNS : Byte ordering of stream @DESCRIPTION: Allows one to get the byte ordering for an i/o stream. @METHOD : @GLOBALS : @CALLS : @CREATED : January 29, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_byte_order acr_get_byte_order(Acr_File *afp) { Data_Info data_info; /* Get data info pointer */ data_info = get_data_info(afp); /* Return the byte ordering */ return data_info->byte_order; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_machine_byte_order @INPUT : (none) @OUTPUT : (none) @RETURNS : Byte ordering for this machine. @DESCRIPTION: Gets the byte ordering for the machine on which the program is running. @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_get_machine_byte_order(void) { int dummy = 1; char *ptr = (char *) &dummy; if ((int) ptr[0] == 1) return ACR_LITTLE_ENDIAN; else if ((int) ptr[sizeof(int)-1] == 1) return ACR_BIG_ENDIAN; else { (void) fprintf(stderr, "Internal error: Cannot figure out machine byte order!\n"); exit(EXIT_FAILURE); return ACR_BIG_ENDIAN; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_need_invert @INPUT : byte_order - byte_order of foreign data @OUTPUT : (none) @RETURNS : TRUE if need to invert shorts and longs @DESCRIPTION: Indicates whether we need to swap bytes for shorts and longs to convert between the given byte ordering and the machine byte ordering. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : January 29, 1997 (P.N.) ---------------------------------------------------------------------------- */ int acr_need_invert(Acr_byte_order byte_order) { return (acr_get_machine_byte_order() != byte_order); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_vr_encoding @INPUT : afp - i/o stream vr_encoding - ACR_EXPLICIT_VR or ACR_IMPLICIT_VR @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Allows a user to set the vr encoding type for an i/o stream. @METHOD : @GLOBALS : @CALLS : @CREATED : January 29, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_vr_encoding(Acr_File *afp, Acr_VR_encoding_type vr_encoding) { Data_Info data_info; /* Get data info pointer */ data_info = get_data_info(afp); /* Set the VR encoding */ data_info->vr_encoding = vr_encoding; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_vr_encoding @INPUT : afp - i/o stream @OUTPUT : (none) @RETURNS : VR encoding of stream @DESCRIPTION: Allows one to get the vr encoding for an i/o stream @METHOD : @GLOBALS : @CALLS : @CREATED : January 29, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_VR_encoding_type acr_get_vr_encoding(Acr_File *afp) { Data_Info data_info; /* Get data info pointer */ data_info = get_data_info(afp); /* Return the VR encoding */ return data_info->vr_encoding; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_ignore_errors @INPUT : afp - i/o stream ignore_nonfatal_protocol_errors - if TRUE then non-fatal protocol errors will be ignored @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Allows a user to indicate whether to ignore protocol errors that can be ignored. @METHOD : @GLOBALS : @CALLS : @CREATED : April 28, 2000 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_ignore_errors(Acr_File *afp, int ignore_nonfatal_protocol_errors) { Data_Info data_info; /* Get data info pointer */ data_info = get_data_info(afp); /* Set the flag */ data_info->ignore_nonfatal_protocol_errors = ignore_nonfatal_protocol_errors; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_ignore_protocol_errors @INPUT : afp - i/o stream @OUTPUT : (none) @RETURNS : TRUE if stream is set to ignore nonfatal protocol errors @DESCRIPTION: Allows one to get the ignore errors flag for a stream @METHOD : @GLOBALS : @CALLS : @CREATED : April 28, 2000 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_ignore_protocol_errors(Acr_File *afp) { Data_Info data_info; /* Get data info pointer */ data_info = get_data_info(afp); /* Return the VR encoding */ return data_info->ignore_nonfatal_protocol_errors; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_reverse_byte_order @INPUT : nvals - number of values to invert value_size - length of each value input_values - pointer to array of input values @OUTPUT : output_values - pointer to array of inverted values or NULL @RETURNS : (nothing) @DESCRIPTION: Reverses byte-ordering of an array of values. Will reverse an array in place if input_values and output_values point to the same array or if output_values is NULL. @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_reverse_byte_order(long nvals, size_t value_size, void *input_values, void *output_values) { long i, jlow, jhigh; char *ptr1, *ptr2, v0, v1; int nbytes; /* Get data pointers and check whether output_values is NULL */ ptr1 = (char *) input_values; ptr2 = (char *) output_values; if (ptr2 == NULL) ptr2 = ptr1; /* Copy values from both ends at the same time and stop in the middle */ nbytes = (value_size+1)/2; for (i=0; i= nbytes_to_skip) { return ACR_OK; } else if (acr_get_io_watchpoint(afp) <= 0) { return ACR_REACHED_WATCHPOINT; } else if (i == 0) { return ACR_END_OF_INPUT; } else { return ACR_ABNORMAL_END_OF_INPUT; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_read_buffer @INPUT : afp nbytes_to_read @OUTPUT : buffer nbytes_read - if NULL, then this value is ignored, otherwise the number of bytes actually read in is returned. @RETURNS : Input status. If an error occurs on the first byte, then ACR_END_OF_INPUT is returned, if an error occurs elsewhere, then ACR_ABNORMAL_END_OF_INPUT is returned, otherwise ACR_OK is returned. @DESCRIPTION: Reads in a buffer of data and optionally returns the number of bytes read @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_read_buffer(Acr_File *afp, unsigned char buffer[], long nbytes_to_read, long *nbytes_read) { long i; int ch; for (i=0; i < nbytes_to_read; i++) { ch = acr_getc(afp); if (ch == EOF) { break; } buffer[i] = (unsigned char) ch; } /* Save the number of bytes read */ if (nbytes_read != NULL) { *nbytes_read = i; } /* Return the status */ if (i >= nbytes_to_read) { return ACR_OK; } else if (acr_get_io_watchpoint(afp) <= 0) { return ACR_REACHED_WATCHPOINT; } else if (i == 0) { return ACR_END_OF_INPUT; } else { return ACR_ABNORMAL_END_OF_INPUT; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_unget_buffer @INPUT : afp nbytes_to_unget buffer @OUTPUT : (none) @RETURNS : Unget status. @DESCRIPTION: Puts a buffer of data back into the input stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_unget_buffer(Acr_File *afp, unsigned char buffer[], long nbytes_to_unget) { long i; for (i=nbytes_to_unget-1; i >= 0; i--) { if (acr_ungetc((int) buffer[i], afp) == EOF) { break; } } /* Return the status */ if (i >= 0) { return ACR_IO_ERROR; } else { return ACR_OK; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_write_buffer @INPUT : afp nbytes_to_write buffer @OUTPUT : nbytes_written @RETURNS : Output status. @DESCRIPTION: Writes out a buffer of data and optionally returns the number of bytes written @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_write_buffer(Acr_File *afp, unsigned char buffer[], long nbytes_to_write, long *nbytes_written) { long i; for (i=0; i < nbytes_to_write; i++) { if (acr_putc(buffer[i], afp) == EOF) { break; } } /* Save the number of bytes written */ if (nbytes_written != NULL) { *nbytes_written = i; } /* Return the status */ if (i < nbytes_to_write) { return ACR_ABNORMAL_END_OF_OUTPUT; } else { return ACR_OK; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_test_byte_order @INPUT : afp @OUTPUT : (none) @RETURNS : status. @DESCRIPTION: Tests input for byte ordering to use. The test is done by looking at the length of the first element. First a test is done for implicit VR, assuming that the length of the first element is less than 64K and greater than zero, and we try the two possible byte orders. If the VR encoding is explicit, then we have two shortwords (2-bytes), both of which are non-zero and the longword (4 bytes) will be greater than 64K. In this case, we test the 2-byte length looking for a length that is less than 256 bytes. If that fails, than we revert to the original byte order. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : January 29, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Status acr_test_byte_order(Acr_File *afp) { long buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT+ACR_SIZEOF_LONG]; Acr_Long data_length; Acr_Short data_length2; Acr_Status status; Acr_byte_order byte_order, old_byte_order; #define ACR_TEST_MAX USHRT_MAX #define ACR_TEST_MAX2 UCHAR_MAX /* Save old byte ordering */ old_byte_order = acr_get_byte_order(afp); /* Read in group id, element id and length of data */ status = acr_read_buffer(afp, buffer, SIZEOF_ARRAY(buffer), &buflen); if (status != ACR_OK) return status; /* Put the characters back */ status = acr_unget_buffer(afp, buffer, buflen); if (status != ACR_OK) return status; /* Test data length (the first element should be a group length). Try big-endian ordering first. */ byte_order = ACR_BIG_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_long(byte_order, 1, &buffer[2*ACR_SIZEOF_SHORT], &data_length); /* If that doesn't work, set it to little-endian ordering. */ if (data_length >= ACR_TEST_MAX) { byte_order = ACR_LITTLE_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_long(byte_order, 1, &buffer[2*ACR_SIZEOF_SHORT], &data_length); } /* If one of them worked, then it means that we have implicit VR encoding since we didn't look for a VR field */ if (data_length < ACR_TEST_MAX) { acr_set_vr_encoding(afp, ACR_IMPLICIT_VR); } /* Otherwise we probably have explicit vr encoding. */ else { acr_set_vr_encoding(afp, ACR_EXPLICIT_VR); /* Check the length in this case to see if it small. The default will be little endian. */ byte_order = ACR_BIG_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_short(byte_order, 1, &buffer[3*ACR_SIZEOF_SHORT], &data_length2); if (data_length2 >= ACR_TEST_MAX2) { byte_order = ACR_LITTLE_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_short(byte_order, 1, &buffer[3*ACR_SIZEOF_SHORT], &data_length2); } if (data_length2 >= ACR_TEST_MAX2) { /* If we get here, we have completely failed to make sense of * the byte ordering. */ acr_set_byte_order(afp, old_byte_order); } } return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_copy_file_encoding @INPUT : afp1 - source stream @OUTPUT : afp2 - target stream @RETURNS : (nothing) @DESCRIPTION: Copies the byte ordering and VR encoding from one i/o stream to another. @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_copy_file_encoding(Acr_File *afp1, Acr_File *afp2) { acr_set_byte_order(afp2, acr_get_byte_order(afp1)); acr_set_vr_encoding(afp2, acr_get_vr_encoding(afp1)); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_header_size @INPUT : vr_name - 2-letter name of Vr vr_encoding - ACR_EXPLICIT_VR or ACR_IMPLICIT_VR @OUTPUT : (none) @RETURNS : length of header @DESCRIPTION: Calculates the length of the element header (excluding data) @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_get_element_header_size(char vr_name[2], Acr_VR_encoding_type vr_encoding) { int length; length = 2*ACR_SIZEOF_SHORT + ACR_SIZEOF_LONG; if ((vr_encoding == ACR_EXPLICIT_VR) && is_special_vr(vr_name)) { length += ACR_SIZEOF_LONG; } return length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_peek_at_next_element_id @INPUT : afp - Acr_File pointer from which to read @OUTPUT : group_id element_id @RETURNS : Status @DESCRIPTION: Peeks ahead to get the group and element ids of the next element. The file position is restored. If a read error occurs, then group_id and element_id are set to INT_MIN and the status is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : February 5, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_peek_at_next_element_id(Acr_File *afp, int *group_id, int *element_id) { long buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT]; Acr_Short svalue; Acr_Status status, status2; Acr_byte_order byte_order; /* Set default values */ status = ACR_OK; *group_id = INT_MIN; *element_id = INT_MIN; /* Read in the values */ status = acr_read_buffer(afp, buffer, SIZEOF_ARRAY(buffer), &buflen); /* Put them back */ status2 = acr_unget_buffer(afp, buffer, buflen); if (status == ACR_OK) status = status2; /* Check for input error */ if (status != ACR_OK) return status; /* Get the id's */ byte_order = acr_get_byte_order(afp); acr_get_short(byte_order, 1, &buffer[0], &svalue); *group_id = (int)svalue; acr_get_short(byte_order, 1, &buffer[ACR_SIZEOF_SHORT], &svalue); *element_id = (int)svalue; return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_read_one_element @INPUT : afp - Acr_File pointer from which to read @OUTPUT : group_id - ACR-NEMA group id element_id - ACR-NEMA element id vr_name - 2 character string giving value representation. Two NULs are returned if VR is unknown. data_length - length of data to follow. Value ACR_VARIABLE_LENGTH is returned for undefined length elements in which case the data portion is not read in. data_pointer - pointer to data. Space is allocated by this routine. One additional byte is allocated and set to zero so that the data can be treated as a string. If a sequence is encountered, then NULL is returned. @RETURNS : Status. @DESCRIPTION: Routine to read in one ACR-NEMA element. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : January 29, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Status acr_read_one_element(Acr_File *afp, int *group_id, int *element_id, char vr_name[], long *data_length, char **data_pointer) { long buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT+ACR_SIZEOF_LONG]; Acr_Short grpid, elid, sval; Acr_Long datalen; size_t size_allocated; int offset; Acr_byte_order byte_order; Acr_Status status; /* Get byte ordering */ byte_order = acr_get_byte_order(afp); /* Read in group id, element id and length of data */ status = acr_read_buffer(afp, buffer, SIZEOF_ARRAY(buffer), &buflen); if (status != ACR_OK) return status; offset = 0; acr_get_short(byte_order, 1, &buffer[offset], &grpid); offset += ACR_SIZEOF_SHORT; *group_id = (int)grpid; acr_get_short(byte_order, 1, &buffer[offset], &elid); offset += ACR_SIZEOF_SHORT; *element_id = (int)elid; /* Look for VR and length of data */ if (grpid == ACR_ITEM_GROUP || acr_get_vr_encoding(afp) == ACR_IMPLICIT_VR) { vr_name[0] = '\0'; vr_name[1] = '\0'; acr_get_long(byte_order, 1, &buffer[offset], &datalen); offset += ACR_SIZEOF_LONG; } else { vr_name[0] = buffer[offset++]; vr_name[1] = buffer[offset++]; acr_get_short(byte_order, 1, &buffer[offset], &sval); offset += ACR_SIZEOF_SHORT; datalen = (Acr_Long)sval; } /* Read in length for special VR's */ if (is_special_vr(vr_name)) { status = acr_read_buffer(afp, buffer, (long) ACR_SIZEOF_LONG, NULL); if (status != ACR_OK) return ACR_ABNORMAL_END_OF_INPUT; acr_get_long(byte_order, 1, &buffer[0], &datalen); } /* Check for undefined length */ if (datalen == ACR_UNDEFINED_ELEMENT_LENGTH) { *data_length = ACR_VARIABLE_LENGTH; *data_pointer = NULL; return ACR_OK; } *data_length = (long)datalen; /* Check for sequence VR */ if (is_sequence_vr(vr_name)) { *data_pointer = NULL; return ACR_OK; } /* Allocate space for the data and null-terminate it */ size_allocated = *data_length + 1; *data_pointer = MALLOC(size_allocated); if (*data_pointer == NULL) { *data_length = 0; size_allocated = *data_length + 1; *data_pointer = MALLOC(size_allocated); } (*data_pointer)[*data_length] = '\0'; /* Read in the data */ status = acr_read_buffer(afp, (unsigned char *) *data_pointer, *data_length, NULL); if (status != ACR_OK) { FREE(*data_pointer); return ACR_ABNORMAL_END_OF_INPUT; } return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_write_one_element @INPUT : afp - Acr_File pointer from which to read group_id - ACR-NEMA group id element_id - ACR-NEMA element id vr_name - 2 character string giving value representation. It is an error to pass in two NULs if explicit VR is used (ACR_NO_VR_SPECIFIED is returned). data_length - length of data to follow. If set to ACR_VARIABLE_LENGTH, then the data portion is not written out. data_pointer - pointer to data. If NULL, then no data is written. @OUTPUT : (nothing) @RETURNS : Status. @DESCRIPTION: Routine to write out one ACR-NEMA element. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : January 29, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Status acr_write_one_element(Acr_File *afp, int group_id, int element_id, char vr_name[], long data_length, char *data_pointer) { long buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT+2*ACR_SIZEOF_LONG]; Acr_Short grpid, elid, sval; Acr_Long datalen; int offset; Acr_byte_order byte_order; Acr_Status status; buflen = sizeof(buffer)/sizeof(buffer[0]) - ACR_SIZEOF_LONG; /* Get byte ordering */ byte_order = acr_get_byte_order(afp); /* Get the group id and element id */ offset = 0; grpid = (Acr_Short) group_id; acr_put_short(byte_order, 1, &grpid, &buffer[offset]); offset += ACR_SIZEOF_SHORT; elid = (Acr_Short) element_id; acr_put_short(byte_order, 1, &elid, &buffer[offset]); offset += ACR_SIZEOF_SHORT; /* Check data length */ if ((Acr_Long)data_length == ACR_VARIABLE_LENGTH) datalen = ACR_UNDEFINED_ELEMENT_LENGTH; else datalen = (Acr_Long)data_length; /* Check whether we need VR */ if (acr_get_vr_encoding(afp) == ACR_IMPLICIT_VR) { acr_put_long(byte_order, 1, &datalen, &buffer[offset]); offset += ACR_SIZEOF_LONG; } else { if (vr_name[0] == '\0') return ACR_NO_VR_SPECIFIED; buffer[offset++] = vr_name[0]; buffer[offset++] = vr_name[1]; if (!is_special_vr(vr_name)) { sval = (Acr_Short) datalen; acr_put_short(byte_order, 1, &sval, &buffer[offset]); offset += ACR_SIZEOF_SHORT; } else { sval = 0; acr_put_short(byte_order, 1, &sval, &buffer[offset]); offset += ACR_SIZEOF_SHORT; acr_put_long(byte_order, 1, &datalen, &buffer[offset]); offset += ACR_SIZEOF_LONG; buflen += ACR_SIZEOF_LONG; } } /* Write it out */ status = acr_write_buffer(afp, buffer, buflen, NULL); if (status != ACR_OK) return status; if ((data_length == ACR_VARIABLE_LENGTH) || (data_pointer == NULL)) { return ACR_OK; } /* Write out the data */ status = acr_write_buffer(afp, (unsigned char *) data_pointer, data_length, NULL); if (status != ACR_OK) return status; return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_status_string @INPUT : status - status code to look up @OUTPUT : (nothing) @RETURNS : Pointer to string describing status. @DESCRIPTION: Routine to get a string that describes a status value. @METHOD : @GLOBALS : @CALLS : @CREATED : July 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ char *acr_status_string(Acr_Status status) { char *status_string; switch (status) { case ACR_OK: status_string = "No error"; break; case ACR_END_OF_INPUT: status_string = "End of input"; break; case ACR_PROTOCOL_ERROR: status_string = "Protocol error"; break; case ACR_OTHER_ERROR: status_string = "Other error"; break; case ACR_ABNORMAL_END_OF_INPUT: status_string = "Abnormal end of input"; break; case ACR_HIGH_LEVEL_ERROR: status_string = "High-level error"; break; case ACR_ABNORMAL_END_OF_OUTPUT: status_string = "Abnormal end of output"; break; case ACR_REACHED_WATCHPOINT: status_string = "Reached watchpoint"; break; case ACR_IO_ERROR: status_string = "I/O error"; break; case ACR_NO_VR_SPECIFIED: status_string = "VR not specified on output"; break; case ACR_PDU_UID_TOO_LONG: status_string = "Input PDU UID too long"; break; case ACR_CONNECTION_TIMEDOUT: status_string = "Connection timed out"; break; default: status_string = "Unknown status"; break; } return status_string; } minc-2.2.00/conversion/Acr_nema/dicom_client_routines.c0000644000265600003100000015274212027132657020076 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_client_routines.c @DESCRIPTION: High-level routines to simplify the job of connecting to a dicom server. @GLOBALS : @CREATED : May 6, 1997 (Peter Neelin) @MODIFIED : * $Log: dicom_client_routines.c,v $ * Revision 6.24 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.23 2008/01/17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.22 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.21 2005/02/16 19:22:32 bert * Autoconfiscation * * Revision 6.20 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.19 2001/03/19 18:31:55 neelin * Modifications to allow opening a stream to stdout (with no input) so * that a dicom stream can be captured. * * Revision 6.18 2000/10/03 14:01:24 neelin * Changed inclusion of bstring.h to happen only on SGIs, since linux also has * bcopy, etc. in string.h. * * Revision 6.17 2000/09/29 15:06:47 neelin * Fixed conversion of port string to number so that it is in network byte * order even on little-endian machines (linux PC). * * Revision 6.16 2000/05/24 14:31:05 neelin * Modified acr_transmit_group_list to remove elements that have been added * so that the group_list is returned unchanged. * * Revision 6.15 2000/05/17 20:17:46 neelin * Added mechanism to allow testing of input streams for more data through * function acr_file_ismore. * This is used in dicom_client_routines to allow asynchronous transfer * of data, with testing for more input done before sending new messages. * Previous use of select for this was misguided, since select may report that * no data is waiting on the file descriptor while data is store in the file * pointer buffer (or Acr file pointer buffer). * * Revision 6.14 1999/10/29 17:51:50 neelin * Fixed Log keyword * * Revision 6.13 1998/11/16 19:35:51 neelin * Added include for compilation under SunOS. * * Revision 6.12 1998/11/13 15:55:27 neelin * Modifications to support asynchronous transfers. * * Revision 6.11 1998/04/01 20:56:58 neelin * Added code to set socket buffer size so that things will go faster * under SunOS. * * Revision 6.10 1998/03/23 20:22:56 neelin * Removed unnecessary include. * * Revision 6.9 1998/03/23 20:17:04 neelin * Moved some general-purpose functions to dicom_network.c. * * Revision 6.8 1998/03/17 17:05:16 neelin * Set default maximum length to 1MB for servers that do not handle * length 0 (unlimited). * * Revision 6.7 1998/02/20 17:28:42 neelin * Removed unused variables. * * Revision 6.6 1998/02/20 17:24:41 neelin * In client routines, fd must be dup'ed before fdopen or problems may * occur reading and writing to 2 file pointers that open the same descriptor. * * Revision 6.4 1997/10/20 23:22:38 neelin * Added routine acr_dicom_close_no_release to close a connection that does * not have an association. * * Revision 6.3 1997/10/20 22:52:46 neelin * Added support for implementation user information in association request. * * Revision 6.2 1997/10/20 21:46:02 neelin * Delete answering message when making association. * * Revision 6.1 1997/09/15 16:50:59 neelin * Separated out connection timeouts from i/o timeouts and added functions * to change them. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 1.2 1997/09/11 17:19:49 neelin * Modified creation of uids. Replaced cftime with strftime. * * Revision 1.1 1997/09/08 21:52:21 neelin * Initial revision * * Revision 1.4 1997/07/11 17:35:58 neelin * Changed around send and receive routines for data once again. * * Revision 1.3 1997/07/11 13:55:41 neelin * Fixed handling of message ids. * * Revision 1.2 1997/07/11 13:23:37 neelin * Made changes so that code will compile on sun OS. * Separated out receive_reply from send_group_list. * * Revision 1.1 1997/07/10 17:39:51 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef sgi #include #endif #include #include #include #include /* Constants */ #ifndef public # define public #endif #ifndef private # define private static #endif #ifndef INADDR_NONE # define INADDR_NONE 0xffffffff #endif /* Dicom definitions */ #define ACR_IMPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2" #define ACR_EXPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2.1" #define ACR_EXPLICIT_VR_BIG_END_UID "1.2.840.10008.1.2.2" #define ACR_APPLICATION_CONTEXT_UID "1.2.840.10008.3.1.1.1" #define ACR_C_STORE_RQ 0x0001 #define ACR_C_STORE_RSP 0x8001 #define ACR_ASSOC_RJ_CALLED_AP_TITLE_UNREC 7 #define ACR_ASSOC_RJ_NO_REASON 1 #define ACR_ASSOC_RJ_PERM 1 #define ACR_ASSOC_RJ_USER 1 #define ACR_ASSOC_PR_CN_ACCEPT 0 #define ACR_ASSOC_PR_CN_REJECT 1 #define ACR_PDU_ITEM_USER_INFORMATION 0x50 #define ACR_MESSAGE_GID 0 #define ACR_SUCCESS 0x0000 DEFINE_ELEMENT(static, ACR_Affected_SOP_class_UID , 0x0000, 0x0002, UI); DEFINE_ELEMENT(static, ACR_Command , 0x0000, 0x0100, US); DEFINE_ELEMENT(static, ACR_Message_id , 0x0000, 0x0110, US); DEFINE_ELEMENT(static, ACR_Message_id_brt , 0x0000, 0x0120, US); DEFINE_ELEMENT(static, ACR_Priority , 0x0000, 0x0700, US); DEFINE_ELEMENT(static, ACR_Dataset_type , 0x0000, 0x0800, US); DEFINE_ELEMENT(static, ACR_Status , 0x0000, 0x0900, US); DEFINE_ELEMENT(static, ACR_Affected_SOP_instance_UID , 0x0000, 0x1000, UI); #if 0 DEFINE_ELEMENT(static, ACR_Move_originator_AE_title , 0x0000, 0x1031, AE); #endif DEFINE_ELEMENT(static, ACR_SOP_class_UID , 0x0008, 0x0016, UI); DEFINE_ELEMENT(static, ACR_SOP_instance_UID , 0x0008, 0x0018, UI); DEFINE_ELEMENT(static, ACR_Study_instance_UID , 0x0020, 0x000d, UI); DEFINE_ELEMENT(static, ACR_Series_instance_UID , 0x0020, 0x000e, UI); DEFINE_ELEMENT(static, ACR_Image_type , 0x0008, 0x0008, CS); DEFINE_ELEMENT(static, ACR_Sequence_variant , 0x0018, 0x0021, CS); DEFINE_ELEMENT(static, ACR_Image_position , 0x0020, 0x0032, DS); DEFINE_ELEMENT(static, ACR_Image_orientation , 0x0020, 0x0037, DS); DEFINE_ELEMENT(static, ACR_Frame_of_reference_UID , 0x0020, 0x0052, UI); DEFINE_ELEMENT(static, ACR_Samples_per_pixel , 0x0028, 0x0002, US); DEFINE_ELEMENT(static, ACR_Photometric_interpretation , 0x0028, 0x0004, CS); /* Minimum socket buffer size that we would like to have for TCP connections */ #define MIN_SOCK_BUFLEN (50*1024) /* Default values for timeouts and outstanding responses */ #define DEFAULT_TIMEOUT (60*2) #define DEFAULT_INITIAL_TIMEOUT (10) #define DEFAULT_MAX_OUTSTANDING (-1) /* Typedefs */ typedef struct { int timeout_length; int max_outstanding_responses; int last_message_id; int last_answered_id; } Dicom_client_data; /* Globals for handling connection timeouts */ static int Initial_timeout_length = DEFAULT_INITIAL_TIMEOUT; static int Connection_timeout = FALSE; static Acr_File *Alarmed_afp = NULL; /* Private functions */ private Dicom_client_data *get_client_data_ptr(Acr_File *afp); private Acr_Message compose_assoc_request(char *called_ae, char *calling_ae, char *abstract_syntax_list[], char *transfer_syntax_list[]); private int check_reply(Acr_Message message, int *presentation_context_id, char **transfer_syntax, long *maximum_length); private Acr_Status receive_message(Acr_File *afpin, Acr_Message *message); private Acr_Status send_message(Acr_File *afpout, Acr_Message message); private void timeout_handler(int sig); private int read_replies(Acr_File *afpin); private int synchronize_input(Acr_File *afpin); private Acr_Message make_message(Acr_Group group_list); /* ----------------------------- MNI Header ----------------------------------- @NAME : get_client_data_ptr @INPUT : afp @OUTPUT : (none) @RETURNS : Pointer to dicom client data @DESCRIPTION: Routine to get the pointer to the client data. If none exists, then it is created. @METHOD : @GLOBALS : @CALLS : @CREATED : November 11, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Dicom_client_data *get_client_data_ptr(Acr_File *afp) { Dicom_client_data *client_data; /* Get the data */ client_data = (Dicom_client_data *) acr_get_dicom_client_data(afp); /* If it is NULL then initialize it */ if (client_data == NULL) { client_data = MALLOC(sizeof(*client_data)); if (client_data == NULL) { (void) fprintf(stderr, "Out of memory\n"); exit(EXIT_FAILURE); } client_data->timeout_length = DEFAULT_TIMEOUT; client_data->max_outstanding_responses = DEFAULT_MAX_OUTSTANDING; client_data->last_message_id = 0; client_data->last_answered_id = client_data->last_message_id; acr_set_dicom_client_data(afp, (void *) client_data); } return client_data; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_open_dicom_connection @INPUT : host - name of host to which we should connect If host name is "-" then output is sent to standard out and input is not opened - afpin is set to NULL. port - string giving port number or name of service to which we should connect called_ae - Remote application entity requested calling_ae - Application entity making request abstract_syntax - transfer_syntax - if NULL, then send the standard 3 are proposed (implicit-little endian, explicit little, explict big) @OUTPUT : afpin - dicom file handle for input afpout - dicom file handle for output @RETURNS : TRUE if successful connection is made, FALSE otherwise. @DESCRIPTION: Routine to open a dicom connection to a remote host. @METHOD : @GLOBALS : @CALLS : @CREATED : July 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_open_dicom_connection(char *host, char *port, char *called_ae, char *calling_ae, char *abstract_syntax, char *transfer_syntax, Acr_File **afpin, Acr_File **afpout) { FILE *fpin, *fpout; char *abstract_syntax_list[2] = {NULL, NULL}; char *transfer_syntax_list[2] = {NULL, NULL}; /* Make network connection if a host name is given. If no host, then set timeout to zero to indicate infinite wait */ if (strcmp(host, "-") == 0) { *afpin = NULL; *afpout = acr_initialize_dicom_output(stdout, 0, acr_stdio_write); acr_set_client_timeout(*afpout, 0.0); } else { if (!acr_connect_to_host(host, port, &fpin, &fpout)) { return FALSE; } *afpin = acr_initialize_dicom_input(fpin, 0, acr_stdio_read); *afpout = acr_initialize_dicom_output(fpout, 0, acr_stdio_write); /* Add ismore function to input */ acr_dicom_set_ismore_function(*afpin, acr_stdio_ismore); } /* Establish association */ abstract_syntax_list[0] = abstract_syntax; transfer_syntax_list[0] = transfer_syntax; if (!acr_make_dicom_association(*afpin, *afpout, called_ae, calling_ae, abstract_syntax_list, transfer_syntax_list)) { acr_close_dicom_no_release(*afpin, *afpout); return FALSE; } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_close_dicom_no_release @INPUT : afpin - dicom file handle for input (can be NULL) afpout - dicom file handle for output @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to close a dicom connection without releasing the association. @METHOD : @GLOBALS : @CALLS : @CREATED : October 20, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_close_dicom_no_release(Acr_File *afpin, Acr_File *afpout) { FILE *fpin, *fpout; /* Close the input handle */ if (afpin != NULL) { fpin = (FILE *) acr_dicom_get_io_data(afpin); acr_close_dicom_file(afpin); (void) fclose(fpin); } /* Close the output handle */ fpout = (FILE *) acr_dicom_get_io_data(afpout); acr_close_dicom_file(afpout); (void) fclose(fpout); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_close_dicom_connection @INPUT : afpin - dicom file handle for input (can be NULL) afpout - dicom file handle for output @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to close a dicom connection. @METHOD : @GLOBALS : @CALLS : @CREATED : July 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_close_dicom_connection(Acr_File *afpin, Acr_File *afpout) { /* Release the association */ (void) acr_release_dicom_association(afpin, afpout); /* Close the connection */ acr_close_dicom_no_release(afpin, afpout); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_connect_to_host @INPUT : host - name of host to which we should connect port - string giving port number or name of service to which we should connect @OUTPUT : fpin - file handle for input fpout - file handle for output @RETURNS : TRUE if successful connection is made, FALSE otherwise. @DESCRIPTION: Routine to open a connection to a remote host. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_connect_to_host(char *host, char *port, FILE **fpin, FILE **fpout) { struct servent *sp; struct hostent *hp; struct sockaddr_in server; int sock; int sockbuflen, oldsockbuflen; int sockoptlen; /* Set default file pointers */ *fpin = *fpout = NULL; /* Initialize the address structure */ bzero((char *) &server, sizeof(server)); /* Get the port, either as a number or as a service name */ if ((*port >= '0') && (*port <= '9')) { server.sin_port = htons(atoi(port)); } else if ((sp = getservbyname(port, "tcp")) != NULL) { server.sin_port = sp->s_port; } else { (void) fprintf(stderr, "Service \"%s\" not found\n", port); return FALSE; } /* Look up the host, either as a name or as an IP address */ if ((*host >= '0') && (*host <= '9')) { server.sin_addr.s_addr = inet_addr(host); server.sin_family = AF_INET; if (server.sin_addr.s_addr == INADDR_NONE) { (void) fprintf(stderr, "Badly formed IP address %s\n", host); return FALSE; } } else if ((hp = gethostbyname(host)) != NULL) { bcopy(hp->h_addr, (char *) &server.sin_addr, hp->h_length); server.sin_family = hp->h_addrtype; } else { (void) fprintf(stderr, "Unknown host: %s\n", host); return FALSE; } /* Open the connection */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("Error getting socket"); return FALSE; } (void) signal(SIGALRM, timeout_handler); (void) alarm(Initial_timeout_length); if (connect(sock, (struct sockaddr *) &server, sizeof (server)) < 0) { (void) alarm(0); (void) fprintf(stderr, "Unable to connect to %s: ", host); if (Connection_timeout) { (void) fprintf(stderr, "connection timed out\n"); } else { perror(NULL); } return FALSE; } (void) alarm(0); /* Get socket buffer size */ sockbuflen = MIN_SOCK_BUFLEN; sockoptlen = sizeof(sockbuflen); if ((getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *) &sockbuflen, &sockoptlen) == 0) && (sockbuflen < MIN_SOCK_BUFLEN) && (sockbuflen > 0)) { oldsockbuflen = sockbuflen; sockbuflen = MIN_SOCK_BUFLEN; sockoptlen = sizeof(sockbuflen); while ((sockbuflen > oldsockbuflen) && (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *) &sockbuflen, sockoptlen) != 0)) { sockbuflen = (int) ((double) sockbuflen * 0.75); } if (sockbuflen <= oldsockbuflen) { (void) setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *) &oldsockbuflen, sockoptlen); } } /* Open file handles */ if ((*fpin = fdopen(sock, "r")) == NULL) { (void) fprintf(stderr, "Error opening socket for read\n"); return FALSE; } if (((sock = dup(sock)) < 0) || ((*fpout = fdopen(sock, "w")) == NULL)) { (void) fclose(*fpin); if (sock >= 0) (void) close(sock); (void) fprintf(stderr, "Error opening socket for write\n"); return FALSE; } /* Ignore SIGPIPES in case the output connection gets closed when we are doing output. */ (void) signal(SIGPIPE, SIG_IGN); return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_make_dicom_association @INPUT : afpin - input stream (can be NULL) afpout - output stream abstract_syntax_list - NULL terminated list of abstract syntaxes transfer_syntax_list - NULL-terminated list of transfer syntaxes. If NULL or empty, then the 3 standard syntaxes are proposed. @OUTPUT : (none) @RETURNS : Pointer to appropriate abstract syntax or NULL if association not made. @DESCRIPTION: Routine to establish a dicom association. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public char *acr_make_dicom_association(Acr_File *afpin, Acr_File *afpout, char *called_ae, char *calling_ae, char *abstract_syntax_list[], char *transfer_syntax_list[]) { Acr_Message message; char *transfer_syntax, *abstract_syntax; Acr_Status status; Acr_byte_order byte_order; Acr_VR_encoding_type vr_encoding; int isyntax, nsyntax; int presentation_context_id; long maximum_length; /* Synchronize input */ if (afpin != NULL) { if (!synchronize_input(afpin)) return NULL; } /* Compose a message */ message = compose_assoc_request(called_ae, calling_ae, abstract_syntax_list, transfer_syntax_list); if (message == NULL) { return NULL; } /* Get the requested maximum length */ maximum_length = acr_find_long(acr_get_message_group_list(message), DCM_PDU_Maximum_length, 0L); /* Ship it out */ status = send_message(afpout, message); acr_delete_message(message); if (status != ACR_OK) { acr_dicom_error(status, "Error sending association request"); return NULL; } /* Wait for an answer */ if (afpin == NULL) { presentation_context_id = 1; transfer_syntax = transfer_syntax_list[0]; } else { status = receive_message(afpin, &message); if (status != ACR_OK) { acr_dicom_error(status, "Error receiving association reply"); return NULL; } /* Check it */ if (!check_reply(message, &presentation_context_id, &transfer_syntax, &maximum_length)) { return NULL; } } /* Set the presentation context id for the streams */ if (afpin != NULL) { acr_set_dicom_pres_context_id(afpin, presentation_context_id); } acr_set_dicom_pres_context_id(afpout, presentation_context_id); /* Figure out which abstract syntax was accepted */ for (nsyntax=0; abstract_syntax_list[nsyntax] != NULL; nsyntax++) {} isyntax = (presentation_context_id - 1) / 2; if ((isyntax < 0) || (isyntax >= nsyntax)) { (void) fprintf(stderr, "Invalid presentation context accepted.)\n"); return NULL; } abstract_syntax = abstract_syntax_list[isyntax]; /* Make sure that the i/o streams have the correct encoding and byte-order */ if (acr_uid_equal(transfer_syntax, ACR_IMPLICIT_VR_LITTLE_END_UID)) { byte_order = ACR_LITTLE_ENDIAN; vr_encoding = ACR_IMPLICIT_VR; } else if (acr_uid_equal(transfer_syntax, ACR_EXPLICIT_VR_LITTLE_END_UID)) { byte_order = ACR_LITTLE_ENDIAN; vr_encoding = ACR_EXPLICIT_VR; } else if (acr_uid_equal(transfer_syntax, ACR_EXPLICIT_VR_BIG_END_UID)) { byte_order = ACR_BIG_ENDIAN; vr_encoding = ACR_EXPLICIT_VR; } else { (void) fprintf(stderr, "Unrecognized transfer syntax \"%s\"\n", transfer_syntax); return NULL; } if (afpin != NULL) { acr_set_byte_order(afpin, byte_order); acr_set_vr_encoding(afpin, vr_encoding); } acr_set_byte_order(afpout, byte_order); acr_set_vr_encoding(afpout, vr_encoding); /* Set the maximum length */ acr_set_dicom_maximum_length(afpout, maximum_length); /* Delete the input message */ if (afpin != NULL) { acr_delete_message(message); } /* Return the abstract syntax */ return abstract_syntax; } /* ----------------------------- MNI Header ----------------------------------- @NAME : compose_assoc_request @INPUT : called_ae - Remote application entity requested calling_ae - Application entity making request abstract_syntax_list - NULL terminated list of abstract syntaxes transfer_syntax_list - NULL-terminated list of transfer syntaxes. If NULL or empty, then the 3 standard syntaxes are proposed. @OUTPUT : (none) @RETURNS : Message to be sent to remote host @DESCRIPTION: Routine to compose an association request message. It only allows one abstract syntax to be sent. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Message compose_assoc_request(char *called_ae, char *calling_ae, char *abstract_syntax_list[], char *transfer_syntax_list[]) { Acr_Message message; Acr_Group group; Acr_Element item_list, sublist, subitem, element; char **syntax_list; int iabstract, itransfer, num_syntax; int cur_presentation_context_id; static char *standard_transfer_syntax[] = { ACR_IMPLICIT_VR_LITTLE_END_UID, ACR_EXPLICIT_VR_LITTLE_END_UID, ACR_EXPLICIT_VR_BIG_END_UID }; static int num_standard_transfer_syntax = sizeof(standard_transfer_syntax) / sizeof(standard_transfer_syntax[0]); /* Check for an NULL or empty abstract syntax list */ if ((abstract_syntax_list == NULL) || (abstract_syntax_list[0] == NULL)) { (void) fprintf(stderr, "Error composing association request: Empty abstract syntax list\n"); return NULL; } /* Build up the request */ group = acr_create_group(DCM_PDU_GRPID); acr_group_add_element(group, acr_create_element_short(DCM_PDU_Type, ACR_PDU_ASSOC_RQ)); /* Add the caller and calling AE titles */ acr_group_add_element(group, acr_create_element_string(DCM_PDU_Called_Ap_title, called_ae)); acr_group_add_element(group, acr_create_element_string(DCM_PDU_Calling_Ap_title, calling_ae)); /* Add the application context */ acr_group_add_element(group, acr_create_element_string(DCM_PDU_Application_context, ACR_APPLICATION_CONTEXT_UID)); /* Work out the list of transfer syntaxes */ if ((transfer_syntax_list == NULL) || (transfer_syntax_list[0] == NULL)) { syntax_list = standard_transfer_syntax; num_syntax = num_standard_transfer_syntax; } else { syntax_list = transfer_syntax_list; for (num_syntax=0; transfer_syntax_list[num_syntax] != NULL; num_syntax++) {} } /* Loop over abstract syntaxes (and presentation contexts) */ item_list = NULL; for (iabstract = 0; abstract_syntax_list[iabstract] != NULL; iabstract++) { /* Work out the presentation context id */ cur_presentation_context_id = (iabstract * 2) + 1; /* Create a presentation context */ sublist = NULL; subitem = acr_create_element_short(DCM_PDU_Presentation_context_id, cur_presentation_context_id); sublist = acr_element_list_add(sublist, subitem); /* Add an abstract syntax */ subitem = acr_create_element_string(DCM_PDU_Abstract_syntax, abstract_syntax_list[iabstract]); sublist = acr_element_list_add(sublist, subitem); /* Add the transfer syntax */ for (itransfer=0; itransfer < num_syntax; itransfer++) { subitem = acr_create_element_string(DCM_PDU_Transfer_syntax, syntax_list[itransfer]); sublist = acr_element_list_add(sublist, subitem); } /* Add this presentation context to the list */ item_list = acr_element_list_add(item_list, acr_create_element_sequence(DCM_PDU_Presentation_context, sublist)); } /* End of loop over presentation contexts */ /* Create the presentation context list element */ element = acr_create_element_sequence(DCM_PDU_Presentation_context_list, item_list); acr_group_add_element(group, element); /* Add the user information */ acr_group_add_element(group, acr_create_element_long(DCM_PDU_Maximum_length, 1048576L)); acr_group_add_element(group, acr_create_element_string(DCM_PDU_Implementation_class_uid, acr_get_implementation_uid())); /* Make a message and add this group */ message = acr_create_message(); acr_message_add_group(message, group); return message; } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_reply @INPUT : message @OUTPUT : presentation_context_id transfer_syntax maximum_length -maximum length for dicom output @RETURNS : TRUE if reply is okay, FALSE otherwise. @DESCRIPTION: Routine to check the reply from the remote host. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int check_reply(Acr_Message message, int *presentation_context_id, char **transfer_syntax, long *maximum_length) { Acr_Group group; Acr_Element element, item, sublist, subitem; int pdu_type; /* Set values in case of error */ *transfer_syntax = NULL; *presentation_context_id = -1; *maximum_length = 0; /* Get the group */ group = acr_get_message_group_list(message); /* See what they say */ pdu_type = acr_find_short(group, DCM_PDU_Type, -1); switch (pdu_type) { case ACR_PDU_ASSOC_AC: break; case ACR_PDU_ASSOC_RJ: (void) fprintf(stderr, "Association rejected: code %d\n", acr_find_short(group, DCM_PDU_Reason, -1)); return FALSE; case ACR_PDU_ABORT_RQ: (void) fprintf(stderr, "Association aborted: code %d\n", acr_find_short(group, DCM_PDU_Reason, -1)); return FALSE; default: (void) fprintf(stderr, "Bad response to association request\n"); return FALSE; } /* Get the presentation context list */ element = acr_find_group_element(group, DCM_PDU_Presentation_context_reply_list); if (element == NULL) { (void) fprintf(stderr, "Invalid response to assocation request\n"); return FALSE; } /* Loop over list */ for (item = (Acr_Element) acr_get_element_data(element); item != NULL; item = acr_get_element_next(item)) { if (!acr_element_is_sequence(item)) continue; /* Get presentation context info */ sublist = (Acr_Element) acr_get_element_data(item); /* Check whether it was accepted */ subitem = acr_find_element_id(sublist, DCM_PDU_Result); if ((subitem == NULL) || (acr_get_element_short(subitem) != ACR_ASSOC_PR_CN_ACCEPT)) { continue; } /* Check the presentation context id */ subitem = acr_find_element_id(sublist, DCM_PDU_Presentation_context_id); if (subitem == NULL) continue; *presentation_context_id = acr_get_element_short(subitem); /* Grab the transfer syntax */ subitem = acr_find_element_id(sublist, DCM_PDU_Transfer_syntax); if ((subitem == NULL)) continue; *transfer_syntax = acr_get_element_string(subitem); /* If we get to here, we have an accepted syntax, so stop looping */ break; } /* Check that we found a transfer syntax */ if (*transfer_syntax == NULL) { (void) fprintf(stderr, "No presentation contexts were accepted\n"); return FALSE; } /* Get the maximum length */ *maximum_length = acr_find_long(group, DCM_PDU_Maximum_length, 0L); return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : receive_message @INPUT : afpin - input stream @OUTPUT : message - message that was read in @RETURNS : status @DESCRIPTION: Routine to receive messages @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status receive_message(Acr_File *afpin, Acr_Message *message) { Acr_Status status; Dicom_client_data *client_data; Alarmed_afp = afpin; client_data = get_client_data_ptr(afpin); Connection_timeout = FALSE; (void) signal(SIGALRM, timeout_handler); (void) alarm(client_data->timeout_length); status=acr_input_dicom_message(afpin, message); (void) alarm(0); if (Connection_timeout) { status = ACR_CONNECTION_TIMEDOUT; } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : send_message @INPUT : afpout - output stream message - message to send @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Routine to send messages @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status send_message(Acr_File *afpout, Acr_Message message) { Acr_Status status; Dicom_client_data *client_data; client_data = get_client_data_ptr(afpout); Alarmed_afp = afpout; Connection_timeout = FALSE; (void) signal(SIGALRM, timeout_handler); (void) alarm(client_data->timeout_length); status = acr_output_dicom_message(afpout, message); (void) alarm(0); if (Connection_timeout) { status = ACR_CONNECTION_TIMEDOUT; } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_client_timeout @INPUT : afp - stream on which to set timeout seconds - time in seconds to wait for i/o before timing out @OUTPUT : (none) @RETURNS : @DESCRIPTION: Routine to set the length of network timeouts. This time is used once the connection has been made. Note that although a double-precision argument is given, it is truncated to integer before being used. A value of zero or less means that no timeout is used. @METHOD : @GLOBALS : @CALLS : @CREATED : September 15, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_set_client_timeout(Acr_File *afp, double seconds) { Dicom_client_data *client_data; client_data = get_client_data_ptr(afp); client_data->timeout_length = (int) seconds; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_client_initial_timeout @INPUT : seconds - time in seconds to wait for initial connection before timing out @OUTPUT : (none) @RETURNS : @DESCRIPTION: Routine to set the length of initial network connection timeouts. This time is used only when the initial connection is made. Note that although a double-precision argument is given, it is truncated to integer before being used. A value of zero or less means that no timeout is used. @METHOD : @GLOBALS : @CALLS : @CREATED : September 15, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_set_client_initial_timeout(double seconds) { Initial_timeout_length = (int) seconds; } /* ----------------------------- MNI Header ----------------------------------- @NAME : timeout_handler @INPUT : @OUTPUT : (none) @RETURNS : @DESCRIPTION: Routine to handle connection timeouts. @METHOD : @GLOBALS : @CALLS : @CREATED : March 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ /* ARGSUSED */ private void timeout_handler(int sig) { Connection_timeout = TRUE; if (Alarmed_afp != NULL) { acr_dicom_set_eof(Alarmed_afp); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_client_max_outstanding @INPUT : afp - stream on which to set asynchronous transfer (can be NULL) max - maximum number of outstanding messages that are allowed @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to set the maximum number of messages that can be sent by acr_send_group_list before a reply is received. This must be set on the input stream to take effect. Setting a negative maximum means that acr_send_group_list will immediately block until the reply is received (completely synchonous). A value of zero means that the send will return immediately after sending, but will block on the next call until the reply is recieved. Setting a non-zero positive value will allow the transmission of more messages (up to the max) without any reply (asynchronous). Once the limit is reached, acr_send_group_list will block until a reply is received. Using asynchronous transfers can greatly improve speed for small messages, but means that error reporting can occur asynchonously as well. @METHOD : @GLOBALS : @CALLS : @CREATED : November 12, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_set_client_max_outstanding(Acr_File *afp, int max) { Dicom_client_data *client_data; if (afp == NULL) return; client_data = get_client_data_ptr(afp); client_data->max_outstanding_responses = max; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_client_max_outstanding @INPUT : afp - stream on which to set asynchronous transfer @OUTPUT : (none) @RETURNS : maximum number of outstanding responses permitted for this stream. @DESCRIPTION: Routine to get the maximum number of messages that can be sent by acr_send_group_list before a reply is received. @METHOD : @GLOBALS : @CALLS : @CREATED : November 12, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_get_client_max_outstanding(Acr_File *afp) { Dicom_client_data *client_data; client_data = get_client_data_ptr(afp); return client_data->max_outstanding_responses; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dicom_error @INPUT : status - status returned from dicom routine string - string to display before error message @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Prints out the string, followed by a colon, a blank and and error message based on the status. @METHOD : @GLOBALS : @CALLS : @CREATED : February 21, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_dicom_error(Acr_Status status, char *string) { char *error; /* Get the appropriate error string */ error = acr_status_string(status); /* Print it out */ (void) fprintf(stderr, "%s: %s\n", string, error); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_release_dicom_association @INPUT : afpin - input stream (can be NULL) afpout - output stream @OUTPUT : (none) @RETURNS : TRUE if release went smoothly. @DESCRIPTION: Routine to shut down a dicom association. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_release_dicom_association(Acr_File *afpin, Acr_File *afpout) { Acr_Message message; Acr_Group group; Acr_Status status; int pdu_type; /* Synchronize input */ if (afpin != NULL) { if (!synchronize_input(afpin)) return FALSE; } /* Compose a message */ group = acr_create_group(DCM_PDU_GRPID); acr_group_add_element(group, acr_create_element_short(DCM_PDU_Type, ACR_PDU_REL_RQ)); message = acr_create_message(); acr_message_add_group(message, group); /* Ship it out */ status = send_message(afpout, message); acr_delete_message(message); if (status != ACR_OK) { acr_dicom_error(status, "Error sending release request"); return FALSE; } if (afpin != NULL) { /* Wait for an answer */ status = receive_message(afpin, &message); if (status != ACR_OK) { acr_dicom_error(status, "Error receiving release reply"); return FALSE; } /* Check it */ pdu_type = acr_find_short(group, DCM_PDU_Type, -1); if (pdu_type != ACR_PDU_REL_RP) { (void) fprintf(stderr, "Bad reply to release request (PDU type %d)\n", pdu_type); return FALSE; } } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_send_group_list @INPUT : afpin - input stream (can be NULL) afpout - output stream group_list - dicom dataset to send sop_class_uid - this should just be abstract syntax returned by make_association (or passed in to open_dicom_connection). @OUTPUT : (none) @RETURNS : TRUE if exchange went smoothly. @DESCRIPTION: Routine to send a dicom data set and get the response. Asynchronous transmission and reply is supported in this routine only. Use function acr_set_client_max_outstanding to turn this feature on. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_send_group_list(Acr_File *afpin, Acr_File *afpout, Acr_Group group_list, char *sop_class_uid) { Dicom_client_data *client_data; if (afpin != NULL) { /* Get the client_data. Message ids are tracked on the input side unless there is no input side */ client_data = get_client_data_ptr(afpin); /* Read in replies */ if (!read_replies(afpin)) return FALSE; } else { /* Get the client_data. Since there is no input we store it on the output side. */ client_data = get_client_data_ptr(afpout); } /* Send the message */ if (!acr_transmit_group_list(afpout, group_list, sop_class_uid, ++(client_data->last_message_id))) { return FALSE; } /* Check the reply if user wants to force synchronous operation */ if (afpin != NULL) { if (client_data->max_outstanding_responses < 0) { if (!read_replies(afpin)) return FALSE; } } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_replies @INPUT : afpin - input stream @OUTPUT : (none) @RETURNS : TRUE if replies are okay. @DESCRIPTION: Routine to read in outstanding replies. If asynchronous message exchange is permitted (see function acr_set_client_max_outstanding), then this routine will not block. @METHOD : @GLOBALS : @CALLS : @CREATED : November 12, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int read_replies(Acr_File *afpin) { int result; Dicom_client_data *client_data; int num_outstanding, max_outstanding; int keep_looping; /* Get the client_data */ client_data = get_client_data_ptr(afpin); /* Check whether there are any outstanding responses */ if (client_data->last_message_id > client_data->last_answered_id) { /* Get the maximum number of outstanding responses permitted. Make sure that max_outstanding is not negative so that we don't block waiting for a responses to an unsent message. */ max_outstanding = client_data->max_outstanding_responses; if (max_outstanding < 0) max_outstanding = 0; /* Loop until there is nothing left waiting */ keep_looping = TRUE; while (keep_looping) { /* Figure out how many outstanding responses there are */ num_outstanding = client_data->last_message_id - client_data->last_answered_id; /* Get out of the loop if there is nothing to read and the number of outstanding responses is not too large */ if (!acr_file_ismore(afpin) && (num_outstanding <= max_outstanding)) { keep_looping = FALSE; break; } /* Read in a reply and keep track of id of answered message */ result = acr_receive_reply(afpin); if (result < 0) return FALSE; if (result != (client_data->last_answered_id+1)) { (void) fprintf(stderr, "Received reply to wrong message\n"); return FALSE; } client_data->last_answered_id = result; } /* End loop over responses */ } /* End if outstanding responses */ return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : synchronize_input @INPUT : afpin - input stream @OUTPUT : (none) @RETURNS : TRUE if replies are okay. @DESCRIPTION: Routine to synchronize the input stream with the output (see function acr_set_client_max_outstanding). This function will block until all replies are read in. @METHOD : @GLOBALS : @CALLS : @CREATED : November 12, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int synchronize_input(Acr_File *afpin) { int old_max_outstanding; int result; /* Set the maximum number of outstanding replies to zero to force blocking, saving the old value */ old_max_outstanding = acr_get_client_max_outstanding(afpin); acr_set_client_max_outstanding(afpin, 0); /* Read the replies */ result = read_replies(afpin); /* Restore the old value */ acr_set_client_max_outstanding(afpin, old_max_outstanding); return result; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_transmit_group_list @INPUT : afpout - output stream group_list - dicom dataset to send sop_class_uid - this should just be abstract syntax returned by make_association (or passed in to open_dicom_connection). message_id - Unique message id. @OUTPUT : (none) @RETURNS : TRUE if send went smoothly. @DESCRIPTION: Routine to send a dicom data set. To check for the reply, call acr_receive_reply. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_transmit_group_list(Acr_File *afpout, Acr_Group group_list, char *sop_class_uid, int message_id) { Acr_Status status; Acr_Message message; Acr_Group output_group_list; char uid_buffer[64] = {'\0'}; char *instance_uid; Acr_Element_Id elements_to_remove[25]; int nelements_to_remove = 0; int ielem; Acr_Group group; /* Get a UID for this object */ instance_uid = acr_find_string(group_list, ACR_SOP_instance_UID, NULL); if (instance_uid == NULL) { instance_uid = strncpy(uid_buffer, acr_create_uid(), sizeof(uid_buffer)-1); } /* Create a command */ output_group_list = acr_create_group(ACR_MESSAGE_GID); acr_group_add_element(output_group_list, acr_create_element_string(ACR_Affected_SOP_class_UID, sop_class_uid)); acr_group_add_element(output_group_list, acr_create_element_short(ACR_Command, ACR_C_STORE_RQ)); acr_group_add_element(output_group_list, acr_create_element_short(ACR_Message_id, message_id)); acr_group_add_element(output_group_list, acr_create_element_short(ACR_Priority, 0)); acr_group_add_element(output_group_list, acr_create_element_short(ACR_Dataset_type, 0)); acr_group_add_element(output_group_list, acr_create_element_string(ACR_Affected_SOP_instance_UID, instance_uid)); /* Send the command */ message = make_message(output_group_list); status = send_message(afpout, message); acr_delete_message(message); if (status != ACR_OK) { acr_dicom_error(status, "Error sending store request"); return FALSE; } /* Macro to insert a new string element into the group list and record the element id so that it can be removed later */ nelements_to_remove = 0; #define INSERT_N_SAVE_ELEM(elid, string) \ {acr_insert_string(&group_list, elid, string); \ elements_to_remove[nelements_to_remove++] = elid;} /* Add the class and instance UID's to the data group list */ if (acr_find_group_element(group_list, ACR_SOP_class_UID) == NULL) { INSERT_N_SAVE_ELEM(ACR_SOP_class_UID, sop_class_uid); } if (acr_find_group_element(group_list, ACR_SOP_instance_UID) == NULL) { INSERT_N_SAVE_ELEM(ACR_SOP_instance_UID, instance_uid); } /* Add the study and series UID's to the group list */ if (acr_find_group_element(group_list, ACR_Study_instance_UID) == NULL) { INSERT_N_SAVE_ELEM(ACR_Study_instance_UID, acr_create_uid()); } if (acr_find_group_element(group_list, ACR_Series_instance_UID) == NULL) { INSERT_N_SAVE_ELEM(ACR_Series_instance_UID, acr_create_uid()); } /* Make up some essential data if it is not already in the group list */ if (acr_find_group_element(group_list, ACR_Image_type) == NULL) { INSERT_N_SAVE_ELEM(ACR_Image_type, "ORIGINAL\\PRIMARY\\UNDEFINED"); } if (acr_find_group_element(group_list, ACR_Sequence_variant) == NULL) { INSERT_N_SAVE_ELEM(ACR_Sequence_variant, "NONE\\NONE"); } if (acr_find_group_element(group_list, ACR_Image_position) == NULL) { INSERT_N_SAVE_ELEM(ACR_Image_position, "0\\0\\0"); } if (acr_find_group_element(group_list, ACR_Image_orientation) == NULL) { INSERT_N_SAVE_ELEM(ACR_Image_orientation, "1\\0\\0\\0\\1\\0"); } if (acr_find_group_element(group_list, ACR_Frame_of_reference_UID) == NULL) { INSERT_N_SAVE_ELEM(ACR_Frame_of_reference_UID, acr_create_uid()); } if (acr_find_group_element(group_list, ACR_Samples_per_pixel) == NULL) { acr_insert_short(&group_list, ACR_Samples_per_pixel, 1); elements_to_remove[nelements_to_remove++] = ACR_Samples_per_pixel; } if (acr_find_group_element(group_list, ACR_Photometric_interpretation) == NULL) { INSERT_N_SAVE_ELEM(ACR_Photometric_interpretation, "MONOCHROME2"); } /* Send the data. Disconnect the message from the group list so that the latter is not deleted */ message = make_message(group_list); status = send_message(afpout, message); acr_message_reset(message); acr_delete_message(message); /* Delete the elements that we added */ for (ielem=0; ielem < nelements_to_remove; ielem++) { group = acr_find_group(group_list, elements_to_remove[ielem]->group_id); if (group != NULL) { acr_group_remove_element(group, elements_to_remove[ielem]->element_id); } } /* Check the status */ if (status != ACR_OK) { acr_dicom_error(status, "Error sending store data"); return FALSE; } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_receive_reply @INPUT : afpin - input stream @OUTPUT : (none) @RETURNS : Message id being reponded to or -1 if an error occurs @DESCRIPTION: Routine to receive a reply to a send command. @METHOD : @GLOBALS : @CALLS : @CREATED : May 9, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_receive_reply(Acr_File *afpin) { Acr_Status status; Acr_Message message; Acr_Group reply_group; int command_status; int message_id; /* Wait for an answer */ status = receive_message(afpin, &message); if (status != ACR_OK) { acr_dicom_error(status, "Error receiving store reply"); return -1; } /* Check the reply */ reply_group = acr_get_message_group_list(message); if (acr_find_short(reply_group, ACR_Command, -1) != ACR_C_STORE_RSP) { (void) fprintf(stderr, "Bad response to store request\n"); return -1; } command_status = acr_find_short(reply_group, ACR_Status, -1); switch (command_status) { case ACR_SUCCESS: break; default: (void) fprintf(stderr, "Unrecognized store status (%d)\n", command_status); return -1; } message_id = acr_find_short(reply_group, ACR_Message_id_brt, -1); /* Delete the reply message */ acr_delete_message(message); return message_id; } /* ----------------------------- MNI Header ----------------------------------- @NAME : make_message @INPUT : group_list @OUTPUT : (nothing) @RETURNS : output message. @DESCRIPTION: Convert a group list into a message. @METHOD : @GLOBALS : @CALLS : @CREATED : November 24, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Message make_message(Acr_Group group_list) { Acr_Group next_group, group; Acr_Message output_message; /* Create the output message */ output_message = acr_create_message(); /* Loop through groups, adding them to the message */ group = group_list; while (group != NULL) { next_group = acr_get_group_next(group); acr_set_group_next(group, NULL); acr_message_add_group(output_message, group); group = next_group; } return output_message; } minc-2.2.00/conversion/Acr_nema/dicom_network.c0000644000265600003100000030715712027132657016363 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_network.c @DESCRIPTION: Routines for doing dicom network communications @METHOD : @GLOBALS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : * $Log: dicom_network.c,v $ * Revision 6.12 2008-08-12 05:00:22 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.11 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.10 2001/03/19 18:30:32 neelin * Added function to set implementation uid and changed name of function * that gets it. * * Revision 6.9 2000/05/17 20:17:47 neelin * Added mechanism to allow testing of input streams for more data through * function acr_file_ismore. * This is used in dicom_client_routines to allow asynchronous transfer * of data, with testing for more input done before sending new messages. * Previous use of select for this was misguided, since select may report that * no data is waiting on the file descriptor while data is store in the file * pointer buffer (or Acr file pointer buffer). * * Revision 6.8 2000/02/03 13:30:30 neelin * Changed initial value of counter for acr_create_uid so that uid does not ever * contain a zero. * * Revision 6.7 1999/10/29 17:51:51 neelin * Fixed Log keyword * * Revision 6.6 1998/11/11 17:47:38 neelin * Fixed up freeing of data pointers on file close. * * Revision 6.5 1998/11/11 17:05:03 neelin * Added pointer for client data to dicom structure. * * Revision 6.4 1998/03/23 20:22:37 neelin * Added includes for new functions. * * Revision 6.3 1998/03/23 20:16:16 neelin * Moved some general-purpose functions from dicom_client_routines and * added one for implementation uid. * * Revision 6.2 1998/03/10 17:05:30 neelin * Fixed handling of PDV control header last fragment bit (it should be * set for both command and data parts of the message). Re-organized code * to use watchpoints differently: put PDU watchpoint on real afp * everywhere and store PDV watchpoint in dicom io structure. * * Revision 6.1 1997/10/20 22:52:46 neelin * Added support for implementation user information in association request. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.3 1997/08/21 13:24:56 neelin * Pre-release * * Revision 4.2 1997/07/10 17:14:38 neelin * Added more status codes and function to return status string. * * Revision 4.1 1997/07/09 17:38:55 neelin * Added function acr_dicom_get_io_data. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 1.2 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 1.1 1997/02/20 16:38:17 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include /* Constants */ #define ACR_COMMAND_GRPID 0x0 #define PDU_HEADER_LEN (2+ACR_SIZEOF_LONG) #define PDU_ITEM_HEADER_LEN (2+ACR_SIZEOF_SHORT) #define ASSOC_RQ_LEN 74 #define ASSOC_RJ_LEN 10 #define ABORT_RQ_LEN 10 #define DATA_TF_LEN 6 #define MAX_PDU_STRING_LENGTH 1024 #define DICOM_NETWORK_BYTE_ORDER ACR_BIG_ENDIAN /* PDU item types */ #define PDU_ITEM_APPLICATION_CONTEXT 0x10 #define PDU_ITEM_PRESENTATION_CONTEXT 0x20 #define PDU_ITEM_PRES_CONTEXT_REPLY 0x21 #define PDU_ITEM_ABSTRACT_SYNTAX 0x30 #define PDU_ITEM_TRANSFER_SYNTAX 0x40 #define PDU_ITEM_USER_INFORMATION 0x50 #define PDU_ITEM_MAXIMUM_LENGTH 0x51 #define PDU_ITEM_IMPLEMENTATION_CLASS_UID 0x52 #define PDU_ITEM_IMPLEMENTATION_VERSION_NAME 0x55 /* Mask for getting info out of PDV message control header */ #define PDV_COMMAND_PDV_MASK 0x1 #define PDV_LAST_FRAGMENT_MASK 0x2 /* Types to allow 2-level hierarchy of i/o streams */ typedef enum {DICOM_INPUT=0xbead, DICOM_OUTPUT} Dicom_IO_stream_type; typedef struct { Dicom_IO_stream_type stream_type; Acr_File *real_afp; /* Pointer to real input stream */ Acr_File *virtual_afp; /* Pointer to message stream to which this io data is attached */ int presentation_context_id; long pdv_watchpoint; /* Distance from end of current PDV to PDU watchpoint on real input stream. This should be a positive number. */ long maximum_length; /* Maximum PDU length (excluding header) */ int writing_command; /* True if writing command portion */ long data_length; /* Length of data portion of message */ void *client_data; /* Pointer to client data, if any */ } Acr_Dicom_IO; /* Private functions */ private Acr_Status read_pdu_header(Acr_File *afp, int *pdu_type, Acr_Long *pdu_length); private Acr_Status read_assoc_rq(Acr_File *afp, Acr_Group group); private Acr_Status read_assoc_rq_ac(Acr_File *afp, Acr_Group group, int is_request); private Acr_Status read_data_tf(Acr_File *dicom_afp, Acr_Group group); private Acr_Status read_rel_rq(Acr_File *afp, Acr_Group group); private Acr_Status read_abort_rq(Acr_File *afp, Acr_Group group); private Acr_Status read_assoc_ac(Acr_File *afp, Acr_Group group); private Acr_Status read_assoc_rj(Acr_File *afp, Acr_Group group); private Acr_Status read_rel_rp(Acr_File *afp, Acr_Group group); private Acr_Status read_pdu_item(Acr_File *afp, Acr_Element *item); private Acr_Status read_uid_item(Acr_File *afp, Acr_Element_Id elid, Acr_Element *item); private Acr_Status read_long_item(Acr_File *afp, Acr_Element_Id elid, Acr_Element *item); private Acr_Status read_unknown_item(Acr_File *afp, int item_type, Acr_Element *item); private Acr_Status read_pres_context_item(Acr_File *afp, Acr_Element *item); private Acr_Status read_pres_context_reply_item(Acr_File *afp, Acr_Element *item); private Acr_Status read_user_info_item(Acr_File *afp, Acr_Element *item); private char *get_uid_string(char *buffer, int length); private Acr_Element pdu_create_element_uid(Acr_Element_Id elid, char *value, int length); private Acr_Element pdu_create_element_short(Acr_Element_Id elid, void *input_value); private Acr_Status write_assoc_rq(Acr_File *afp, Acr_Group group); private Acr_Status write_assoc_ac(Acr_File *afp, Acr_Group group); private Acr_Status write_assoc_rq_ac(Acr_File *afp, Acr_Group group, int is_request, long *length); private Acr_Status write_assoc_rj(Acr_File *afp, Acr_Group group_list); private Acr_Status write_rel_rq(Acr_File *afp, Acr_Group group_list); private Acr_Status write_rel_rp(Acr_File *afp, Acr_Group group_list); private Acr_Status write_abort_rq(Acr_File *afp, Acr_Group group_list); private Acr_Status write_fixed_length_pdu(Acr_File *afp, int pdu_type, int result, int source, int reason); private Acr_Status write_data_tf(Acr_File *dicom_afp, Acr_Message message); private Acr_Status write_uid_item(Acr_File *afp, Acr_Element element, int item_type, long *length); private Acr_Status write_pres_context_item(Acr_File *afp, Acr_Element item, int is_request, long *length); private Acr_Status write_user_info_item(Acr_File *afp, Acr_Group group, long *length); private Acr_Status write_unknown_item(Acr_File *afp, int item_type, long data_length, char *data_pointer, long *length); private void pdu_copy_uid(char *string, char *buffer, int length); private Acr_File *initialize_dicom_stream(void *io_data, int maxlength, Acr_Io_Routine io_routine, Dicom_IO_stream_type stream_type); private Acr_Dicom_IO *get_dicom_io_pointer(Acr_File *afp); private Acr_File *get_dicom_real_afp(Acr_File *afp); private long get_dicom_pdv_watchpoint(Acr_File *afp); private void set_dicom_pdv_watchpoint(Acr_File *afp, long pdv_watchpoint); private void dicom_reset(Acr_File *afp); private void dicom_setup_output(Acr_File *afp, long command_length, long data_length); private int dicom_input_routine(void *io_data, void *buffer, int nbytes); private int dicom_output_routine(void *io_data, void *buffer, int nbytes); private int dicom_ismore(void *io_data); /* Macros */ #define EXTRACT_UID(group, elid, value, length) \ acr_group_add_element(group, pdu_create_element_uid(elid, value, (int)length)) #define EXTRACT_SHORT(group, elid, value) \ acr_group_add_element(group, pdu_create_element_short(elid, value)) #define SAVE_SHORT(group, elid, value) \ acr_group_add_element(group, \ acr_create_element_short(elid, (Acr_Short) (value))) #define GET_SHORT(input, output) \ acr_get_short(DICOM_NETWORK_BYTE_ORDER, (long) 1, input, output) #define GET_LONG(input, output) \ acr_get_long(DICOM_NETWORK_BYTE_ORDER, (long) 1, input, output) #define PUT_SHORT(input, output) \ acr_put_short(DICOM_NETWORK_BYTE_ORDER, (long) 1, input, output) #define PUT_LONG(input, output) \ acr_put_long(DICOM_NETWORK_BYTE_ORDER, (long) 1, input, output) #define COPY_UID(group, elid, buffer, length) \ pdu_copy_uid(acr_find_string(group, elid, ""), (char *) buffer, length) /*****************************************************************************/ /*************************** UTILITY ROUTINES ********************************/ /*****************************************************************************/ /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_uid_equal @INPUT : uid1 uid2 @OUTPUT : (nothing) @RETURNS : TRUE if uid's are equal, FALSE otherwise @DESCRIPTION: Responds to READYq message @METHOD : @GLOBALS : @CALLS : @CREATED : February 21, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_uid_equal(char *uid1, char *uid2) { int len1, len2, i; /* Skip leading blanks */ while (isspace(*uid1)) {uid1++;} while (isspace(*uid2)) {uid2++;} /* Skip trailing blanks */ len1 = strlen(uid1); for (i=len1-1; (i >= 0) && isspace(uid1[i]); i--) {} if (isspace(uid1[i+1])) uid1[i+1] = '\0'; len2 = strlen(uid2); for (i=len2-1; (i >= 0) && isspace(uid1[i]); i--) {} if (isspace(uid1[i+1])) uid1[i+1] = '\0'; /* Compare the strings */ return (strcmp(uid1, uid2) == 0); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_uid @INPUT : (none) @OUTPUT : (none) @RETURNS : pointer to internal buffer containing uid @DESCRIPTION: Routine to generate a unique uid. The string is returned in an internal buffer space and will be overwritten by subsequent calls. @METHOD : @GLOBALS : @CALLS : @CREATED : August 25, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public char *acr_create_uid(void) { static char uid[64]; time_t current_time; int offset; int maxlen; union { unsigned char ch[4]; int ul; } host_id; static int counter = 1; /* Make up a new UID */ host_id.ul = gethostid(); current_time = time(NULL); (void) sprintf(uid, "1.%d.%d.%d.%d.%d.%d.%d", (int) 'I',(int) 'P', (int) host_id.ch[0], (int) host_id.ch[1], (int) host_id.ch[2], (int) host_id.ch[3], (int) getpid()); offset = strlen(uid); maxlen = sizeof(uid) - 1 - offset; (void) strftime(&uid[offset], (size_t) maxlen, ".%Y%m%d%H%M%S", localtime(¤t_time)); (void) sprintf(&uid[strlen(uid)], ".%08d", counter++); return uid; } /* Space for storing the implementation class uid. Should only be used by acr_set_implementation_uid and acr_get_implementation_uid */ static char Implementation_class_uid[65] = ""; /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_implementation_uid @INPUT : uid to set for implementation class @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to set a uid for this software implementation. This string is returned by acr_get_implementation_uid which is used by client routines setting up associations. A static space is used to store the uid string. @METHOD : @GLOBALS : @CALLS : @CREATED : March 7, 2000 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_set_implementation_uid(char *uid) { (void) strncpy(Implementation_class_uid, uid, sizeof(Implementation_class_uid)); Implementation_class_uid[sizeof(Implementation_class_uid)-1] = '\0'; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_implementation_uid @INPUT : (none) @OUTPUT : (none) @RETURNS : pointer to internal buffer containing uid @DESCRIPTION: Routine to generate a uid for this software implementation. The string is returned in an internal buffer space and will be overwritten by subsequent calls. @METHOD : @GLOBALS : @CALLS : @CREATED : March 23, 1998 (Peter Neelin) @MODIFIED : March 7, 2001 (P.N.) - changed name from acr_implementation_uid ---------------------------------------------------------------------------- */ public char *acr_get_implementation_uid(void) { /* Set the uid if it is not already set */ if (Implementation_class_uid[0] == '\0') { (void) sprintf(Implementation_class_uid, "1.%d.%d.%d.%d.%d", (int) 'I', (int) 'P', (int) 'M', (int) 'N', (int) 'I'); } return Implementation_class_uid; } /*****************************************************************************/ /*************************** INPUT ROUTINES **********************************/ /*****************************************************************************/ /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_input_dicom_message @INPUT : dicom_afp - acr file pointer for dicom input @OUTPUT : message - NULL if no message is read @RETURNS : status of input @DESCRIPTION: Reads in a dicom message and returns it in a message structure. @METHOD : Although dicom connection, etc. syntaxes differ from the message syntax, this routine and the ones following put it all in the same form. @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Acr_Status acr_input_dicom_message(Acr_File *dicom_afp, Acr_Message *message) { int pdu_type; Acr_Long pdu_length; long old_watchpoint; Acr_File *afp; Acr_Group group; Acr_Status status; /* Set message to NULL in case of error */ *message = NULL; /* Get real afp */ afp = get_dicom_real_afp(dicom_afp); if (afp == NULL) { (void) fprintf(stderr, "Bad dicom file pointer\n"); exit(EXIT_FAILURE); } /* Set a watchpoint before we do anything so that we don't get stuck reading too much */ old_watchpoint = acr_get_io_watchpoint(afp); acr_set_io_watchpoint(afp, PDU_HEADER_LEN); /* Read in PDU type and length */ status = read_pdu_header(afp, &pdu_type, &pdu_length); if (old_watchpoint != ACR_NO_WATCHPOINT) old_watchpoint -= PDU_HEADER_LEN - acr_get_io_watchpoint(afp); if (status != ACR_OK) { acr_set_io_watchpoint(afp, old_watchpoint); return status; } /* Create the message and add the PDU type */ group = acr_create_group(DCM_PDU_GRPID); SAVE_SHORT(group, DCM_PDU_Type, pdu_type); /* Set a watchpoint for reading */ acr_set_io_watchpoint(afp, (long)pdu_length); /* Call the appropriate routine */ switch (pdu_type) { case ACR_PDU_ASSOC_RQ: status = read_assoc_rq(afp, group); break; case ACR_PDU_ASSOC_AC: status = read_assoc_ac(afp, group); break; case ACR_PDU_ASSOC_RJ: status = read_assoc_rj(afp, group); break; case ACR_PDU_DATA_TF: status = read_data_tf(dicom_afp, group); break; case ACR_PDU_REL_RQ: status = read_rel_rq(afp, group); break; case ACR_PDU_REL_RP: status = read_rel_rp(afp, group); break; case ACR_PDU_ABORT_RQ: status = read_abort_rq(afp, group); break; default: status = acr_skip_input_data(afp, pdu_length); break; } /* Check that we read exactly up to the watchpoint */ if (acr_get_io_watchpoint(afp) != 0) { switch (status) { case ACR_OK: status = ACR_PROTOCOL_ERROR; break; case ACR_END_OF_INPUT: status = ACR_ABNORMAL_END_OF_INPUT; break; } } if (old_watchpoint != ACR_NO_WATCHPOINT) old_watchpoint -= pdu_length - acr_get_io_watchpoint(afp); acr_set_io_watchpoint(afp, old_watchpoint); /* Create the message */ *message = acr_create_message(); acr_message_add_group_list(*message, group); return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_pdu_header @INPUT : afp - acr file pointer @OUTPUT : pdu_type pdu_length @RETURNS : status of input @DESCRIPTION: Reads in the header of a dicom PDU and returns the appropriate values. @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_pdu_header(Acr_File *afp, int *pdu_type, Acr_Long *pdu_length) { unsigned char buffer[PDU_HEADER_LEN]; Acr_Status status; /* Read in PDU type and length */ status = acr_read_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; *pdu_type = (int) buffer[0]; GET_LONG(&buffer[2], pdu_length); return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_assoc_rq @INPUT : afp - acr file pointer @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in an association request @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_assoc_rq(Acr_File *afp, Acr_Group group) { return read_assoc_rq_ac(afp, group, TRUE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_assoc_rq_ac @INPUT : afp - acr file pointer is_request - TRUE if we should handle request type PDU, FALSE if we should handle accept type PDU @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in an association request or accept PDU @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_assoc_rq_ac(Acr_File *afp, Acr_Group group, int is_request) { unsigned char buffer[ASSOC_RQ_LEN - PDU_HEADER_LEN]; Acr_Element item, presentation_context_list, nextitem, followingitem; int have_pres_context_request; Acr_Status status; /* Read in header */ status = acr_read_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; /* Extract appropriate info and add it to the group */ EXTRACT_SHORT(group, DCM_PDU_Protocol_Version, (Acr_Short*)&buffer[6-PDU_HEADER_LEN]); if (is_request) { EXTRACT_UID(group, DCM_PDU_Called_Ap_title, (char *) &buffer[10-PDU_HEADER_LEN], 16); EXTRACT_UID(group, DCM_PDU_Calling_Ap_title, (char *) &buffer[26-PDU_HEADER_LEN], 16); } /* Loop, reading items, until the watchpoint is reached */ presentation_context_list = NULL; while (acr_get_io_watchpoint(afp) > 0) { /* Read in the item (or item list) */ status = read_pdu_item(afp, &item); if (status != ACR_OK) { acr_delete_element_list(item); acr_delete_element_list(presentation_context_list); return status; } /* Loop over items, checking that we got an acceptable one and add it to the appropriate thing */ for (nextitem = item; nextitem != NULL; nextitem = followingitem) { /* We have to get the next item before adding the current one to the list, otherwise we lose the link, since adding sets the next pointer to NULL */ followingitem = acr_get_element_next(nextitem); /* Put presentation context items in a list */ if (acr_match_element_id(DCM_PDU_Presentation_context, nextitem) || acr_match_element_id(DCM_PDU_Presentation_context_reply, nextitem)) { presentation_context_list = acr_element_list_add(presentation_context_list, nextitem); have_pres_context_request = acr_match_element_id(DCM_PDU_Presentation_context, nextitem); } else { acr_group_add_element(group, nextitem); } } } /* Add the presentation context list to the group */ if (have_pres_context_request) { acr_group_add_element(group, acr_create_element_sequence(DCM_PDU_Presentation_context_list, presentation_context_list)); } else { acr_group_add_element(group, acr_create_element_sequence(DCM_PDU_Presentation_context_reply_list, presentation_context_list)); } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_data_tf @INPUT : dicom_afp - acr file pointer for DICOM message level @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in a data PDU @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_data_tf(Acr_File *dicom_afp, Acr_Group group) { Acr_Status status; Acr_Message message; Acr_Group cur, new; Acr_File *real_afp; /* Reset the virtual input stream */ dicom_reset(dicom_afp); /* Set the watchpoint to some very large number (other than ACR_NO_WATCHPOINT) so that acr_input_message will be happy knowing that there is a watchpoint, even though we don't know what it really is until we get close to it. */ acr_set_io_watchpoint(dicom_afp, LONG_MAX-1); /* Get the real afp */ real_afp = get_dicom_real_afp(dicom_afp); if (real_afp == NULL) { (void) fprintf(stderr, "Bad dicom file pointer\n"); exit(EXIT_FAILURE); } /* Set a watchpoint to force the read routine to look for a PDV header */ set_dicom_pdv_watchpoint(dicom_afp, (long) 0); /* Read in the message */ status = acr_input_message(dicom_afp, &message); /* Add the presentation context id to the pdu group */ SAVE_SHORT(group, DCM_PDU_Presentation_context_id, (Acr_Short) acr_get_dicom_pres_context_id(dicom_afp)); /* Get groups and tack them onto the group list that we already have */ if (message != NULL) { new = acr_get_message_group_list(message); cur = group; while (acr_get_group_next(cur) != NULL) { cur = acr_get_group_next(cur); } acr_set_group_next(cur, new); acr_message_reset(message); acr_delete_message(message); } /* Check that we read exactly up to the watchpoint */ if (acr_get_io_watchpoint(real_afp) != 0) { switch (status) { case ACR_OK: status = ACR_PROTOCOL_ERROR; break; case ACR_END_OF_INPUT: status = ACR_ABNORMAL_END_OF_INPUT; break; } } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_rel_rq @INPUT : afp - acr file pointer @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in a release request @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ /* ARGSUSED */ private Acr_Status read_rel_rq(Acr_File *afp, Acr_Group group) { return acr_skip_input_data(afp, (long) ACR_SIZEOF_LONG); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_abort_rq @INPUT : afp - acr file pointer @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in an abort request @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_abort_rq(Acr_File *afp, Acr_Group group) { unsigned char buffer[ABORT_RQ_LEN - PDU_HEADER_LEN]; Acr_Status status; /* Read in request header */ status = acr_read_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; /* Get values */ SAVE_SHORT(group, DCM_PDU_Source, buffer[8 - PDU_HEADER_LEN]); SAVE_SHORT(group, DCM_PDU_Reason, buffer[9 - PDU_HEADER_LEN]); return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_assoc_ac @INPUT : afp - acr file pointer @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in an association accept PDU @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_assoc_ac(Acr_File *afp, Acr_Group group) { return read_assoc_rq_ac(afp, group, FALSE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_assoc_rj @INPUT : afp - acr file pointer @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in an association reject PDU @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_assoc_rj(Acr_File *afp, Acr_Group group) { unsigned char buffer[ASSOC_RJ_LEN - PDU_HEADER_LEN]; Acr_Status status; /* Read in request header */ status = acr_read_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; /* Get values */ SAVE_SHORT(group, DCM_PDU_Result, buffer[7 - PDU_HEADER_LEN]); SAVE_SHORT(group, DCM_PDU_Source, buffer[8 - PDU_HEADER_LEN]); SAVE_SHORT(group, DCM_PDU_Reason, buffer[9 - PDU_HEADER_LEN]); return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_rel_rp @INPUT : afp - acr file pointer @OUTPUT : group - group to which pdu information should be added @RETURNS : status of input @DESCRIPTION: Reads in a release reply @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ /* ARGSUSED */ private Acr_Status read_rel_rp(Acr_File *afp, Acr_Group group) { return acr_skip_input_data(afp, (long) ACR_SIZEOF_LONG); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_pdu_item @INPUT : afp - acr file pointer @OUTPUT : item - element representing value read in @RETURNS : status of input @DESCRIPTION: Reads in any type of PDU item and returns it as an element. The element may either by a real DICOM-type element or may be a sequence item. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_pdu_item(Acr_File *afp, Acr_Element *item) { unsigned char buffer[PDU_ITEM_HEADER_LEN]; Acr_Short item_length; int item_type; long old_watchpoint; Acr_Status status; /* Read in PDU item type and length */ status = acr_read_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; item_type = (int) buffer[0]; GET_SHORT(&buffer[2], &item_length); /* Set a watchpoint for reading after saving the previous watchpoint */ old_watchpoint = acr_get_io_watchpoint(afp); acr_set_io_watchpoint(afp, (long) item_length); /* Call the appropriate routine */ switch (item_type) { case PDU_ITEM_APPLICATION_CONTEXT: status = read_uid_item(afp, DCM_PDU_Application_context, item); break; case PDU_ITEM_PRESENTATION_CONTEXT: status = read_pres_context_item(afp, item); break; case PDU_ITEM_PRES_CONTEXT_REPLY: status = read_pres_context_reply_item(afp, item); break; case PDU_ITEM_ABSTRACT_SYNTAX: status = read_uid_item(afp, DCM_PDU_Abstract_syntax, item); break; case PDU_ITEM_TRANSFER_SYNTAX: status = read_uid_item(afp, DCM_PDU_Transfer_syntax, item); break; case PDU_ITEM_USER_INFORMATION: status = read_user_info_item(afp, item); break; case PDU_ITEM_MAXIMUM_LENGTH: status = read_long_item(afp, DCM_PDU_Maximum_length, item); break; case PDU_ITEM_IMPLEMENTATION_CLASS_UID: status = read_uid_item(afp, DCM_PDU_Implementation_class_uid, item); break; case PDU_ITEM_IMPLEMENTATION_VERSION_NAME: status = read_uid_item(afp, DCM_PDU_Implementation_version_name, item); break; default: status = read_unknown_item(afp, item_type, item); break; } /* Make sure that we read the right amount of data */ if ((status == ACR_OK) && (acr_get_io_watchpoint(afp) != 0)) { status = ACR_PROTOCOL_ERROR; } /* Set the old watchpoint */ if (old_watchpoint != ACR_NO_WATCHPOINT) old_watchpoint -= (long) item_length - acr_get_io_watchpoint(afp); acr_set_io_watchpoint(afp, old_watchpoint); return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_uid_item @INPUT : afp - acr file pointer elid - id of element to be created @OUTPUT : item - element representing value read in @RETURNS : status of input @DESCRIPTION: Reads in a UID item and creates the corresponding element. Data is read up to the next watchpoint. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_uid_item(Acr_File *afp, Acr_Element_Id elid, Acr_Element *item) { unsigned char buffer[MAX_PDU_STRING_LENGTH]; long length; Acr_Status status; /* Set default item */ *item = NULL; /* Figure out how much data to read */ length = acr_get_io_watchpoint(afp); if (length > MAX_PDU_STRING_LENGTH) return ACR_PDU_UID_TOO_LONG; /* Read in the buffer */ status = acr_read_buffer(afp, buffer, length, NULL); if (status != ACR_OK) return status; /* Pull out the uid and create the item */ *item = pdu_create_element_uid(elid, (char *) buffer, (int) length); return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_long_item @INPUT : afp - acr file pointer elid - id of element to be created @OUTPUT : item - element representing value read in @RETURNS : status of input @DESCRIPTION: Reads in an item of type long and creates the corresponding element. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_long_item(Acr_File *afp, Acr_Element_Id elid, Acr_Element *item) { unsigned char buffer[ACR_SIZEOF_LONG]; Acr_Long value; Acr_Status status; /* Set default item */ *item = NULL; /* Check that the right amount of data is to be read */ if (acr_get_io_watchpoint(afp) != ACR_SIZEOF_LONG) return ACR_PROTOCOL_ERROR; /* Read in the buffer and get the value */ status = acr_read_buffer(afp, buffer, (long) ACR_SIZEOF_LONG, NULL); if (status != ACR_OK) return status; GET_LONG((void *) buffer, &value); /* Create the item */ *item = acr_create_element_long(elid, value); return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_unknown_item @INPUT : afp - acr file pointer item_type - type code for item to be read in (should be a value between 0 and 255) @OUTPUT : item - element representing value read in @RETURNS : status of input @DESCRIPTION: Reads in an item of unknown type and creates an element with element id = item_type + ACR_UNKNOWN_PDU_ITEM_OFFSET @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_unknown_item(Acr_File *afp, int item_type, Acr_Element *item) { Acr_Status status; long length; unsigned char *data_pointer; /* Set default item */ *item = NULL; /* Figure out how much data to read */ length = acr_get_io_watchpoint(afp); /* Get space for the data. Add a NUL character to the end in case it is a string */ data_pointer = MALLOC((size_t) length+1); data_pointer[length] = '\0'; /* Read in the buffer and get the value */ status = acr_read_buffer(afp, data_pointer, length, NULL); if (status != ACR_OK) { FREE(data_pointer); return status; } /* Figure out the element id */ item_type += ACR_UNKNOWN_PDU_ITEM_OFFSET; /* Create the item */ *item = acr_create_element(DCM_PDU_GRPID, item_type, ACR_VR_UNKNOWN, length, (char *) data_pointer); return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_pres_context_item @INPUT : afp - acr file pointer @OUTPUT : item - element representing value read in @RETURNS : status of input @DESCRIPTION: Reads in a presentation context item for an associate request and creates the corresponding element. Data is read up to the next watchpoint. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_pres_context_item(Acr_File *afp, Acr_Element *item) { unsigned char buffer[4]; Acr_Element itemlist = NULL, newitem; Acr_Status status; int nitems; /* Set default item */ *item = NULL; /* Read in buffer */ status = acr_read_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; /* Get presentation context id and save it in the item list */ newitem = acr_create_element_short(DCM_PDU_Presentation_context_id, (Acr_Short) buffer[0]); itemlist = acr_element_list_add(itemlist, newitem); /* Read in items until we reach watchpoint */ nitems = 0; while (acr_get_io_watchpoint(afp) > 0) { /* Read in the item and add it to the list */ status = read_pdu_item(afp, &newitem); if (newitem != NULL) { itemlist = acr_element_list_add(itemlist, newitem); } /* Check for a read error */ if (status != ACR_OK) { acr_delete_element_list(itemlist); return status; } /* Make sure that we got the right thing */ if (((nitems == 0) && !acr_match_element_id(DCM_PDU_Abstract_syntax, newitem)) || ((nitems > 0) && !acr_match_element_id(DCM_PDU_Transfer_syntax, newitem))) { acr_delete_element_list(itemlist); return ACR_PROTOCOL_ERROR; } nitems++; } /* Create the item */ *item = acr_create_element_sequence(DCM_PDU_Presentation_context, itemlist); return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_pres_context_reply_item @INPUT : afp - acr file pointer @OUTPUT : item - element representing value read in @RETURNS : status of input @DESCRIPTION: Reads in a presentation context item for an associate accept and creates the corresponding element. Data is read up to the next watchpoint. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_pres_context_reply_item(Acr_File *afp, Acr_Element *item) { unsigned char buffer[4]; Acr_Element itemlist = NULL, newitem; Acr_Status status; /* Set default item */ *item = NULL; /* Read in buffer */ status = acr_read_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; /* Get presentation context id and result and save them in the item list */ newitem = acr_create_element_short(DCM_PDU_Presentation_context_id, (Acr_Short) buffer[0]); itemlist = acr_element_list_add(itemlist, newitem); newitem = acr_create_element_short(DCM_PDU_Result, (Acr_Short) buffer[2]); itemlist = acr_element_list_add(itemlist, newitem); /* Read in items until we reach watchpoint */ while (acr_get_io_watchpoint(afp) > 0) { /* Read in the item and add it to the list */ status = read_pdu_item(afp, &newitem); if (newitem != NULL) { itemlist = acr_element_list_add(itemlist, newitem); } /* Check for a read error */ if (status != ACR_OK) { acr_delete_element_list(itemlist); return status; } /* Make sure that we got the right thing */ if (!acr_match_element_id(DCM_PDU_Transfer_syntax, newitem)) { acr_delete_element_list(itemlist); return ACR_PROTOCOL_ERROR; } } /* Create the item */ *item = acr_create_element_sequence(DCM_PDU_Presentation_context_reply, itemlist); return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_user_info_item @INPUT : afp - acr file pointer @OUTPUT : item - element list representing values read in @RETURNS : status of input @DESCRIPTION: Reads in a user info item and creates the corresponding element list. Data is read up to the next watchpoint. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status read_user_info_item(Acr_File *afp, Acr_Element *item) { Acr_Status status; Acr_Element newitem; /* Set default item */ *item = NULL; /* Read in items until we reach watchpoint */ while (acr_get_io_watchpoint(afp) > 0) { /* Read in the item */ status = read_pdu_item(afp, &newitem); /* Check for a read error */ if (status != ACR_OK) { acr_delete_element_list(newitem); return status; } /* Add the item to the list */ *item = acr_element_list_add(*item, newitem); } return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_uid_string @INPUT : buffer - pointer to start of string length - length of string @OUTPUT : (none) @RETURNS : Pointer to temporary string space containing a copy of the string without leading and trailing blanks. @DESCRIPTION: Removes leading and trailing blanks from a string and copies it into temporary space. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private char *get_uid_string(char *buffer, int length) { static char string[MAX_PDU_STRING_LENGTH]; int start, end, ichar; /* Check for maximum string length */ if (length >= MAX_PDU_STRING_LENGTH) length = MAX_PDU_STRING_LENGTH - 1; /* Skip leading spaces */ for (start=0; (start < length) && isspace((int) buffer[start]); start++) {} /* Look for the last non-space */ for (end=length-1; (end >= 0) && isspace((int) buffer[end]); end--) {} /* Copy the string */ for (ichar=start; ichar <= end; ichar++) { string[ichar-start] = buffer[ichar]; } /* Finish off the string. Pad the string with a blank if needed to give an even length */ if (((end-start+1) % 2) != 0) { /* Odd length */ string[++end] = ' '; } string[end+1] = '\0'; return string; } /* ----------------------------- MNI Header ----------------------------------- @NAME : pdu_create_element_uid @INPUT : elid - Element id structure value - pointer to start of string length - length of string @OUTPUT : (none) @RETURNS : Pointer to newly created element @DESCRIPTION: Creates an element containing a string of fixed length. Leading and trailing spaces are removed. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Element pdu_create_element_uid(Acr_Element_Id elid, char *value, int length) { Acr_Element item; item = acr_create_element_string(elid, get_uid_string(value, length)); acr_set_element_vr(item, ACR_VR_UI); return item; } /* ----------------------------- MNI Header ----------------------------------- @NAME : pdu_create_element_short @INPUT : elid - Element id structure value - pointer to location containing short @OUTPUT : (none) @RETURNS : Pointer to newly created element @DESCRIPTION: Creates an element containing a short which is converted from the input format. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Element pdu_create_element_short(Acr_Element_Id elid, void *input_value) { Acr_Short svalue; GET_SHORT(input_value, &svalue); return acr_create_element_short(elid, svalue); } /*****************************************************************************/ /*************************** OUTPUT ROUTINES *********************************/ /*****************************************************************************/ /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_output_dicom_message @INPUT : dicom_afp - acr file pointer for dicom output message - the message to write out @OUTPUT : (none) @RETURNS : status of output @DESCRIPTION: Writes out a dicom message. @METHOD : Although dicom connection, etc. syntaxes differ from the message syntax, this routine and the ones following take a message in the same form. @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Acr_Status acr_output_dicom_message(Acr_File *dicom_afp, Acr_Message message) { int pdu_type; Acr_Group group_list; Acr_File *afp; Acr_Status status; /* Get real afp */ afp = get_dicom_real_afp(dicom_afp); if (afp == NULL) { (void) fprintf(stderr, "Bad dicom file pointer\n"); exit(EXIT_FAILURE); } /* Get group list */ group_list = acr_get_message_group_list(message); /* Switch on pdu type. If the type is not found, then assume that we are writing data. */ pdu_type = acr_find_short(group_list, DCM_PDU_Type, ACR_PDU_DATA_TF); switch (pdu_type) { case ACR_PDU_ASSOC_RQ: status = write_assoc_rq(afp, group_list); break; case ACR_PDU_ASSOC_AC: status = write_assoc_ac(afp, group_list); break; case ACR_PDU_ASSOC_RJ: status = write_assoc_rj(afp, group_list); break; case ACR_PDU_DATA_TF: status = write_data_tf(dicom_afp, message); break; case ACR_PDU_REL_RQ: status = write_rel_rq(afp, group_list); break; case ACR_PDU_REL_RP: status = write_rel_rp(afp, group_list); break; case ACR_PDU_ABORT_RQ: status = write_abort_rq(afp, group_list); break; default: (void) fprintf(stderr, "Unrecognized pdu type for output (%d)\n", pdu_type); status = ACR_PROTOCOL_ERROR; } /* Flush the output buffer */ if ((acr_file_flush(afp) == EOF) && (status == ACR_OK)) { status = ACR_ABNORMAL_END_OF_OUTPUT; } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_assoc_rq @INPUT : afp - acr file pointer group - info to write @OUTPUT : (none) @RETURNS : status of output @DESCRIPTION: Writes out an association request @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status write_assoc_rq(Acr_File *afp, Acr_Group group) { return write_assoc_rq_ac(afp, group, TRUE, NULL); } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_assoc_ac @INPUT : afp - acr file pointer group - info to write @OUTPUT : (none) @RETURNS : status of output @DESCRIPTION: Writes out an association accept @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status write_assoc_ac(Acr_File *afp, Acr_Group group) { return write_assoc_rq_ac(afp, group, FALSE, NULL); } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_assoc_rq_ac @INPUT : afp - acr file pointer group - info to write is_request - TRUE if we should handle request type PDU, FALSE if we should handle accept type PDU @OUTPUT : length - if non-NULL, then nothing is written and the value is incremented by the amount of data written out. @RETURNS : status of output @DESCRIPTION: Writes out an association request or accept PDU @METHOD : Can be used to write out a PDU or calculate its length. If length is non-NULL, then length calculation is done and nothing is written out. Otherwise the PDU is written out. This routine calls itself to work out the PDU length. @GLOBALS : @CALLS : @CREATED : February 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status write_assoc_rq_ac(Acr_File *afp, Acr_Group group, int is_request, long *length) { unsigned char buffer[ASSOC_RQ_LEN]; long pdu_length; int do_write; int offset; Acr_Short svalue; Acr_Long lvalue; Acr_Element element; Acr_Status status; Acr_Element_Id elid; /* Should we write or calculate length */ do_write = (length == NULL); /* Write out the first part of the PDU */ if (do_write) { /* Zero the buffer */ for (offset=0; offset 0) && isspace(uid[uid_length-1])) {uid_length--;} /* Write out the uid */ if (do_write) { status = acr_write_buffer(afp, (unsigned char *)uid, uid_length, NULL); if (status != ACR_OK) return status; } else { *length += uid_length; } #if 0 /* Check that we wrote an even number of bytes */ if ((uid_length % 2) != 0) { if (do_write) { (void) acr_putc((int) ' ', afp); } else { *length += 1; } } #endif return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_pres_context_item @INPUT : afp - acr file pointer item - information to write out @OUTPUT : length - if non-NULL, then routine computes length of output @RETURNS : status of output @DESCRIPTION: Writes out a presentation context item (or reply item). @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status write_pres_context_item(Acr_File *afp, Acr_Element item, int is_request, long *length) { unsigned char buffer[PDU_ITEM_HEADER_LEN+4]; long item_length; Acr_Status status; int do_write; Acr_Element itemlist, subitem; Acr_Short svalue; /* Check element */ if ((item == NULL) || (!acr_element_is_sequence(item))) { return ACR_PROTOCOL_ERROR; } itemlist = (Acr_Element) acr_get_element_data(item); /* Check whether we are writing or counting */ do_write = (length == NULL); /* Write item header */ if (do_write) { buffer[0] = (is_request ? PDU_ITEM_PRESENTATION_CONTEXT : PDU_ITEM_PRES_CONTEXT_REPLY); buffer[1] = 0; item_length = 0; (void) write_pres_context_item(afp, item, is_request, &item_length); item_length -= PDU_ITEM_HEADER_LEN; svalue = (Acr_Short) item_length; PUT_SHORT(&svalue, (Acr_Short*)&buffer[2]); subitem = acr_find_element_id(itemlist, DCM_PDU_Presentation_context_id); if (subitem == NULL) return ACR_PROTOCOL_ERROR; buffer[4] = (unsigned char) acr_get_element_short(subitem); buffer[5] = 0; if (!is_request) { subitem = acr_find_element_id(itemlist, DCM_PDU_Result); if (subitem == NULL) return ACR_PROTOCOL_ERROR; buffer[6] = (unsigned char) acr_get_element_short(subitem); } else buffer[6] = 0; buffer[7] = 0; status = acr_write_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; } else { *length += sizeof(buffer); } /* Write out the transfer syntaxes */ if (is_request) { subitem = acr_find_element_id(itemlist, DCM_PDU_Abstract_syntax); if (subitem == NULL) return ACR_PROTOCOL_ERROR; status = write_uid_item(afp, subitem, PDU_ITEM_ABSTRACT_SYNTAX, length); if (status != ACR_OK) return status; subitem = itemlist; while (subitem != NULL) { if (acr_match_element_id(DCM_PDU_Transfer_syntax, subitem)) { status = write_uid_item(afp, subitem, PDU_ITEM_TRANSFER_SYNTAX, length); if (status != ACR_OK) return status; } subitem = acr_get_element_next(subitem); } } else { subitem = acr_find_element_id(itemlist, DCM_PDU_Transfer_syntax); if (subitem == NULL) return ACR_PROTOCOL_ERROR; status = write_uid_item(afp, subitem, PDU_ITEM_TRANSFER_SYNTAX, length); if (status != ACR_OK) return status; } return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_user_info_item @INPUT : afp - acr file pointer group - information to write out @OUTPUT : length - if non-NULL, then routine computes length of output @RETURNS : status of output @DESCRIPTION: Writes out a user info item @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status write_user_info_item(Acr_File *afp, Acr_Group group, long *length) { unsigned char buffer[2*PDU_ITEM_HEADER_LEN+ACR_SIZEOF_LONG]; long item_length; Acr_Long maximum_length; Acr_Status status; int do_write; Acr_Short svalue; Acr_Element element; int item_type; /* Check whether we are writing or counting */ do_write = (length == NULL); /* Write item header */ if (do_write) { buffer[0] = PDU_ITEM_USER_INFORMATION; buffer[1] = 0; item_length = 0; (void) write_user_info_item(afp, group, &item_length); item_length -= PDU_ITEM_HEADER_LEN; svalue = (Acr_Short) item_length; PUT_SHORT(&svalue, (Acr_Short*)&buffer[2]); buffer[4] = PDU_ITEM_MAXIMUM_LENGTH; buffer[5] = 0; svalue = ACR_SIZEOF_LONG; PUT_SHORT(&svalue, (Acr_Short*)&buffer[6]); maximum_length = acr_find_long(group, DCM_PDU_Maximum_length, 0); PUT_LONG(&maximum_length, (Acr_Long*)&buffer[8]); status = acr_write_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; } else { *length += sizeof(buffer); } /* Write out implementation information */ element = acr_find_group_element(group, DCM_PDU_Implementation_class_uid); if (element != NULL) { status = write_unknown_item(afp, PDU_ITEM_IMPLEMENTATION_CLASS_UID, acr_get_element_length(element), acr_get_element_data(element), length); if (status != ACR_OK) return status; } element = acr_find_group_element(group, DCM_PDU_Implementation_version_name); if (element != NULL) { status = write_unknown_item(afp, PDU_ITEM_IMPLEMENTATION_VERSION_NAME, acr_get_element_length(element), acr_get_element_data(element), length); if (status != ACR_OK) return status; } /* Write any unknown items with an item type > PDU_ITEM_USER_INFORMATION */ if (acr_get_group_group(group) == DCM_PDU_GRPID) { /* Loop over all elements */ for (element = acr_get_group_element_list(group); element != NULL; element = acr_get_element_next(element)) { /* Check that the element is unknown and that it is an user info item */ item_type = acr_get_element_element(element); if (item_type < ACR_UNKNOWN_PDU_ITEM_OFFSET) continue; item_type -= ACR_UNKNOWN_PDU_ITEM_OFFSET; if (item_type < PDU_ITEM_USER_INFORMATION) continue; /* Write out the value */ status = write_unknown_item(afp, item_type, acr_get_element_length(element), acr_get_element_data(element), length); if (status != ACR_OK) return status; } } return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_unknown_item @INPUT : afp - acr file pointer item_type - code identifying item to be written out data_length - length of data to be written data_pointer - pointer to data @OUTPUT : length - if non-NULL, then nothing is written and the value is incremented by the amount of data written out. @RETURNS : status of output @DESCRIPTION: Writes out an item of unknown type. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Status write_unknown_item(Acr_File *afp, int item_type, long data_length, char *data_pointer, long *length) { unsigned char buffer[PDU_ITEM_HEADER_LEN]; long item_length; int do_write; Acr_Status status; Acr_Short svalue; /* Check whether we are writing or counting */ do_write = (length == NULL); /* Write item header */ if (do_write) { buffer[0] = (unsigned char) item_type; buffer[1] = 0; item_length = 0; (void) write_unknown_item(afp, item_type, data_length, data_pointer, &item_length); item_length -= PDU_ITEM_HEADER_LEN; svalue = (Acr_Short) item_length; PUT_SHORT(&svalue, (Acr_Short*)&buffer[2]); status = acr_write_buffer(afp, buffer, sizeof(buffer), NULL); if (status != ACR_OK) return status; } else { *length += sizeof(buffer); } /* Write out the data */ if (do_write) { status = acr_write_buffer(afp, (unsigned char *) data_pointer, data_length, NULL); if (status != ACR_OK) return status; } else { *length += data_length; } return ACR_OK; } /* ----------------------------- MNI Header ----------------------------------- @NAME : pdu_copy_uid @INPUT : string length - maximum length of uid @OUTPUT : buffer @RETURNS : (nothing) @DESCRIPTION: Copies a uid from string to buffer, padding with trailing blanks up to length. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private void pdu_copy_uid(Acr_String string, char *buffer, int length) { int i; for (i=0; (i < length) && (string[i] != '\0'); i++) { buffer[i] = string[i]; } for (; (i < length); i++) { buffer[i] = ' '; } } /*****************************************************************************/ /************************** DICOM I/O STREAM *********************************/ /*****************************************************************************/ /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_initialize_dicom_input @INPUT : io_data - pointer to data for read and write routines maxlength - maximum length for a single read or write (zero or negative means use internal maximum). io_routine - routine to read or write data @OUTPUT : (none) @RETURNS : pointer to Acr_File structure created @DESCRIPTION: Sets up the routines for reading dicom messages from an input stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Acr_File *acr_initialize_dicom_input(void *io_data, int maxlength, Acr_Io_Routine io_routine) { return initialize_dicom_stream(io_data, maxlength, io_routine, DICOM_INPUT); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dicom_set_ismore_function @INPUT : afp ismore_function @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Sets the function to be used for testing if there is more data waiting on the input stream. stream. @METHOD : @GLOBALS : @CALLS : @CREATED : May 17, 2000 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_dicom_set_ismore_function(Acr_File *afp, Acr_Ismore_Function ismore_function) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); /* Set the dicom ismore function on the virtual stream and the user-supplied one on the real stream */ if (stream_data == NULL) { acr_file_set_ismore_function(afp, ismore_function); } else { acr_file_set_ismore_function(stream_data->virtual_afp, dicom_ismore); acr_file_set_ismore_function(stream_data->real_afp, ismore_function); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_initialize_dicom_output @INPUT : io_data - pointer to data for read and write routines maxlength - maximum length for a single read or write (zero or negative means use internal maximum). io_routine - routine to read or write data @OUTPUT : (none) @RETURNS : pointer to Acr_File structure created @DESCRIPTION: Sets up the routines for writing dicom messages to an output stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Acr_File *acr_initialize_dicom_output(void *io_data, int maxlength, Acr_Io_Routine io_routine) { return initialize_dicom_stream(io_data, maxlength, io_routine, DICOM_OUTPUT); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_close_dicom_file @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Closes a dicom output stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_close_dicom_file(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); /* Flush the virtual stream */ (void) acr_file_flush(afp); /* Close the real stream */ if (stream_data != NULL) { acr_file_free(stream_data->real_afp); if (stream_data->client_data != NULL) { FREE(stream_data->client_data); } } /* Free the virtual stream. This will free the stream data structure. */ acr_file_free(afp); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dicom_get_io_data @INPUT : afp @OUTPUT : (none) @RETURNS : pointer to io data @DESCRIPTION: Gets back pointer that was passed in to acr_initialize_dicom_{input,output}. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void *acr_dicom_get_io_data(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); /* Get the io pointer for the real stream */ return acr_file_get_io_data(stream_data->real_afp); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dicom_enable_trace / acr_dicom_disable_trace @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Enables / disables trace on a dicom stream (on the real stream) @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_dicom_enable_trace(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); acr_file_enable_trace((stream_data == NULL) ? afp : stream_data->real_afp); } public void acr_dicom_disable_trace(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); acr_file_disable_trace((stream_data == NULL) ? afp : stream_data->real_afp); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dicom_set_eof @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Tells the input or output stream that it has reached the end of file so that no more data will be read or written. This can be useful for preventing further reading or writing if an alarm goes off, for example. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_dicom_set_eof(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); /* Set eof on both afp's */ acr_file_set_eof(afp); acr_file_set_eof(stream_data->real_afp); } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_dicom_stream @INPUT : io_data - pointer to data for read and write routines maxlength - maximum length for a single read or write (zero or negative means use internal maximum). io_routine - routine to read or write data stream_type - DICOM_INPUT or DICOM_OUTPUT @OUTPUT : (none) @RETURNS : pointer to Acr_File structure created @DESCRIPTION: Sets up the routines for dicom i/o @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_File *initialize_dicom_stream(void *io_data, int maxlength, Acr_Io_Routine io_routine, Dicom_IO_stream_type stream_type) { Acr_File *real_afp, *virtual_afp; Acr_Dicom_IO *stream_data; Acr_Io_Routine virtual_io_routine; /* Create the real input stream */ real_afp = acr_file_initialize(io_data, maxlength, io_routine); /* Create the virtual afp data */ stream_data = MALLOC(sizeof(*stream_data)); stream_data->stream_type = stream_type; stream_data->real_afp = real_afp; stream_data->presentation_context_id = 0; stream_data->pdv_watchpoint = ACR_NO_WATCHPOINT; stream_data->maximum_length = LONG_MAX; stream_data->writing_command = FALSE; stream_data->data_length = 0; stream_data->client_data = NULL; /* Create the virtual input stream */ if (stream_type == DICOM_INPUT) { virtual_io_routine = dicom_input_routine; } else { virtual_io_routine = dicom_output_routine; } virtual_afp = acr_file_initialize((void *) stream_data, 0, virtual_io_routine); stream_data->virtual_afp = virtual_afp; return virtual_afp; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dicom_io_pointer @INPUT : afp @OUTPUT : (none) @RETURNS : pointer to Acr_Dicom_IO structure or NULL if an error occurs @DESCRIPTION: Gets the pointer to the Acr_Dicom_IO structure contained within the afp. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_Dicom_IO *get_dicom_io_pointer(Acr_File *afp) { Acr_Dicom_IO *stream_data; stream_data = (Acr_Dicom_IO *) acr_file_get_io_data(afp); if ((stream_data == NULL) || ((stream_data->stream_type != DICOM_INPUT) && (stream_data->stream_type != DICOM_OUTPUT))) { return NULL; } return stream_data; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dicom_real_afp @INPUT : afp @OUTPUT : (none) @RETURNS : pointer to Acr_File for real input or output @DESCRIPTION: Gets the pointer to the Acr_File structure that is really connected to a stdio input or output stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Acr_File *get_dicom_real_afp(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return NULL; /* Return the afp */ return stream_data->real_afp; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dicom_pdv_watchpoint @INPUT : afp @OUTPUT : (none) @RETURNS : Distance from current position to pdv watchpoint on real stream @DESCRIPTION: Returns the distance to the PDV watchpoint on the real i/o stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private long get_dicom_pdv_watchpoint(Acr_File *afp) { Acr_Dicom_IO *stream_data; long current_watchpoint; stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return ACR_NO_WATCHPOINT; current_watchpoint = acr_get_io_watchpoint(stream_data->real_afp); if ((stream_data->pdv_watchpoint == ACR_NO_WATCHPOINT) || (current_watchpoint == ACR_NO_WATCHPOINT)) { return ACR_NO_WATCHPOINT; } else { return current_watchpoint - stream_data->pdv_watchpoint; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_dicom_pdv_watchpoint @INPUT : afp pdv_watchpoint - distance to pdu watchpoint @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Sets the watchpoint for the PDV relative to the current position. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private void set_dicom_pdv_watchpoint(Acr_File *afp, long pdv_watchpoint) { Acr_Dicom_IO *stream_data; long current_watchpoint; stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return; current_watchpoint = acr_get_io_watchpoint(stream_data->real_afp); if (pdv_watchpoint == ACR_NO_WATCHPOINT) { stream_data->pdv_watchpoint = ACR_NO_WATCHPOINT; } else if (current_watchpoint == ACR_NO_WATCHPOINT) { acr_set_io_watchpoint(stream_data->real_afp, pdv_watchpoint); stream_data->pdv_watchpoint = 0; } else { stream_data->pdv_watchpoint = current_watchpoint - pdv_watchpoint; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_dicom_maximum_length @INPUT : afp maximum_length - if <= 0, then a very large value is used @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Sets the maximum PDU length for a dicom stream. If the length is unreasonably small (<= PDV header length) then a more reasonable value is set. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_set_dicom_maximum_length(Acr_File *afp, long maximum_length) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return; /* Set the maximum length */ if (maximum_length <= 0) maximum_length = LONG_MAX; else if (maximum_length <= DATA_TF_LEN) maximum_length = DATA_TF_LEN * 2; stream_data->maximum_length = maximum_length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_dicom_pres_context_id @INPUT : afp presentation_context_id - presentation context id to use @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Sets the presentation context id for an i/o stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_set_dicom_pres_context_id(Acr_File *afp, int presentation_context_id) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return; /* Set the id */ stream_data->presentation_context_id = presentation_context_id; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_dicom_pres_context_id @INPUT : afp @OUTPUT : (none) @RETURNS : presentation context id @DESCRIPTION: Gets the presentation context id for an i/o stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_get_dicom_pres_context_id(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return 0; /* Return the id */ return stream_data->presentation_context_id; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_dicom_client_data @INPUT : afp client_data - pointer to client data to store @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Stores a pointer to client data @METHOD : @GLOBALS : @CALLS : @CREATED : November 11, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_set_dicom_client_data(Acr_File *afp, void *client_data) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return; /* Check for an old value */ if (stream_data->client_data != NULL) { FREE(stream_data->client_data); } /* Set the pointer */ stream_data->client_data = client_data; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_dicom_client_data @INPUT : afp @OUTPUT : (none) @RETURNS : pointer to client data @DESCRIPTION: Gets the pointer to the client data @METHOD : @GLOBALS : @CALLS : @CREATED : November 11, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void *acr_get_dicom_client_data(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return 0; /* Return the pointer */ return stream_data->client_data; } /* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_reset @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Resets the dicom (virtual) stream @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private void dicom_reset(Acr_File *afp) { Acr_Dicom_IO *stream_data; /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return; /* Do the reset and mark this as the first time */ acr_file_reset(afp); set_dicom_pdv_watchpoint(afp, ACR_NO_WATCHPOINT); } /* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_setup_output @INPUT : afp command_length - length of command portion of message data_length - length of data portion of message @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Sets up the dicom virtual stream to handle data output @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private void dicom_setup_output(Acr_File *afp, long command_length, long data_length) { Acr_Dicom_IO *stream_data; /* Reset the stream */ dicom_reset(afp); /* Get the structure pointer */ stream_data = get_dicom_io_pointer(afp); if (stream_data == NULL) return; /* Set real afp watchpoint to zero to force a PDU header right away */ acr_set_io_watchpoint(stream_data->real_afp, 0); set_dicom_pdv_watchpoint(afp, 0); /* Figure out whether we are starting with a command or data, save the data length and set the watchpoint so that we can figure out when to change from command to data */ if (command_length > 0) { stream_data->writing_command = TRUE; stream_data->data_length = data_length; acr_set_io_watchpoint(afp, command_length); } else { stream_data->writing_command = FALSE; stream_data->data_length = data_length; acr_set_io_watchpoint(afp, data_length); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_input_routine @INPUT : io_data nbytes - number of bytes to read @OUTPUT : buffer - buffer into which we will read @RETURNS : Number of bytes read. @DESCRIPTION: Dicom input routine for reading from a real input stream into a virtual input stream. @METHOD : We use three watchpoints. One on the real stream to mark the end of the PDU. One in stream data structure to mark the end of the PDV. One is set on the virtual (dicom) stream when we find the last fragment of a message to mark the end of the message data. @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int dicom_input_routine(void *io_data, void *buffer, int nbytes) { unsigned char header_buffer[DATA_TF_LEN]; Acr_Dicom_IO *stream_data; long nread; int pdu_type; Acr_Long pdu_length, pdv_length; long pdv_watchpoint; Acr_Status status; int presentation_context_id, control_header; Acr_File *real_afp, *dicom_afp; /* Get file pointer */ if (io_data == NULL) return 0; stream_data = (Acr_Dicom_IO *) io_data; real_afp = stream_data->real_afp; dicom_afp = stream_data->virtual_afp; /* Get distance to next watchpoint on real stream */ pdv_watchpoint = get_dicom_pdv_watchpoint(dicom_afp); /* Check whether we need to read in some more headers */ if (pdv_watchpoint <= 0) { /* Do we need to read in a PDU header? */ if (acr_get_io_watchpoint(real_afp) <= 0) { acr_set_io_watchpoint(real_afp, PDU_HEADER_LEN + sizeof(header_buffer)); status = read_pdu_header(real_afp, &pdu_type, &pdu_length); if ((status != ACR_OK) || (pdu_type != ACR_PDU_DATA_TF)) { return -1; } acr_set_io_watchpoint(real_afp, pdu_length); } /* Read in the PDV header */ status = acr_read_buffer(real_afp, header_buffer, sizeof(header_buffer), NULL); if (status != ACR_OK) return -1; GET_LONG((void *) header_buffer, &pdv_length); pdv_length -= 2; presentation_context_id = (int) header_buffer[ACR_SIZEOF_LONG]; control_header = (int) header_buffer[ACR_SIZEOF_LONG+1]; /* Check for a bad PDV length compared to PDU length */ if (pdv_length > acr_get_io_watchpoint(real_afp)) { return -1; } /* Set the watchpoint for this PDV */ set_dicom_pdv_watchpoint(dicom_afp, (long)pdv_length); pdv_watchpoint = (long)pdv_length; /* Save the presentation context id */ acr_set_dicom_pres_context_id(dicom_afp, presentation_context_id); /* Check whether this is the last fragment. If it is, set the watchpoint. */ if ((control_header & PDV_LAST_FRAGMENT_MASK) && ((long)pdv_length == acr_get_io_watchpoint(real_afp))) { acr_set_io_watchpoint(dicom_afp, (long)pdv_length); } } /* Make sure that we don't read too far */ if (nbytes > pdv_watchpoint) { nbytes = pdv_watchpoint; } /* Read the data into the buffer */ status = acr_read_buffer(real_afp, buffer, (long) nbytes, &nread); return (int) nread; } /* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_output_routine @INPUT : io_data nbytes - number of bytes to write @OUTPUT : buffer - buffer into which we will write @RETURNS : Number of bytes written. @DESCRIPTION: Dicom output routine for writing a virtual output stream into a real output stream. @METHOD : We use three watchpoints. One one the real stream to mark the end of the next PDV. One stored in the stream data structure to indicate the end of the PDU (this is relative to the end of the PDV watchpoint). One on the virtual stream to mark the end of the command or of the data. @METHOD : We use three watchpoints. One on the real stream to mark the end of the PDU. One in stream data structure to mark the end of the PDV. One is set on the virtual (dicom) stream to mark the end of the command or data. @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int dicom_output_routine(void *io_data, void *buffer, int nbytes) { unsigned char pdu_buffer[PDU_HEADER_LEN]; unsigned char header_buffer[DATA_TF_LEN]; Acr_Dicom_IO *stream_data; Acr_File *real_afp, *dicom_afp; Acr_Long pdu_length, pdv_length; long message_watchpoint, pdv_watchpoint, data_length, pdu_watchpoint; long nwritten; int total_written, bytes_to_write; Acr_Status status; int message_control_header; /* Get file pointer */ if (io_data == NULL) return 0; stream_data = (Acr_Dicom_IO *) io_data; real_afp = stream_data->real_afp; dicom_afp = stream_data->virtual_afp; /* Get distances to watchpoints */ pdv_watchpoint = get_dicom_pdv_watchpoint(dicom_afp); message_watchpoint = acr_get_io_watchpoint(dicom_afp); /* Make sure that we have not gone too far */ if (message_watchpoint < 0) { return -1; } /* Loop until we have written out the whole buffer */ total_written = 0; while (nbytes > 0) { /* Check whether we need to write out more headers */ if (pdv_watchpoint <= 0) { /* If the PDU watchpoint is <= 0, then we need to write out a PDU header. */ if (acr_get_io_watchpoint(real_afp) <= 0) { /* Figure out pdu length */ pdu_length = 0; /* Get data length */ data_length = (stream_data->writing_command ? stream_data->data_length : message_watchpoint + nbytes); /* Add in command length if needed */ if (stream_data->writing_command) { pdu_length += sizeof(header_buffer) + message_watchpoint + nbytes; } /* Add in data length if needed, making sure that we can get some data into this pdu */ if ((data_length > 0) && (pdu_length+sizeof(header_buffer) < stream_data->maximum_length)) { pdu_length += sizeof(header_buffer) + data_length; } /* Check that we haven't exceeded the maximum length */ if (pdu_length > stream_data->maximum_length) { pdu_length = stream_data->maximum_length; } /* Set the PDU watchpoint */ acr_set_io_watchpoint(real_afp, pdu_length + sizeof(pdu_buffer)); /* Write out the buffer */ pdu_buffer[0] = ACR_PDU_DATA_TF; pdu_buffer[1] = 0; PUT_LONG(&pdu_length, (Acr_Long*)&pdu_buffer[2]); status = acr_write_buffer(real_afp, pdu_buffer, sizeof(pdu_buffer), NULL); if (status != ACR_OK) return total_written; } /* If PDU watchpoint <= 0 */ /* Get info for PDV header */ message_control_header = 0; if (stream_data->writing_command) { message_control_header |= PDV_COMMAND_PDV_MASK; } /* Get length of PDV, making sure that it will fit in the PDU */ pdv_length = message_watchpoint + nbytes; pdu_watchpoint = acr_get_io_watchpoint(real_afp); if ((pdv_length + sizeof(header_buffer)) > pdu_watchpoint) { pdv_length = pdu_watchpoint - sizeof(header_buffer); } else { message_control_header |= PDV_LAST_FRAGMENT_MASK; } pdv_length += 2; /* Write out PDV header */ PUT_LONG(&pdv_length, (Acr_Long*)&header_buffer[0]); header_buffer[4] = (unsigned char) stream_data->presentation_context_id; header_buffer[5] = (unsigned char) message_control_header; status = acr_write_buffer(real_afp, header_buffer, sizeof(header_buffer), NULL); if (status != ACR_OK) return total_written; /* Set the watchpoint for this PDV */ pdv_length -= 2; if ((pdv_length <= 0) || (pdv_length > acr_get_io_watchpoint(real_afp))) return total_written; set_dicom_pdv_watchpoint(dicom_afp, pdv_length); pdv_watchpoint = pdv_length; } /* If pdv_watchpoint <= 0 */ /* Write out data */ bytes_to_write = nbytes; if (nbytes >= pdv_watchpoint) { bytes_to_write = pdv_watchpoint; } status = acr_write_buffer(real_afp, buffer, bytes_to_write, &nwritten); total_written += nwritten; if (nwritten < bytes_to_write) return total_written; nbytes -= bytes_to_write; buffer = (void *) ((char *) buffer + bytes_to_write); pdv_watchpoint -= bytes_to_write; } /* While nbytes > 0 */ /* Check for end of command part */ if (stream_data->writing_command && (message_watchpoint == 0)) { acr_set_io_watchpoint(dicom_afp, stream_data->data_length); stream_data->writing_command = FALSE; } return total_written; } /* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_ismore @INPUT : io_data @OUTPUT : (nothing) @RETURNS : 1 if more data is waiting, 0 if not, and -1 if EOF or error. @DESCRIPTION: Routine for testing for waiting data on a dicom input stream. @METHOD : @GLOBALS : @CALLS : @CREATED : May 17, 2000 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int dicom_ismore(void *io_data) { Acr_Dicom_IO *stream_data; /* Get file pointer */ if (io_data == NULL) return -1; stream_data = (Acr_Dicom_IO *) io_data; /* Call ismore function for real stream */ return acr_file_ismore(stream_data->real_afp); } minc-2.2.00/conversion/Acr_nema/element.c0000644000265600003100000017001512027132660015131 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : element.c @DESCRIPTION: Routines for doing acr_nema element operations. @METHOD : @GLOBALS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : * $Log: element.c,v $ * Revision 6.12 2008-08-12 05:00:22 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.11 2006/09/01 16:33:49 jharlap * fixed bug in Acr_nema that caused dump_acr_nema to skip all elements with element number 0x0010 when it should only have skipped 0x7fe0,0x0010. * * Revision 6.10 2006/04/09 15:28:40 bert * Add functions acr_get_element_double_array and acr_create_element_double * * Revision 6.9 2006/03/10 19:22:56 bert * Update to conversion/Acr_nema/element.c for value printing * * Revision 6.8 2005/07/14 15:56:56 bert * Print raw byte data when dumping fields with unknown value representations and sizes other than 2 or 4. (ported from 1.X) * * Revision 6.7.2.2 2005/06/06 20:48:14 bert * Print raw byte data when dumping fields with unknown value representations and sizes other than 2 or 4. * * Revision 6.7.2.1 2005/05/12 21:15:30 bert * Initial checkin * * Revision 6.7 2005/04/18 23:22:29 bert * Initialize newlist in acr_copy_element() to avoid problems with empty lists * * Revision 6.6 2005/03/11 22:05:29 bert * Implement _acr_name_proc to allow printing of field names in dump_acr_nema * * Revision 6.5 2005/03/04 00:25:54 bert * Avoid memory leak by freeing unused elements in a sequence. Fix order of initialization in acr_create_element() to set variable length property correctly. Don't change VR encoding when parsing a sequence, rely on the new handling of 0xfffe group items by the acr_io functions * * Revision 6.4 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.3 2002/12/07 01:37:24 neelin * Added missing type * * Revision 6.2 2001/12/12 19:00:54 neelin * Corrected error in reading of a sequence element. When making a linked * list of items, previtem was not being updated properly and items were * being dropped. This exhibited itself as protocol error since an incorrect * element length was being computed. (Thanks to Roch Comeau for pointing * this out.) * * Revision 6.1 1999/10/29 17:51:52 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.2 1997/09/02 22:52:12 neelin * Fixed padding of of UI strings and got rid of acr_string_pad_char * function. * * Revision 5.1 1997/08/22 15:08:34 neelin * Added routine acr_string_pad_char to set character used for padding * strings to an even number of bytes. * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.1 1997/05/13 22:46:25 neelin * Modified behaviour of acr_create_element_string (and numeric) so that * the VR type is taken from the elid if it is specified there. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.2 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.1 1995/11/16 13:13:49 neelin * Added include of math.h to get declaration of strtod under SunOs * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:10 neelin * Release of minc version 0.2 * * Revision 1.8 94/09/28 10:35:44 neelin * Pre-release * * Revision 1.7 93/11/30 12:19:15 neelin * Handle MALLOC returning NULL because of extremely large data element length. * * Revision 1.6 93/11/30 08:57:28 neelin * Added element copy routine. * * Revision 1.5 93/11/26 18:47:36 neelin * Added element copy routine. * * Revision 1.4 93/11/25 10:35:34 neelin * Ensure that strings have an even length (pad with space). * * Revision 1.3 93/11/24 11:25:14 neelin * Changed short to unsigned short. * * Revision 1.2 93/11/22 13:11:34 neelin * Added Acr_Element_Id code. * * Revision 1.1 93/11/19 12:48:12 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include /* Private functions */ static void delete_element_data(Acr_Element element); static Acr_Element create_element_mem(Acr_Element_Id elid, Acr_VR_Type vr_code, size_t value_size, void *value); /* Macros */ #define SIZEOF_ARRAY(a) (sizeof(a)/sizeof(a[0])) /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_element @INPUT : group_id element_id vr_code - Internal VR code data_length - if < 0, then data is assumed to be a pointer to a list of elements in the sequence data_pointer - pointer to actual data or to list of elements @OUTPUT : (none) @RETURNS : Pointer to element structure @DESCRIPTION: Creates an acr-nema element structure. If data_length is negative, then the element is a sequence and the data_pointer must point to a list of elements. In this case, the element is assumed to have variable length. If the element is an ACR_VR_SQ, then it is possible to change it to have fixed length by calling acr_set_element_variable_length with FALSE. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : February 4, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Element acr_create_element(int group_id, int element_id, Acr_VR_Type vr_code, long data_length, char *data_pointer) { Acr_Element element; /* Allocate the element. We set the data pointer to NULL so that acr_set_element_data does not try to free an unitialized pointer */ element = MALLOC(sizeof(*element)); element->data_pointer = NULL; /* Assign fields */ acr_set_element_id(element, group_id, element_id); acr_set_element_vr(element, vr_code); acr_set_element_vr_encoding(element, ACR_EXPLICIT_VR); acr_set_element_byte_order(element, acr_get_machine_byte_order()); acr_set_element_next(element, NULL); acr_set_element_data(element, data_length, data_pointer); acr_set_element_variable_length(element, (data_length < 0)); return element; } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_element_data @INPUT : element @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Deletes element data, but leaves element in an intermediate state with dangling pointers and incorrect lengths. @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void delete_element_data(Acr_Element element) { char *data_pointer; data_pointer = acr_get_element_data(element); if (data_pointer != NULL) { if (acr_element_is_sequence(element)) { acr_delete_element_list((Acr_Element) data_pointer); } else { FREE(data_pointer); } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_delete_element @INPUT : element @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Deletes an acr-nema element structure (freeing the data pointer) @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : February 4, 1997 (P.N.) ---------------------------------------------------------------------------- */ void acr_delete_element(Acr_Element element) { if (element == NULL) return; delete_element_data(element); FREE(element); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_delete_element_list @INPUT : element_list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Delete a list of acr-nema elements @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_delete_element_list(Acr_Element element_list) { Acr_Element next, cur; if (element_list == NULL) return; /* Loop through the list, deleting elements */ next = element_list; while (next != NULL) { cur = next; next = acr_get_element_next(cur); acr_delete_element(cur); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_element_list_add @INPUT : element_list - pointer to element list or NULL element - element to add to list @OUTPUT : (none) @RETURNS : Pointer to new element list @DESCRIPTION: Adds an element to a list of elements. If element_list is NULL, then a new list is created. @METHOD : @GLOBALS : @CALLS : @CREATED : February 11, 1997 (P.N.) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_element_list_add(Acr_Element element_list, Acr_Element element) { Acr_Element current; /* Add the element to the list */ if (element_list == NULL) { element_list = element; } else { current = element_list; while (acr_get_element_next(current) != NULL) { current = acr_get_element_next(current); } acr_set_element_next(current, element); } return element_list; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_element_id @INPUT : element group_id element_id @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set group and element id of an acr-nema element @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_element_id(Acr_Element element, int group_id, int element_id) { element->group_id = group_id; element->element_id = element_id; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_element_vr @INPUT : element group_id vr_code @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set VR code for an element @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_element_vr(Acr_Element element, Acr_VR_Type vr_code) { element->vr_code = (short) vr_code; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_element_vr_encoding @INPUT : element group_id vr_encoding - ACR_EXPLICIT_ENCODING or ACR_IMPLICIT_ENCODING @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set encoding type for element VR @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_element_vr_encoding(Acr_Element element, Acr_VR_encoding_type vr_encoding) { element->uses_explicit_vr = (vr_encoding == ACR_EXPLICIT_VR); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_element_byte_order @INPUT : element group_id byte_order - ACR_LITTLE_ENDIAN or ACR_BIG_ENDIAN @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set byte order for an element @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_element_byte_order(Acr_Element element, Acr_byte_order byte_order) { element->has_little_endian_order = (byte_order == ACR_LITTLE_ENDIAN); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_element_variable_length @INPUT : element group_id has_variable_length @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set flag indicating whether element has variable length or not. This can only be set if the element contains sequence data. @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_element_variable_length(Acr_Element element, int has_variable_length) { if (acr_element_is_sequence(element)) { element->has_variable_length = (has_variable_length != FALSE); } else { element->has_variable_length = FALSE; } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_element_data @INPUT : element data_length - if < 0, then data is treated as a list of elements data_pointer @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set data length and pointer of an acr-nema element. A negative length means that this element is a sequence and the data pointer points to a list of elements (items). @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : February 4, 1997 (P.N.) ---------------------------------------------------------------------------- */ void acr_set_element_data(Acr_Element element, long data_length, char *data_pointer) { Acr_Element item, last, last2; long last_length; /* Free the old data if needed */ if (element->data_pointer != NULL) { delete_element_data(element); } /* Set the pointer and check for a sequence */ element->data_pointer = data_pointer; element->is_sequence = (data_length < 0); /* If we have a sequence, work out its length and set each item to not use explicit VR */ if (element->is_sequence) { data_length = 0; last = last2 = NULL; for (item = (Acr_Element) data_pointer; item != NULL; item=acr_get_element_next(item)) { last_length = acr_get_element_total_length(item, ACR_IMPLICIT_VR); data_length += last_length; acr_set_element_vr_encoding(item, ACR_IMPLICIT_VR); last2 = last; last = item; } /* Check for a last delimiting item - remove it so that we don't have to worry about switching between defined and undefined lengths - it will always be added later */ if ((last != NULL) && (acr_get_element_group(last) == ACR_ITEM_GROUP) && ((acr_get_element_element(last) == ACR_ITEM_DELIMITER) || (acr_get_element_element(last) == ACR_SEQ_DELIMITER))) { if (last2 != NULL) { acr_set_element_next(last2, NULL); data_length -= last_length; } else { element->data_pointer = NULL; data_length = 0; } acr_delete_element(last); } } /* Save the length */ element->data_length = data_length; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_element_next @INPUT : element next @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set pointer to next element for an acr-nema element @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_element_next(Acr_Element element, Acr_Element next) { element->next = next; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_group @INPUT : element @OUTPUT : (none) @RETURNS : group id @DESCRIPTION: Get group id for element @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_get_element_group(Acr_Element element) { return element->group_id; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_element @INPUT : element @OUTPUT : (none) @RETURNS : element id @DESCRIPTION: Get element id for element @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_get_element_element(Acr_Element element) { return element->element_id; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_vr @INPUT : element @OUTPUT : (none) @RETURNS : element VR code @DESCRIPTION: Get VR code for element @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_VR_Type acr_get_element_vr(Acr_Element element) { return (Acr_VR_Type) element->vr_code; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_vr_encoding @INPUT : element @OUTPUT : (none) @RETURNS : ACR_EXPLICIT_ENCODING or ACR_IMPLICIT_ENCODING @DESCRIPTION: Get VR encoding type for element @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_VR_encoding_type acr_get_element_vr_encoding(Acr_Element element) { return (element->uses_explicit_vr ? ACR_EXPLICIT_VR : ACR_IMPLICIT_VR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_element_is_sequence @INPUT : element @OUTPUT : (none) @RETURNS : TRUE if element stores a sequence of items @DESCRIPTION: @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_element_is_sequence(Acr_Element element) { return element->is_sequence; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_byte_order @INPUT : element @OUTPUT : (none) @RETURNS : ACR_BIG_ENDIAN or ACR_LITTLE_ENDIAN @DESCRIPTION: @METHOD : @GLOBALS : @CALLS : @CREATED : February 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_byte_order acr_get_element_byte_order(Acr_Element element) { return (element->has_little_endian_order ? ACR_LITTLE_ENDIAN : ACR_BIG_ENDIAN); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_element_has_variable_length @INPUT : element @OUTPUT : (none) @RETURNS : TRUE if element has variable length representation @DESCRIPTION: @METHOD : @GLOBALS : @CALLS : @CREATED : February 4, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_element_has_variable_length(Acr_Element element) { return element->has_variable_length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_length @INPUT : element @OUTPUT : (none) @RETURNS : data_length @DESCRIPTION: Get data length for element. If we have a variable length sequence, then we add in the length of the sequence delimiter. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ long acr_get_element_length(Acr_Element element) { long data_length; data_length = element->data_length; if (acr_element_has_variable_length(element)) { data_length += 2 * ACR_SIZEOF_SHORT + ACR_SIZEOF_LONG; } return data_length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_data @INPUT : element @OUTPUT : (none) @RETURNS : data_pointer @DESCRIPTION: Get data pointer for element @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ char *acr_get_element_data(Acr_Element element) { return element->data_pointer; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_total_length @INPUT : element vr_encoding - ACR_IMPLICIT_VR or ACR_EXPLICIT_VR @OUTPUT : (none) @RETURNS : total length for element, or zero if error. @DESCRIPTION: Get total length for element in ACR-NEMA representation depending on VR @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ long acr_get_element_total_length(Acr_Element element, Acr_VR_encoding_type vr_encoding) { /* bert- verify that the VR name is non-null. This protects against * core dumps when reading improperly-formatted files. */ char *vr_name = acr_get_vr_name(acr_get_element_vr(element)); if (vr_name == NULL) { return (0); } return acr_get_element_length(element) + acr_get_element_header_size(vr_name, vr_encoding); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_next @INPUT : element @OUTPUT : (none) @RETURNS : next element @DESCRIPTION: Get next element for element @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_get_element_next(Acr_Element element) { return element->next; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_copy_element @INPUT : element @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Copies an acr-nema element structure @METHOD : @GLOBALS : @CALLS : @CREATED : November 26, 1993 (Peter Neelin) @MODIFIED : February 4, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Element acr_copy_element(Acr_Element element) { Acr_Element copy; long length; unsigned char *data; Acr_Element olditem, newitem, newlist; /* Check for NULL element */ if (element == NULL) return NULL; /* Copy a sequence */ if (acr_element_is_sequence(element)) { length = -1; olditem = (Acr_Element) acr_get_element_data(element); newitem = NULL; newlist = NULL; /* bert- initialize in case list is empty */ while (olditem != NULL) { if (newitem == NULL) { newlist = acr_copy_element(olditem); newitem = newlist; } else { acr_set_element_next(newitem, acr_copy_element(olditem)); newitem = acr_get_element_next(newitem); } olditem = olditem->next; } data = (unsigned char *) newlist; } /* Or copy a value */ else { length = acr_get_element_length(element); data = MALLOC(length+1); if (data == NULL) { length = 0; data = MALLOC(length+1); } data[length] = '\0'; if (length > 0) { (void) memcpy(data, acr_get_element_data(element), length); } } /* Create the new element */ copy = acr_create_element(acr_get_element_group(element), acr_get_element_element(element), acr_get_element_vr(element), length, (void *) data); acr_set_element_vr_encoding(copy, acr_get_element_vr_encoding(element)); acr_set_element_byte_order(copy, acr_get_element_byte_order(element)); acr_set_element_variable_length(copy, acr_element_has_variable_length(element)); return copy; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_input_element @INPUT : afp - acr file pointer @OUTPUT : element @RETURNS : status @DESCRIPTION: Read in an acr-nema element @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_input_element(Acr_File *afp, Acr_Element *element) { int group_id, element_id, item_gid, item_elid; long data_length; char vr_name[2]; char *data_pointer; Acr_Status status; int is_sequence, more_to_read, found_delimiter, has_variable_length; Acr_Element item, itemlist, previtem; Acr_VR_Type vr_code; Acr_VR_encoding_type vr_encoding; /* Set element in case of error */ *element = NULL; vr_encoding = acr_get_vr_encoding(afp); /* Read in the value */ status = acr_read_one_element(afp, &group_id, &element_id, vr_name, &data_length, &data_pointer); if (status != ACR_OK) { return status; } /* Get VR code */ vr_code = acr_lookup_vr_name(vr_name); /* Check for sequence */ is_sequence = (data_length < 0); if ((data_length > 0) && (data_pointer == NULL)) { is_sequence = TRUE; } has_variable_length = (data_length < 0); /* If we have a sequence, read in all the items and store them as a list of elements. */ if (is_sequence) { more_to_read = TRUE; itemlist = NULL; while (more_to_read) { /* Read in an item */ status = acr_input_element(afp, &item); if (item == NULL) break; /* If we know the length of the whole sequence, check it */ if ((status == ACR_OK) && (data_length > 0)) { data_length -= acr_get_element_total_length(item, vr_encoding); if (data_length < 0) status = ACR_PROTOCOL_ERROR; } /* Look for delimiter */ item_gid = acr_get_element_group(item); item_elid = acr_get_element_element(item); found_delimiter = ((item_gid == ACR_ITEM_GROUP) && ((item_elid == ACR_ITEM_DELIMITER) || (item_elid == ACR_SEQ_DELIMITER))); /* Add the item to the list if it is not a delimiter */ if (!found_delimiter) { if (itemlist == NULL) { itemlist = item; } else { acr_set_element_next(previtem, item); } previtem = item; } else { free(item); /* Avoid leaking memory */ } /* Check for end of items */ if ((data_length == 0) || found_delimiter || (status != ACR_OK)) { more_to_read = FALSE; } } /* End of loop over items */ /* Save the item list as the data */ data_pointer = (char *) itemlist; } /* Create the element */ *element = acr_create_element(group_id, element_id, vr_code, (is_sequence ? -1 : data_length), data_pointer); acr_set_element_vr_encoding(*element, acr_get_vr_encoding(afp)); acr_set_element_byte_order(*element, acr_get_byte_order(afp)); if (is_sequence && !has_variable_length) { acr_set_element_variable_length(*element, FALSE); } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_output_element @INPUT : afp - acr file pointer element @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Write out an acr-nema element. The byte ordering of the element data is changed to match that of the output stream @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_output_element(Acr_File *afp, Acr_Element element) { char *vr_name; Acr_VR_Type vr_code; Acr_Status status; long data_length; int is_sequence, has_variable_length; char *data_pointer; int item_id; Acr_Element item; Acr_VR_encoding_type old_vr_encoding; /* Get info from element */ vr_code = acr_get_element_vr(element); vr_name = acr_get_vr_name(vr_code); is_sequence = acr_element_is_sequence(element); has_variable_length = acr_element_has_variable_length(element); if (is_sequence && has_variable_length) { data_length = ACR_VARIABLE_LENGTH; } else { data_length = acr_get_element_length(element); } /* Get the data. */ if (is_sequence) { data_pointer = NULL; } else { data_pointer = acr_get_element_data(element); } /* Convert the element byte order */ acr_convert_element_byte_order(element, acr_get_byte_order(afp)); /* Write out the element */ status = acr_write_one_element(afp, acr_get_element_group(element), acr_get_element_element(element), vr_name, data_length, data_pointer); if (status != ACR_OK) return status; /* Write out items if we have a sequence */ if (is_sequence) { /* Set the encoding to implicit for items */ old_vr_encoding = acr_get_vr_encoding(afp); acr_set_vr_encoding(afp, ACR_IMPLICIT_VR); /* Loop over items */ item = (Acr_Element) acr_get_element_data(element); while (item != NULL) { status = acr_output_element(afp, item); if (status != ACR_OK) return status; item = acr_get_element_next(item); } /* Write out the delimiter if needed */ if (has_variable_length) { if (acr_get_element_group(element) == ACR_ITEM_GROUP) { item_id = ACR_ITEM_DELIMITER; } else { item_id = ACR_SEQ_DELIMITER; } status = acr_write_one_element(afp, ACR_ITEM_GROUP, item_id, ACR_VR_UNKNOWN, 0L, NULL); if (status != ACR_OK) return status; } /* Restore the VR encoding */ acr_set_vr_encoding(afp, old_vr_encoding); } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_convert_element_byte_order @INPUT : element byte_order - ACR_BIG_ENDIAN or ACR_LITTLE_ENDIAN @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Converts the data within an element to a specified byte_order. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_convert_element_byte_order(Acr_Element element, Acr_byte_order byte_order) { Acr_byte_order element_byte_order; long nvalues; size_t value_size; /* Get the element and stream byte orders and change the element byte order to match that of the stream */ element_byte_order = acr_get_element_byte_order(element); acr_set_element_byte_order(element, byte_order); /* Change byte order of data in place */ if (!acr_element_is_sequence(element)) { /* Look for types that might need byte swapping */ switch (acr_get_element_vr(element)) { case ACR_VR_SS: case ACR_VR_US: case ACR_VR_OW: value_size = ACR_SIZEOF_SHORT; break; case ACR_VR_SL: case ACR_VR_UL: value_size = ACR_SIZEOF_LONG; break; case ACR_VR_FL: value_size = ACR_SIZEOF_FLOAT; break; case ACR_VR_FD: value_size = ACR_SIZEOF_DOUBLE; break; default: value_size = 1; break; } /* Reverse byte order */ if (value_size > 1) { if (element_byte_order != byte_order) { nvalues = acr_get_element_length(element) / value_size; acr_reverse_byte_order(nvalues, value_size, acr_get_element_data(element), NULL); } } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_match_element_id @INPUT : elid - element id to check element - element to check @OUTPUT : (none) @RETURNS : TRUE if the ids match, FALSE otherwise @DESCRIPTION: Compares the group and element id of an element id structure to that of an element. Returns TRUE if they are the same. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_match_element_id(Acr_Element_Id elid, Acr_Element element) { return ((elid->group_id == acr_get_element_group(element)) && (elid->element_id == acr_get_element_element(element))); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_element_id @INPUT : elid - element id to check element_list - element list to search @OUTPUT : (none) @RETURNS : Pointer to element found or NULL @DESCRIPTION: Searches an element list for an element id. As a side effect, the VR type of the element is set if it is previously unknown and it is defined in the element id structure. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_find_element_id(Acr_Element element_list, Acr_Element_Id elid) { Acr_Element element; /* Look for the element */ element = element_list; while ((element != NULL) && !acr_match_element_id(elid, element)) { element = acr_get_element_next(element); } /* Set the VR type if it is unknown */ if ((element != NULL) && (acr_get_element_vr(element) == ACR_VR_UNKNOWN) && (elid->vr_code != ACR_VR_UNKNOWN)) { acr_set_element_vr(element, elid->vr_code); } return element; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_memdup @INPUT : value_size - number of bytes to copy value - value to copy @OUTPUT : (none) @RETURNS : Pointer to copy of data @DESCRIPTION: Allocates memory and makes a copy of some memory @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void *acr_memdup(size_t value_size, void *value) { char *copy, *original; size_t i; original = (char *) value; copy = (char *) MALLOC(value_size); for (i=0; igroup_id, elid->element_id, vr_code, value_size, acr_memdup(value_size, value)); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_element_short @INPUT : elid value @OUTPUT : (none) @RETURNS : Pointer to element structure @DESCRIPTION: Creates an acr-nema element structure containing one short. @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_create_element_short(Acr_Element_Id elid, Acr_Short value) { return create_element_mem(elid, ACR_VR_US, sizeof(value), (void *) &value); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_element_long @INPUT : elid value @OUTPUT : (none) @RETURNS : Pointer to element structure @DESCRIPTION: Creates an acr-nema element structure containing one long. @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_create_element_long(Acr_Element_Id elid, Acr_Long value) { return create_element_mem(elid, ACR_VR_UL, sizeof(value), (void *) &value); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_element_double @INPUT : elid nvalues values @OUTPUT : (none) @RETURNS : Pointer to element structure @DESCRIPTION: Creates an acr-nema element structure containing an array of doubles. @METHOD : @GLOBALS : @CALLS : @CREATED : April 8, 2006 (Bert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_create_element_double(Acr_Element_Id elid, int nvalues, Acr_Double *values) { return create_element_mem(elid, ACR_VR_FD, (ACR_SIZEOF_DOUBLE * nvalues), values); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_element_numeric @INPUT : elid value @OUTPUT : (none) @RETURNS : Pointer to element structure @DESCRIPTION: Creates an acr-nema element structure containing one ascii numeric. Note that the VR type is taken from the elid structure unless it is not specified there (ACR_VR_UNKNOWN). @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_create_element_numeric(Acr_Element_Id elid, double value) { char string[256]; Acr_Element element; if (elid->vr_code == ACR_VR_FD) { element = create_element_mem(elid, ACR_VR_FD, sizeof(value), (void *) &value); } else { (void) sprintf(string, "%.15g", value); element = acr_create_element_string(elid, string); if (elid->vr_code == ACR_VR_UNKNOWN) acr_set_element_vr(element, ACR_VR_DS); } return element; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_element_string @INPUT : elid value @OUTPUT : (none) @RETURNS : Pointer to element structure @DESCRIPTION: Creates an acr-nema element structure containing an ascii string. Note that the string is duplicated for the element structure. Note also that the VR type is taken from the elid structure unless it is not specified there (ACR_VR_UNKNOWN). @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_create_element_string(Acr_Element_Id elid, Acr_String value) { long data_length; long alloc_length; char *data; int pad; Acr_VR_Type vr_code; /* Get the appropriate vr code */ vr_code = ((elid->vr_code == ACR_VR_UNKNOWN) ? ACR_VR_ST : elid->vr_code); /* Get string length and check for an odd length */ data_length = strlen(value); if ((data_length % 2) == 0) pad = FALSE; else { pad = TRUE; data_length++; } /* Allocate the string and copy it */ alloc_length = data_length + 1; data = (char *) MALLOC(alloc_length); (void) strcpy(data, value); /* Pad the end with a blank or NUL if needed */ if (pad) { data[data_length - 1] = ((vr_code == ACR_VR_UI) ? '\0' : ' '); data[data_length] = '\0'; } /* Create the element and return it */ return acr_create_element(elid->group_id, elid->element_id, vr_code, data_length, data); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_element_sequence @INPUT : elid value @OUTPUT : (none) @RETURNS : Pointer to element structure @DESCRIPTION: Creates an acr-nema element structure containing a sequence of items. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_create_element_sequence(Acr_Element_Id elid, Acr_Element itemlist) { return acr_create_element(elid->group_id, elid->element_id, ACR_VR_SQ, -1L, (char *) itemlist); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_short @INPUT : element @OUTPUT : (none) @RETURNS : Value from element structure @DESCRIPTION: Gets a single short from an element structure. Returns zero if an error occurs. @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Short acr_get_element_short(Acr_Element element) { Acr_Short value; value = (Acr_Short)acr_get_numeric_vr(acr_get_element_vr(element), acr_get_element_byte_order(element), acr_get_element_data(element), acr_get_element_length(element)); return value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_long @INPUT : element @OUTPUT : (none) @RETURNS : Value from element structure @DESCRIPTION: Gets a single long from an element structure. Returns zero if an error occurs. @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Long acr_get_element_long(Acr_Element element) { Acr_Long value; value = (Acr_Long)acr_get_numeric_vr(acr_get_element_vr(element), acr_get_element_byte_order(element), acr_get_element_data(element), acr_get_element_length(element)); return value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_numeric @INPUT : element @OUTPUT : (none) @RETURNS : Value from element structure @DESCRIPTION: Gets a single ascii numeric from an element structure. Returns zero if an error occurs. @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ double acr_get_element_numeric(Acr_Element element) { double value; value = acr_get_numeric_vr(acr_get_element_vr(element), acr_get_element_byte_order(element), acr_get_element_data(element), acr_get_element_length(element)); return value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_string @INPUT : element @OUTPUT : (none) @RETURNS : Value from element structure @DESCRIPTION: Gets an string from an element structure. @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_String acr_get_element_string(Acr_Element element) { return acr_get_string_vr(acr_get_element_vr(element), acr_get_element_byte_order(element), acr_get_element_data(element), acr_get_element_length(element)); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_short_array @INPUT : element max_values - maximum number of values to return @OUTPUT : values - array of values found @RETURNS : Number of values found @DESCRIPTION: Gets an array of shorts from an element structure. If the number of values in the element is greater than max_values, then only max_values values are extracted, but the total number of values in the element is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : February 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ long acr_get_element_short_array(Acr_Element element, long max_values, Acr_Short values[]) { long nvalues; /* Check VR of element */ switch (acr_get_element_vr(element)) { case ACR_VR_SS: case ACR_VR_US: case ACR_VR_OW: case ACR_VR_UNKNOWN: break; default: return (long) 0; } /* Get number of values in element */ nvalues = acr_get_element_length(element) / ACR_SIZEOF_SHORT; /* Check the maximum number of values */ if (max_values > nvalues) max_values = nvalues; /* Get the data */ acr_get_short(acr_get_element_byte_order(element), max_values, acr_get_element_data(element), values); /* Return the number of values in the structure */ return nvalues; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_double_array @INPUT : element max_values - maximum number of values to return @OUTPUT : values - array of values found @RETURNS : Number of values found @DESCRIPTION: Gets an array of doubles from an element structure. If the number of values in the element is greater than max_values, then only max_values values are extracted, but the total number of values in the element is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : April 8, 2006 (Bert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ long acr_get_element_double_array(Acr_Element element, long max_values, Acr_Double values[]) { long nvalues; /* Check VR of element */ switch (acr_get_element_vr(element)) { case ACR_VR_FD: case ACR_VR_UNKNOWN: break; default: return (long) 0; } /* Get number of values in element */ nvalues = acr_get_element_length(element) / ACR_SIZEOF_DOUBLE; /* Check the maximum number of values */ if (max_values > nvalues) max_values = nvalues; /* Get the data */ acr_get_double(acr_get_element_byte_order(element), max_values, acr_get_element_data(element), values); /* Return the number of values in the structure */ return nvalues; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_element_numeric_array_separator @INPUT : character - character to add to list or EOF if not adding anything @OUTPUT : (none) @RETURNS : Pointer to array of separators, ending with an EOF @DESCRIPTION: Adds to the list of separators for a numeric array, or returns a pointer to the array which is terminated with an EOF. @METHOD : @GLOBALS : @CALLS : @CREATED : February 27, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int *acr_element_numeric_array_separator(int character) { static int *separator_list = NULL; static int nseparators = 0; static int default_list[] = {',', '\\', '/'}; int isep; /* Create the default list */ if (separator_list == NULL) { nseparators = SIZEOF_ARRAY(default_list); separator_list = MALLOC((size_t) (nseparators + 1) * sizeof(*separator_list)); for (isep = 0; isep < nseparators; isep++) { separator_list[isep] = default_list[isep]; } separator_list[nseparators] = EOF; } /* Add the character to the list if it is not already there */ if (character != EOF) { for (isep=0; isep < nseparators; isep++) { if (character == separator_list[isep]) break; } if (character != separator_list[isep]) { nseparators++; separator_list = REALLOC(separator_list, (size_t) (nseparators + 1) * sizeof(*separator_list)); separator_list[nseparators - 1] = character; separator_list[nseparators] = EOF; } } /* Return the list */ return separator_list; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_element_numeric_array @INPUT : element max_values - maximum number of values to return @OUTPUT : values - array of values found @RETURNS : Number of values found @DESCRIPTION: Gets an array of ascii numbers from an element structure. @METHOD : @GLOBALS : @CALLS : @CREATED : November 17, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_get_element_numeric_array(Acr_Element element, int max_values, double values[]) { char *start, *end, *cur, *prev; int *separator_list; int nvalues, isep; /* Get separator list */ separator_list = acr_element_numeric_array_separator(EOF); /* Set up pointers to end of string and first non-space character */ start = (char *) acr_get_element_data(element); end = start + acr_get_element_length(element); cur = start; while (isspace((int) *cur)) cur++; nvalues = 0; /* Loop through string looking for numbers */ while (cur 0) && (string[string_length-1] == '\0')) { string_length--; } /* Print string if short enough and is printable */ if (element_length > 0 && !(acr_get_element_group(cur_element) == 0x7fe0 && acr_get_element_element(cur_element) == 0x0010)) { copy = malloc(string_length + 1); printable = (string_length > 0); for (i=0; i < string_length; i++) { if (! isprint((int) string[i])) { printable = FALSE; copy[i] = ' '; } else if ((string[i] == '\n') || (string[i] == '\r') || (string[i] == '\f')) copy[i] = ' '; else copy[i] = string[i]; } copy[i] = '\0'; if (printable) { (void) fprintf(file_pointer, " string = \"%s\"", copy); } else if (!done_already) { /* If unknown length print as a series of bytes. */ string = acr_get_element_data(cur_element); fprintf(file_pointer, " byte = "); if (element_length < 1000) { for (i = 0; i < element_length; i++) { fprintf(file_pointer, "%#x", (unsigned char)string[i]); if (i != element_length - 1) { fprintf(file_pointer, ", "); } } } else { fprintf(file_pointer, "\n"); for (i = 0; i < element_length; i += 16) { for (j = 0; j < 16; j++) { if (i + j < element_length) { fprintf(file_pointer, "%02x ", (unsigned char)string[i+j]); } else { fprintf(file_pointer, " "); } } fprintf(file_pointer, "| "); for (j = 0; j < 16; j++) { if (i + j < element_length) { int c = (unsigned char)string[i+j]; fprintf(file_pointer, "%c", isprint(c) ? c : '.'); } } fprintf(file_pointer, "\n"); } } } free(copy); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dump_element_list @INPUT : file_pointer - where output should go element_list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Dump information from an acr-nema element list @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_dump_element_list(FILE *file_pointer, Acr_Element element_list) { #define INDENT_AMOUNT 3 Acr_Element cur_element; long element_length; int i; static int current_indent_level = 0; Acr_VR_Type vr_code; /* Check that we have something to print */ if (element_list == NULL) return; /* Increment indent level */ current_indent_level += INDENT_AMOUNT; /* Loop over elements */ cur_element = element_list; while (cur_element != NULL) { /* Indent the line */ for (i=0; i < current_indent_level; i++) { (void) putc((int) ' ', file_pointer); } element_length = acr_get_element_length(cur_element); /* Print the element id */ (void) fprintf(file_pointer, "0x%04x 0x%04x length = %d ", acr_get_element_group(cur_element), acr_get_element_element(cur_element), (int) element_length); if (_acr_name_proc != NULL) { char *name_ptr; name_ptr = (*_acr_name_proc)(acr_get_element_group(cur_element), acr_get_element_element(cur_element)); if (name_ptr != NULL) { fprintf(file_pointer, "(%s)", name_ptr); } } fprintf(file_pointer, ":"); /* Print value if needed */ vr_code = acr_get_element_vr(cur_element); if (acr_element_is_sequence(cur_element)) { (void) fprintf(file_pointer, " VR=%s", acr_get_vr_name(vr_code)); if (acr_get_element_data(cur_element) == NULL) { (void) fprintf(file_pointer, " (empty sequence)"); } else { (void) fprintf(file_pointer, " (sequence)"); } (void) putc((int) '\n', file_pointer); acr_dump_element_list(file_pointer, (Acr_Element) acr_get_element_data(cur_element)); } else if (vr_code != ACR_VR_UNKNOWN) { (void) fprintf(file_pointer, " VR=%s, ", acr_get_vr_name(vr_code)); switch (vr_code) { case ACR_VR_SS: case ACR_VR_US: (void) fprintf(file_pointer, "short = %d (0x%04x)", (int) acr_get_element_short(cur_element), (int) acr_get_element_short(cur_element)); break; case ACR_VR_AT: case ACR_VR_SL: case ACR_VR_UL: (void) fprintf(file_pointer, "long = %d (0x%08x)", (int) acr_get_element_long(cur_element), (int) acr_get_element_long(cur_element)); break; case ACR_VR_OB: case ACR_VR_OW: maybe_print_as_string(file_pointer, cur_element, element_length, 0); break; default: (void) fprintf(file_pointer, "value = \"%s\"", acr_get_element_string(cur_element)); break; } (void) putc((int) '\n', file_pointer); } else { int done_already = 0; switch (element_length) { case ACR_SIZEOF_SHORT: (void) fprintf(file_pointer, " short = %d (0x%04x)", (int) acr_get_element_short(cur_element), (int) acr_get_element_short(cur_element)); done_already = 1; break; case ACR_SIZEOF_LONG: (void) fprintf(file_pointer, " long = %d (0x%08x)", (int) acr_get_element_long(cur_element), (int) acr_get_element_long(cur_element)); done_already = 1; break; } maybe_print_as_string(file_pointer, cur_element, element_length, done_already); /* End line */ (void) fprintf(file_pointer, "\n"); } /* if is_sequence ... else */ cur_element = acr_get_element_next(cur_element); } /* Decrement indent level */ current_indent_level -= INDENT_AMOUNT; } minc-2.2.00/conversion/Acr_nema/file_io.c0000644000265600003100000007056412027132660015116 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : file_io.c @DESCRIPTION: Routines for doing io from acr_nema code. @METHOD : @GLOBALS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : * $Log: file_io.c,v $ * Revision 6.10 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.9 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.8 2005/05/19 20:57:20 bert * Fixes for Windows, ported from 1.X branch * * Revision 6.7.2.2 2005/05/16 22:39:30 bert * Insert conditionals to get it building under Windows * * Revision 6.7.2.1 2005/05/12 21:15:30 bert * Initial checkin * * Revision 6.7 2005/03/04 00:09:00 bert * Lose private and public * * Revision 6.6 2005/02/16 19:22:32 bert * Autoconfiscation * * Revision 6.5 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.4 2001/11/08 14:17:05 neelin * Added acr_test_dicom_file to allow reading of DICOM part 10 format * files. This function also calls acr_test_byte_order to set up the stream * properly and can be used as a direct replacement for that function. * This set of changes does NOT include the ability to write part 10 files. * * Revision 6.3 2000/05/17 20:17:48 neelin * Added mechanism to allow testing of input streams for more data through * function acr_file_ismore. * This is used in dicom_client_routines to allow asynchronous transfer * of data, with testing for more input done before sending new messages. * Previous use of select for this was misguided, since select may report that * no data is waiting on the file descriptor while data is store in the file * pointer buffer (or Acr file pointer buffer). * * Revision 6.2 1999/10/29 17:51:53 neelin * Fixed Log keyword * * Revision 6.1 1998/11/11 16:26:49 neelin * Increased default buffer size to 64K. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.1 1995/02/08 21:16:06 neelin * Changes to make irix 5 lint happy. * * Revision 2.0 1994/09/28 10:36:13 neelin * Release of minc version 0.2 * * Revision 1.7 94/09/28 10:35:42 neelin * Pre-release * * Revision 1.6 94/04/08 10:34:47 neelin * Added include of string.h * * Revision 1.5 94/04/08 10:32:00 neelin * Fixed io tracing. * * Revision 1.4 93/11/25 10:36:14 neelin * Added file free and ungetc * * Revision 1.3 93/11/23 16:02:12 neelin * Corrected header comment in acr_file_flush. * * Revision 1.2 93/11/23 13:21:42 neelin * Added fflush for stdio write routine. * * Revision 1.1 93/11/10 10:33:22 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include /* Define some constants */ #define ACR_MAX_BUFFER_LENGTH (64*1024) #define ACR_BUFFER_MARGIN 256 #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif /* Stream type */ #define ACR_UNKNOWN_STREAM 0 #define ACR_READ_STREAM 1 #define ACR_WRITE_STREAM 2 #if HAVE_MKSTEMP /* Stuff for input and output tracing */ static char *Input_trace_file = "acr_file_input_XXXXXX"; static char *Output_trace_file = "acr_file_output_XXXXXX"; #endif /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_enable_trace @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Turns on tracing for an i/o stream @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_file_enable_trace(Acr_File *afp) { afp->do_trace = TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_disable_trace @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Turns off tracing for an i/o stream @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_file_disable_trace(Acr_File *afp) { afp->do_trace = FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_initialize @INPUT : io_data - pointer to data for read and write routines maxlength - maximum length for a single read or write (zero or negative means use internal maximum). io_routine - routine to read or write data @OUTPUT : (none) @RETURNS : pointer to Acr_File structure created @DESCRIPTION: Sets up the routines for reading/writing from an input or output stream. A given Acr_File can only do input or output, not both. @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : February 5, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_File *acr_file_initialize(void *io_data, int maxlength, Acr_Io_Routine io_routine) { Acr_File *afp; /* Check that an io routine is given */ if (io_routine == NULL) { return NULL; } /* Allocate the strcture */ afp = malloc(sizeof(*afp)); /* Initialize fields */ afp->io_data = io_data; afp->io_routine = io_routine; afp->ismore_function = NULL; if ((maxlength < ACR_MAX_BUFFER_LENGTH) && (maxlength > 0)) afp->maxlength = maxlength; else afp->maxlength = ACR_MAX_BUFFER_LENGTH; afp->stream_type = ACR_UNKNOWN_STREAM; afp->buffer_length = ACR_MAX_BUFFER_LENGTH+ACR_BUFFER_MARGIN; afp->reached_eof = FALSE; afp->watchpoint_set = FALSE; afp->bytes_to_watchpoint = 0; afp->client_data = NULL; /* Allocate the buffer */ afp->start = malloc((size_t) afp->buffer_length); /* Set ptr and end to start so that we can detect beginning of i/o */ afp->length = 0; afp->end = afp->start; afp->ptr = afp->end; /* Set the trace file pointer to null */ afp->do_trace = FALSE; afp->tracefp = NULL; return afp; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_free @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Frees the Acr_File structure, flushing the buffer if needed. @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_file_free(Acr_File *afp) { if (afp != NULL) { if (afp->stream_type == ACR_WRITE_STREAM) { (void) acr_file_flush(afp); } if (afp->start != NULL) { free(afp->start); } if (afp->tracefp != NULL) { (void) fclose(afp->tracefp); } if (afp->client_data != NULL) { free(afp->client_data); } free(afp); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_reset @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Resets the input or output stream, discarding anything that was buffered. Any watchpoint is unset. The eof flag is unset. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_file_reset(Acr_File *afp) { afp->watchpoint_set = FALSE; afp->bytes_to_watchpoint = 0; afp->length = 0; afp->end = afp->start; afp->ptr = afp->end; afp->reached_eof = FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_set_ismore_function @INPUT : afp ismore_function @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Sets the function to be used for testing if there is more data waiting on an input stream. This must be set if acr_file_ismore is to be used. The ismore function should return 1 if there is data waiting, 0 if there is none, and -1 if EOF is reached or an error occurs. @METHOD : @GLOBALS : @CALLS : @CREATED : May 17, 2000 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_file_set_ismore_function(Acr_File *afp, Acr_Ismore_Function ismore_function) { afp->ismore_function = ismore_function; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_set_eof @INPUT : afp @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Tells the input or output stream that it has reached the end of file so that no more data will be read or written. This can be useful for preventing further reading or writing if an alarm goes off, for example. @METHOD : @GLOBALS : @CALLS : @CREATED : March 10, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_file_set_eof(Acr_File *afp) { afp->reached_eof = TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_set_client_data @INPUT : afp client_data - pointer to data for client use @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Associates some client data with an io stream. The pointer is assumed to point to data that should be freed when the stream is closed. Note that this mechanism is designed only to be used by the acr_io routines and is not a general-purpose mechanism. @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_file_set_client_data(Acr_File *afp, void *client_data) { if (afp->client_data != NULL) { free(afp->client_data); } afp->client_data = client_data; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_get_client_data @INPUT : afp @OUTPUT : (none) @RETURNS : pointer to client data @DESCRIPTION: Gets the pointer to client data for the given input stream. @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void *acr_file_get_client_data(Acr_File *afp) { return afp->client_data; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_read_more @INPUT : afp - Acr_File pointer @OUTPUT : (none) @RETURNS : The next character. @DESCRIPTION: Gets more input. If the watchpoint is reached, then EOF is returned. This routine will not read past the watchpoint. @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : February 5, 1997 (P.N.) ---------------------------------------------------------------------------- */ int acr_file_read_more(Acr_File *afp) { int nread, ichar; char trace_file[128]; unsigned char *margin_ptr; long byte_shift, bytes_to_read, watchpoint_distance; /* Check the pointer */ if (afp == NULL) { return EOF; } /* Check whether we really need more */ if (afp->ptr < afp->end) { return (int) *(afp->ptr++); } /* Check for EOF */ if (afp->reached_eof) return EOF; /* Check the stream type */ switch (afp->stream_type) { case ACR_UNKNOWN_STREAM: afp->stream_type = ACR_READ_STREAM; break; case ACR_READ_STREAM: break; case ACR_WRITE_STREAM: default: return EOF; } /* Work out the amount to read */ bytes_to_read = afp->maxlength; if (afp->watchpoint_set) { watchpoint_distance = (afp->start + afp->bytes_to_watchpoint - afp->end); if (watchpoint_distance <= 0) { return EOF; } else if (watchpoint_distance < bytes_to_read) { bytes_to_read = watchpoint_distance; } } /* Check whether we need to start a new buffer for next read */ if ((afp->end + bytes_to_read) > (afp->start + afp->buffer_length)) { /* Check that things are consistent */ if ((afp->end - ACR_BUFFER_MARGIN) <= afp->start) { (void) fprintf(stderr, "Internal error copying afp buffer margin\n"); exit(EXIT_FAILURE); } /* Copy the data down from the top of the buffer */ margin_ptr = afp->end - ACR_BUFFER_MARGIN; for (ichar=0; ichar < ACR_BUFFER_MARGIN; ichar++) { afp->start[ichar] = margin_ptr[ichar]; } /* Update the structure */ byte_shift = margin_ptr - afp->start; afp->end = afp->start + ACR_BUFFER_MARGIN; afp->ptr = afp->end; afp->length = afp->end - afp->start; if (afp->watchpoint_set) { afp->bytes_to_watchpoint -= byte_shift; } } /* Read in another buffer-full */ nread=afp->io_routine(afp->io_data, afp->end, bytes_to_read); /* Do tracing */ if (afp->do_trace) { if (afp->tracefp == NULL) { #if HAVE_MKSTEMP (void) strcpy(trace_file, Input_trace_file); afp->tracefp = fdopen(mkstemp(trace_file), "w"); #elif HAVE_TMPNAM tmpnam(trace_file); afp->tracefp = fopen(trace_file, "w"); #else #error Must have mkstemp() or tmpnam() available. #endif if (afp->tracefp != NULL) { (void) fprintf(stderr, "Opened input trace file %s.\n", trace_file); (void) fflush(stderr); } else { (void) fprintf(stderr, "Error opening input trace file %s.\n", trace_file); (void) fflush(stderr); } } if (nread > 0) { (void) fwrite(afp->end, sizeof(char), nread, afp->tracefp); (void) fflush(afp->tracefp); } } /* Check for EOF */ if (nread <= 0) { afp->reached_eof = TRUE; return EOF; } /* Set up variables */ afp->end += nread; afp->length += nread; /* Return the next value */ return (int) *(afp->ptr++); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_write_more @INPUT : afp - Acr_File pointer @OUTPUT : (none) @RETURNS : The character or EOF. @DESCRIPTION: Writes out the buffer and the character. This routine will write past the watchpoint, but will flush the buffer when it reaches the watchpoint. @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : February 5, 1997 (P.N.) ---------------------------------------------------------------------------- */ int acr_file_write_more(Acr_File *afp, int character) { /* Check the pointer */ if (afp == NULL) { return EOF; } /* Check whether we need to flush the buffer */ if (afp->ptr < afp->end) { return (int) (*(afp->ptr++) = (unsigned char) character); } /* Flush the buffer */ if (acr_file_flush(afp) == EOF) { return EOF; } /* Write the character into the buffer */ return (int) (*(afp->ptr++) = (unsigned char) character); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_flush @INPUT : afp - Acr_File pointer @OUTPUT : (none) @RETURNS : EOF if an error occurs, otherwise 0. @DESCRIPTION: Flushes the buffer. @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : February 5, 1997 (P.N.) ---------------------------------------------------------------------------- */ int acr_file_flush(Acr_File *afp) { int length, nwritten; char trace_file[128]; /* Check the pointer */ if (afp == NULL) { return EOF; } /* Check for EOF */ if (afp->reached_eof) return EOF; /* Check the stream type */ switch (afp->stream_type) { case ACR_UNKNOWN_STREAM: afp->stream_type = ACR_WRITE_STREAM; break; case ACR_WRITE_STREAM: break; case ACR_READ_STREAM: default: return EOF; } /* Check for something to write */ length = afp->ptr - afp->start; if (length > 0) { /* Do trace, if needed */ if (afp->do_trace) { if (afp->tracefp == NULL) { #if HAVE_MKSTEMP (void) strcpy(trace_file, Output_trace_file); afp->tracefp = fdopen(mkstemp(trace_file), "w"); #elif HAVE_TMPNAM tmpnam(trace_file); afp->tracefp = fopen(trace_file, "w"); #else #error Must have mkstemp() or tmpnam() available. #endif if (afp->tracefp != NULL) { (void) fprintf(stderr, "Opened output trace file %s.\n", trace_file); (void) fflush(stderr); } else { (void) fprintf(stderr, "Error opening output trace file %s.\n", trace_file); (void) fflush(stderr); } } (void) fwrite(afp->start, sizeof(char), length, afp->tracefp); (void) fflush(afp->tracefp); } /* Write the data */ nwritten = afp->io_routine(afp->io_data, afp->start, length); if (nwritten != length) { (void) fprintf(stderr, "Output error: wrote only %d bytes of %d\n", nwritten, length); afp->reached_eof = TRUE; return EOF; } } /* Reset the buffer */ if (afp->watchpoint_set) { afp->bytes_to_watchpoint -= length; } afp->ptr = afp->start; afp->length = afp->maxlength; if ((afp->bytes_to_watchpoint > 0) && (afp->bytes_to_watchpoint < afp->length)) { afp->length = afp->bytes_to_watchpoint; } afp->end = afp->start + afp->length; return 0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_ungetc @INPUT : c - character to unget afp - Acr_File pointer @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Puts a character back into the input stream. This command is fragile - it will only work if it can back up on the current buffer. @METHOD : @GLOBALS : @CALLS : @CREATED : November 25, 1993 (Peter Neelin) @MODIFIED : February 5, 1997 (P.N.) ---------------------------------------------------------------------------- */ int acr_ungetc(int c, Acr_File *afp) { /* Check the pointer */ if (afp == NULL) { return EOF; } /* Check the stream type */ if (afp->stream_type != ACR_READ_STREAM) { return EOF; } /* Check to see if we can put the character back */ if (afp->ptr > afp->start) { afp->ptr--; *afp->ptr = (unsigned char) c; } else { return EOF; } return (int) *afp->ptr; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_get_io_data @INPUT : afp - Acr_File pointer @OUTPUT : (none) @RETURNS : pointer to io data @DESCRIPTION: Gets back pointer that was passed in to acr_file_initialize. @METHOD : @GLOBALS : @CALLS : @CREATED : February 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void *acr_file_get_io_data(Acr_File *afp) { return afp->io_data; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_io_watchpoint @INPUT : afp - Acr_File pointer bytes_to_watchpoint - number of bytes from current position to watchpoint @OUTPUT : (none) @RETURNS : nothing @DESCRIPTION: Sets a watchpoint in the i/o stream relative to the current input position. If bytes_to_watchpoint is equal to ACR_NO_WATCHPOINT, then the watchpoint is unset. @METHOD : @GLOBALS : @CALLS : @CREATED : February 5, 1997 (P.N.) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_io_watchpoint(Acr_File *afp, long bytes_to_watchpoint) { if (afp == NULL) return; /* Unset watchpoint */ if (bytes_to_watchpoint == ACR_NO_WATCHPOINT) { afp->watchpoint_set = FALSE; afp->bytes_to_watchpoint = ACR_NO_WATCHPOINT; } /* Set watchpoint */ else { afp->watchpoint_set = TRUE; afp->bytes_to_watchpoint = bytes_to_watchpoint + afp->ptr - afp->start; /* For writing, check if we need to move the end of the buffer to force a flush at the watchpoint */ if ((afp->stream_type == ACR_WRITE_STREAM) && (bytes_to_watchpoint >= 0) && (afp->bytes_to_watchpoint < afp->length)) { afp->length = afp->bytes_to_watchpoint; afp->end = afp->start + afp->length; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_io_watchpoint @INPUT : afp - Acr_File pointer @OUTPUT : (none) @RETURNS : number of bytes from current position to watchpoint @DESCRIPTION: Checks the watchpoint and returns the number of bytes between the current position and the watchpoint. If the current position is past the watchpoint, then a negative number is returned. If the watchpoint is not set, then ACR_NO_WATCHPOINT is returned. This constant is a very large positive number (ie. the watchpoint is always in the future). @METHOD : @GLOBALS : @CALLS : @CREATED : February 5, 1997 (P.N.) @MODIFIED : ---------------------------------------------------------------------------- */ long acr_get_io_watchpoint(Acr_File *afp) { if ((afp == NULL) || !afp->watchpoint_set) return ACR_NO_WATCHPOINT; return (afp->start + afp->bytes_to_watchpoint - afp->ptr); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_file_ismore @INPUT : afp - Acr_File pointer @OUTPUT : (none) @RETURNS : FALSE if no data is waiting on the input stream, but the ismore function has been set for that stream, and the stream is otherwise okay. TRUE in other cases (data waiting, EOF reached, no ismore function set, invalid file pointer). @DESCRIPTION: Checks to see if more data is waiting in the buffer, or calls the io-specific function to test whether more data is available. This call should be non-blocking, but that will depend on the implementation of the io ismore function. The io-specific ismore function should return 1 if there is data waiting, 0 is there is none and -1 if EOF is reached or error occurs. @METHOD : @GLOBALS : @CALLS : @CREATED : May 17, 2000 (P.N.) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_file_ismore(Acr_File *afp) { int retval; /* Check that the ismore function is set */ if (afp->ismore_function == NULL) return TRUE; /* Check that we have a read stream */ switch (afp->stream_type) { case ACR_UNKNOWN_STREAM: afp->stream_type = ACR_READ_STREAM; break; case ACR_READ_STREAM: break; case ACR_WRITE_STREAM: default: return TRUE; } /* Check if there is data in the buffer */ if (afp->ptr < afp->end) { return TRUE; } /* Call the io ismore function */ retval = afp->ismore_function(afp->io_data); /* Check for and end of file condition */ if (retval < 0) { acr_file_set_eof(afp); return TRUE; } else if (retval > 0) { return TRUE; } else { return FALSE; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_stdio_read @INPUT : io_data - should be a FILE * pointer nbytes - number of bytes to read @OUTPUT : buffer - buffer into which we will read @RETURNS : Number of bytes read. @DESCRIPTION: Acr io routine for reading from a stdio FILE pointer @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_stdio_read(void *io_data, void *buffer, int nbytes) { FILE *fp; int nread; /* Get file pointer */ if (io_data == NULL) return 0; fp = (FILE *) io_data; /* Read the data */ nread = fread(buffer, sizeof(char), (size_t) nbytes, fp); if (nread < 0) nread = 0; return nread; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_stdio_write @INPUT : io_data - should be a FILE * pointer buffer - buffer from which we will write nbytes - number of bytes to write @OUTPUT : (nothing) @RETURNS : Number of bytes written. @DESCRIPTION: Acr io routine for writing to a stdio FILE pointer @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_stdio_write(void *io_data, void *buffer, int nbytes) { FILE *fp; int nwritten; /* Get file pointer */ if (io_data == NULL) return 0; fp = (FILE *) io_data; /* Write the data */ nwritten = fwrite(buffer, sizeof(char), (size_t) nbytes, fp); if (nwritten < 0) nwritten = 0; /* Flush the buffer */ if (nwritten > 0) { (void) fflush(fp); } return nwritten; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_stdio_ismore @INPUT : io_data - should be a FILE * pointer @OUTPUT : (nothing) @RETURNS : 1 if more data is waiting, 0 if not, and -1 if EOF or error. @DESCRIPTION: Acr io routine for testing for waiting data on a stdio input FILE pointer. This function is non-blocking. @METHOD : @GLOBALS : @CALLS : @CREATED : May 17, 2000 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_stdio_ismore(void *io_data) { #ifdef O_NONBLOCK FILE *fp; int val; int old_flags, new_flags; int fd; /* Get file pointer */ if (io_data == NULL) return -1; fp = (FILE *) io_data; /* Set non-blocking i/o */ fd = fileno(fp); old_flags = fcntl(fd, F_GETFL, 0); new_flags = old_flags | O_NONBLOCK; if (fcntl(fd, F_SETFL, new_flags) < 0) return -1; /* Read in a character */ val = getc(fp); /* Reset to old flags */ if (fcntl(fd, F_SETFL, old_flags) < 0) return -1; /* Test the return value to see if anything is waiting */ if (val != EOF) { if (ungetc(val, fp) == EOF) return -1; return 1; } else if (feof(fp)) { return -1; } else if (ferror(fp) && (errno != EAGAIN)) { return -1; } #endif /* O_NONBLOCK defined */ return 0; } minc-2.2.00/conversion/Acr_nema/globals.c0000644000265600003100000000214112027132660015115 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : globals.c @DESCRIPTION: Global definitions for acr-nema library. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #define ACR_LIBRARY_GLOBAL_ELEMENT_DEFINITION #include #include #include #include #include minc-2.2.00/conversion/Acr_nema/group.c0000644000265600003100000014261612027132660014642 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : group.c @DESCRIPTION: Routines for doing acr_nema group operations. @METHOD : @GLOBALS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : * $Log: group.c,v $ * Revision 6.12 2008-08-12 05:00:22 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.11 2006/04/09 15:29:43 bert * Add acr_insert_double() * * Revision 6.10 2005/05/09 15:34:46 bert * For acr_find_{short,int,long,double}, treat a zero-length element as if it were absent, and return the default value. * * Revision 6.9 2005/03/11 22:05:29 bert * Implement _acr_name_proc to allow printing of field names in dump_acr_nema * * Revision 6.8 2005/03/04 17:09:11 bert * Change several functions to return Acr_Status instead of void; lose public and private; Make insert_element() check the return value of acr_get_element_total_length() * * Revision 6.7 2004/10/29 13:08:42 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.6 2002/12/08 22:31:34 neelin * When a last fragment is received, the dicom watchpoint is only updated when the next read happens, so the peek ahead will fail after the watchpoint test in acr_input_group_with_max. * * Revision 6.5 2001/11/08 14:17:05 neelin * Added acr_test_dicom_file to allow reading of DICOM part 10 format * files. This function also calls acr_test_byte_order to set up the stream * properly and can be used as a direct replacement for that function. * This set of changes does NOT include the ability to write part 10 files. * * Revision 6.4 2000/05/01 17:18:07 neelin * Modifications tohandle end-of-input properly, both on first group * read, and when ignoring protocol errors. * * Revision 6.3 2000/04/28 15:03:11 neelin * Added support for ignoring non-fatal protocol errors (cases where redundant * information is inconsistent). In particular, it is possible to ignore * differences between the group length element and the true group length. * * Revision 6.2 1999/10/29 17:51:53 neelin * Fixed Log keyword * * Revision 6.1 1998/11/06 19:41:06 neelin * Added functions acr_group_steal_element and acr_find_group. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.2 1997/08/21 13:24:55 neelin * Pre-release * * Revision 4.1 1997/06/17 23:49:08 neelin * Added routines for inserting elements into a group list. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.2 1995/02/08 21:16:06 neelin * Changes to make irix 5 lint happy. * * Revision 2.1 1995/01/04 08:10:16 neelin * Improved string printing in dump function (longer strings and replace * carriage returns, linefeeds and formfeeds by spaces). * * Revision 2.0 94/09/28 10:36:16 neelin * Release of minc version 0.2 * * Revision 1.11 94/09/28 10:35:45 neelin * Pre-release * * Revision 1.10 94/04/07 10:05:04 neelin * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs * to that or ACR_OTHER_ERROR. * Added #ifdef lint to DEFINE_ELEMENT. * * Revision 1.9 93/12/10 09:20:32 neelin * Added acr_find_ routines. * * Revision 1.8 93/12/08 09:04:59 neelin * Fixed memory leak in acr_input_group_with_max. * Fixed acr_input_group_list (didn't stop reading when reached max group). * * Revision 1.7 93/11/30 08:57:42 neelin * Added group and group list copy routines. * * Revision 1.6 93/11/26 18:47:51 neelin * Added group and group list copy routines. * * Revision 1.5 93/11/25 10:36:57 neelin * Fixed input_group_list (wasn't checking max properly). * * Revision 1.4 93/11/24 12:05:12 neelin * Changed format of dump. * * Revision 1.3 93/11/24 11:25:38 neelin * Added some group list stuff (dump, input_group_list). * * Revision 1.2 93/11/22 13:11:58 neelin * Changed to use new Acr_Element_Id stuff * * Revision 1.1 93/11/19 12:48:52 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include /* Private functions */ static void steal_element(Acr_Group group, Acr_Element element, Acr_Element previous); static void remove_element(Acr_Group group, Acr_Element element, Acr_Element previous); static Acr_Status insert_element(Acr_Group group, Acr_Element element, Acr_Element previous); static void update_group_length_element(Acr_Group group, Acr_VR_encoding_type vr_encoding); static Acr_Status acr_input_group_with_max(Acr_File *afp, Acr_Group *group, int max_group_id); acr_name_proc_t _acr_name_proc = NULL; /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_group @INPUT : group_id @OUTPUT : (none) @RETURNS : Pointer to group structure @DESCRIPTION: Creates an acr-nema group structure @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : February 4, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Group acr_create_group(int group_id) { Acr_Group group; Acr_Element length_element; long group_length = 0; /* Allocate the group */ group = MALLOC(sizeof(*group)); /* Create a length element */ group_length = 0; length_element = acr_create_element(group_id, ACR_EID_GRPLEN, ACR_VR_UL, (long) ACR_SIZEOF_LONG, acr_memdup((size_t) ACR_SIZEOF_LONG, &group_length)); /* Assign fields */ group->group_id = group_id; group->nelements = 1; group->implicit_total_length = acr_get_element_total_length(length_element, ACR_IMPLICIT_VR); group->explicit_total_length = acr_get_element_total_length(length_element, ACR_EXPLICIT_VR); group->list_head = length_element; group->list_tail = length_element; group->next = NULL; return group; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_delete_group @INPUT : group @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Deletes an acr-nema group structure (freeing the element list) @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_delete_group(Acr_Group group) { acr_delete_element_list(group->list_head); FREE(group); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_delete_group_list @INPUT : group_list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Delete a list of acr-nema group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_delete_group_list(Acr_Group group_list) { Acr_Group next, cur; /* Check for null group */ if (group_list == NULL) return; /* Loop through the list, deleting groups */ next = group_list; do { cur = next; next = cur->next; acr_delete_group(cur); } while (next != NULL); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_copy_group @INPUT : group @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Makes a copy of an acr-nema group structure @METHOD : @GLOBALS : @CALLS : @CREATED : November 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group acr_copy_group(Acr_Group group) { Acr_Group copy; Acr_Element cur; /* Create the group */ copy = acr_create_group(acr_get_group_group(group)); /* Get the second element (first element is always there) */ cur = acr_get_element_next(group->list_head); while (cur != NULL) { acr_group_add_element(copy, acr_copy_element(cur)); cur = acr_get_element_next(cur); } return copy; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_copy_group_list @INPUT : group_list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Make a copy of a group list @METHOD : @GLOBALS : @CALLS : @CREATED : November 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group acr_copy_group_list(Acr_Group group_list) { Acr_Group copy_list; Acr_Group copy_group; Acr_Group cur; /* Create first group */ copy_list = copy_group = acr_copy_group(group_list); /* Loop through groups */ cur = acr_get_group_next(group_list); while (cur != NULL) { acr_set_group_next(copy_group, acr_copy_group(cur)); copy_group = acr_get_group_next(copy_group); cur = acr_get_group_next(cur); } return copy_list; } /* ----------------------------- MNI Header ----------------------------------- @NAME : steal_element @INPUT : group element - element to remove previous - pointer to previous element or NULL if beginning of group element list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Steal an element from a group (remove it without deleting it). The caller must free the element themselves. @METHOD : @GLOBALS : @CALLS : @CREATED : November 6, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void steal_element(Acr_Group group, Acr_Element element, Acr_Element previous) { Acr_Element next; /* Get pointer to next element */ next = acr_get_element_next(element); /* Update the previous element or list head */ if (previous != NULL) acr_set_element_next(previous, next); else group->list_head = next; /* Check for an element at the tail */ if (next == NULL) group->list_tail = previous; /* Update the group fields */ group->nelements--; group->implicit_total_length -= acr_get_element_total_length(element, ACR_IMPLICIT_VR); group->explicit_total_length -= acr_get_element_total_length(element, ACR_EXPLICIT_VR); /* Update the group length element */ update_group_length_element(group, acr_get_element_vr_encoding(group->list_head)); } /* ----------------------------- MNI Header ----------------------------------- @NAME : remove_element @INPUT : group element - element to remove previous - pointer to previous element or NULL if beginning of group element list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Remove an element from a group. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void remove_element(Acr_Group group, Acr_Element element, Acr_Element previous) { /* Get rid of the old element from the group */ steal_element(group, element, previous); /* Delete the old element */ acr_delete_element(element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : insert_element @INPUT : group element - element to insert previous - pointer to previous element or NULL if beginning of group element list @OUTPUT : (none) @RETURNS : Acr_Status @DESCRIPTION: Insert an element into a group. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static Acr_Status insert_element(Acr_Group group, Acr_Element element, Acr_Element previous) { Acr_Element next; long length; /* Update the pointers */ if (previous != NULL) { /* Middle or tail of list */ next = acr_get_element_next(previous); acr_set_element_next(previous, element); } else { /* Head of list */ next = group->list_head; group->list_head = element; } acr_set_element_next(element, next); /* Check for the tail */ if (next == NULL) { group->list_tail = element; } /* Update the group fields */ group->nelements++; length = acr_get_element_total_length(element, ACR_IMPLICIT_VR); if (length <= 0) { return (ACR_OTHER_ERROR); } group->implicit_total_length += length; length = acr_get_element_total_length(element, ACR_EXPLICIT_VR); if (length <= 0) { return (ACR_OTHER_ERROR); } group->explicit_total_length += length; /* Update the length element */ update_group_length_element(group, acr_get_element_vr_encoding(group->list_head)); return (ACR_OK); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_group_insert_element @INPUT : group element @OUTPUT : (none) @RETURNS : Acr_Status @DESCRIPTION: Insert an element into a group. If an element of the same id already exists in the list, it is removed and deleted. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_group_insert_element(Acr_Group group, Acr_Element element) { Acr_Element next_element, prev_element, cur_element; int element_id; /* Check that the element belongs in this group */ if (group->group_id != acr_get_element_group(element)) { (void) fprintf(stderr, "ACR error: Cannot add element %d (group %d) to group %d\n", acr_get_element_element(element), acr_get_element_group(element), group->group_id); exit(EXIT_FAILURE); } /* Get element id */ element_id = acr_get_element_element(element); /* Check that new element has id > group length element id */ if (element_id < ACR_EID_GRPLEN) { (void) fprintf(stderr, "ACR error: Cannot add element id %d <= length id (%d) to group %d\n", element_id, ACR_EID_GRPLEN, group->group_id); exit(EXIT_FAILURE); } /* Check whether the the element should be added after the last element */ if (acr_get_element_element(group->list_tail) < element_id) { prev_element = group->list_tail; next_element = NULL; } /* Otherwise, search for the appropriate location */ else { prev_element = NULL; next_element = group->list_head; while ((next_element != NULL) && (acr_get_element_element(next_element) < element_id)) { prev_element = next_element; next_element = acr_get_element_next(next_element); } } /* Check for an existing element and get rid of it */ if ((next_element != NULL) && (acr_get_element_element(next_element) == element_id)) { /* Set pointers and get rid of the old element */ cur_element = next_element; next_element = acr_get_element_next(cur_element); remove_element(group, cur_element, prev_element); } /* Insert the new element */ return insert_element(group, element, prev_element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_group_add_element @INPUT : group element @OUTPUT : (none) @RETURNS : Acr_Status @DESCRIPTION: Add an element to an acr-nema group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_group_add_element(Acr_Group group, Acr_Element element) { /* Check that the element belongs in this group */ if (group->group_id != acr_get_element_group(element)) { (void) fprintf(stderr, "ACR error: Cannot add element %d (group %d) to group %d\n", acr_get_element_element(element), acr_get_element_group(element), group->group_id); exit(EXIT_FAILURE); } /* Insert the element at the tail */ return insert_element(group, element, group->list_tail); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_group_remove_element @INPUT : group element_id @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Remove an element from a group. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_group_remove_element(Acr_Group group, int element_id) { Acr_Element next_element, prev_element; /* Search for the appropriate location */ prev_element = NULL; next_element = group->list_head; while ((next_element != NULL) && (acr_get_element_element(next_element) != element_id)) { prev_element = next_element; next_element = acr_get_element_next(next_element); } /* Check for an existing element and get rid of it */ if ((next_element != NULL) && (acr_get_element_element(next_element) == element_id)) { /* Set pointers and get rid of the old element */ remove_element(group, next_element, prev_element); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_group_steal_element @INPUT : group element - the caller must pass an element so that we know that they have a handle to it. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Remove an element from a group without deleting it. @METHOD : @GLOBALS : @CALLS : @CREATED : November 6, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_group_steal_element(Acr_Group group, Acr_Element element) { int element_id; Acr_Element next_element, prev_element; /* Get element id from element */ element_id = acr_get_element_element(element); /* Search for the appropriate location */ prev_element = NULL; next_element = group->list_head; while ((next_element != NULL) && (acr_get_element_element(next_element) != element_id)) { prev_element = next_element; next_element = acr_get_element_next(next_element); } /* Check for an existing element and get rid of it */ if ((next_element != NULL) && (acr_get_element_element(next_element) == element_id)) { /* Set pointers and get rid of the old element */ steal_element(group, next_element, prev_element); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_group_length_element @INPUT : group vr_encoding - ACR_IMPLICIT_VR or ACR_EXPLICIT_VR @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Update the length element of the group according to the VR type @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void update_group_length_element(Acr_Group group, Acr_VR_encoding_type vr_encoding) { Acr_Long group_length; Acr_Element length_element; void *group_length_data; /* Get the element */ length_element = group->list_head; if (length_element == NULL) return; if (acr_get_element_element(length_element) != ACR_EID_GRPLEN) return; /* Calculate the appropriate length */ if (vr_encoding == ACR_IMPLICIT_VR) { group_length = group->implicit_total_length - acr_get_element_total_length(length_element, ACR_IMPLICIT_VR); } else { group_length = group->explicit_total_length - acr_get_element_total_length(length_element, ACR_EXPLICIT_VR); } /* Update the element */ group_length_data = acr_get_element_data(length_element); acr_put_long(acr_get_element_byte_order(length_element), 1, &group_length, group_length_data); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_set_group_next @INPUT : group next @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Set pointer to next group for an acr-nema group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_set_group_next(Acr_Group group, Acr_Group next) { group->next = next; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_group_group @INPUT : group @OUTPUT : (none) @RETURNS : group id @DESCRIPTION: Get group id for group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_get_group_group(Acr_Group group) { return group->group_id; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_group_element_list @INPUT : group @OUTPUT : (none) @RETURNS : element list @DESCRIPTION: Get element list for group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_get_group_element_list(Acr_Group group) { return group->list_head; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_group_total_length @INPUT : group vr_encoding - ACR_EXPLICIT_VR or ACR_IMPLICIT_VR @OUTPUT : (none) @RETURNS : total length of group @DESCRIPTION: Get total length of group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ long acr_get_group_total_length(Acr_Group group, Acr_VR_encoding_type vr_encoding) { if (vr_encoding == ACR_IMPLICIT_VR) return group->implicit_total_length; else return group->explicit_total_length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_group_nelements @INPUT : group @OUTPUT : (none) @RETURNS : number of elements in group @DESCRIPTION: Get number of elements in group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_get_group_nelements(Acr_Group group) { return group->nelements; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_group_next @INPUT : group @OUTPUT : (none) @RETURNS : next group @DESCRIPTION: Get next group for group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group acr_get_group_next(Acr_Group group) { return group->next; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_input_group_with_max @INPUT : afp - acr file pointer max_group_id - maximum group id to read in. If <= 0 then any group is read in. @OUTPUT : group @RETURNS : status @DESCRIPTION: Read in an acr-nema group with an optional maximum group id. If group id exceeds max, then *group is set to NULL. If an error occurs, then a group may still be returned. This routine will stop reading when it reaches a watchpoint. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static Acr_Status acr_input_group_with_max(Acr_File *afp, Acr_Group *group, int max_group_id) { int group_id, element_id, next_group_id; long group_length; Acr_Status status; Acr_Element element; int have_length_element; int get_more_elements; Acr_VR_encoding_type vr_encoding; /* Initialize the group pointer */ *group = NULL; /* Look ahead at the next element */ status = acr_peek_at_next_element_id(afp, &group_id, &element_id); if (status != ACR_OK) return status; /* Check for a group past the limit */ if ((max_group_id > 0) && (group_id > max_group_id)) { return status; } /* Check for a length element */ have_length_element = (element_id == ACR_EID_GRPLEN); /* Read the length element and check it */ if (have_length_element) { status = acr_input_element(afp, &element); if (status != ACR_OK) { acr_delete_element(element); return status; } if ((acr_get_element_element(element) != ACR_EID_GRPLEN) || (acr_get_element_length(element) != ACR_SIZEOF_LONG)) { if (acr_ignore_protocol_errors(afp)) { group_length = 0; } else { acr_delete_element(element); status = ACR_PROTOCOL_ERROR; return status; } } else { group_length = acr_get_element_long(element); } acr_delete_element(element); } /* Create the group */ *group = acr_create_group(group_id); /* Set the VR encoding and the byte ordering for the length element according to the input stream. If the vr_encoding is implicit, then make the VR unknown. Note that the group will always have a length element even if the input stream does not. */ element = acr_get_group_element_list(*group); vr_encoding = acr_get_vr_encoding(afp); acr_set_element_vr_encoding(element, vr_encoding); acr_set_element_byte_order(element, acr_get_byte_order(afp)); if (vr_encoding == ACR_IMPLICIT_VR) { acr_set_element_vr(element, ACR_VR_UNKNOWN); } /* Loop through elements, adding them to the list */ get_more_elements = (have_length_element ? (group_length > 0) : TRUE); while (get_more_elements) { /* Check for a watchpoint */ if (acr_get_io_watchpoint(afp) <= 0) { get_more_elements = FALSE; break; } /* Look ahead at next element */ status = acr_peek_at_next_element_id(afp, &next_group_id, &element_id); if ((status != ACR_OK) || (next_group_id != group_id)) { if ( status == ACR_REACHED_WATCHPOINT ) status = ACR_OK; get_more_elements = FALSE; break; } /* Read in the next element */ status = acr_input_element(afp, &element); if (status != ACR_OK) { get_more_elements = FALSE; } /* Add it to the group */ if (element != NULL) { acr_group_add_element(*group, element); if (have_length_element) { group_length -= acr_get_element_total_length(element, acr_get_vr_encoding(afp)); } } /* Check group length */ if (have_length_element && !acr_ignore_protocol_errors(afp)) { get_more_elements = (group_length > 0); } } /* Check that we got a full group */ if (have_length_element && (group_length != 0) && !acr_ignore_protocol_errors(afp)) { switch (status) { case ACR_OK: status = ACR_PROTOCOL_ERROR; break; case ACR_END_OF_INPUT: status = ACR_ABNORMAL_END_OF_INPUT; break; } } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_input_group @INPUT : afp - acr file pointer @OUTPUT : group @RETURNS : status @DESCRIPTION: Read in an acr-nema group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_input_group(Acr_File *afp, Acr_Group *group) { return acr_input_group_with_max(afp, group, 0); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_output_group @INPUT : afp - acr file pointer group @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Write out an acr-nema group @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_output_group(Acr_File *afp, Acr_Group group) { long ielement, nelements; Acr_Element cur, next; Acr_Status status; /* Update the length element */ update_group_length_element(group, acr_get_vr_encoding(afp)); /* Loop through the elements of the group, writing them out */ nelements = acr_get_group_nelements(group); next = acr_get_group_element_list(group); for (ielement=0; ielement < nelements && next != NULL; ielement++) { cur = next; next = cur->next; status = acr_output_element(afp, cur); if (status != ACR_OK) { return status; } } /* Check for a bogus group (the true number of elements is different from nelements) */ if ((ielement < nelements) || (next != NULL)) { status = ACR_OTHER_ERROR; return status; } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_input_group_list @INPUT : afp - acr file pointer max_group_id - maximum group id to read in. If <= 0 then all groups are read in. If max_group_id is not a group id in the input stream, then the input stream is left with the first element of the next group missing (it gets read here and is not put back), so no more groups can be read in. @OUTPUT : group_list @RETURNS : status @DESCRIPTION: Read in a list of acr-nema groups. If a watchpoint is set on the input handle, then group reading will stop when it is reached, although at least one group will be read in. @METHOD : @GLOBALS : @CALLS : @CREATED : November 24, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_input_group_list(Acr_File *afp, Acr_Group *group_list, int max_group_id) { Acr_Group cur_group, next_group; Acr_Status status; /* Initialize the group list */ *group_list = NULL; /* Read in the first group */ status = acr_input_group_with_max(afp, &next_group, max_group_id); /* Set up pointers */ *group_list = cur_group = next_group; /* Loop, reading groups */ while ((status == ACR_OK) && (cur_group != NULL) && ((max_group_id <= 0) || (acr_get_group_group(cur_group) < max_group_id))) { /* Check for a watchpoint */ if (acr_get_io_watchpoint(afp) <= 0) { break; } /* Read in the next group */ status = acr_input_group_with_max(afp, &next_group, max_group_id); /* Add it to the list */ acr_set_group_next(cur_group, next_group); cur_group = next_group; } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_group @INPUT : group_list group_id @OUTPUT : (none) @RETURNS : gropu pointer @DESCRIPTION: Find a group in a group list @METHOD : @GLOBALS : @CALLS : @CREATED : November 6, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group acr_find_group(Acr_Group group_list, int group_id) { Acr_Group group; int next_id; /* Search through groups for group id */ group = group_list; if (group != NULL) next_id = acr_get_group_group(group); else next_id = 0; while ((next_id != group_id) && (group != NULL)) { group = acr_get_group_next(group); if (group != NULL) next_id = acr_get_group_group(group); } return group; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_group_element @INPUT : group_list elid @OUTPUT : (none) @RETURNS : element pointer @DESCRIPTION: Find an element in a group list @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Element acr_find_group_element(Acr_Group group_list, Acr_Element_Id elid) { Acr_Group group; /* Find the group */ group = acr_find_group(group_list, elid->group_id); /* If not found return NULL */ if (group == NULL) return NULL; /* Search through element list for element */ return acr_find_element_id(acr_get_group_element_list(group), elid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dump_group_list @INPUT : file_pointer - where output should go group_list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Dump information from an acr-nema group list @METHOD : @GLOBALS : @CALLS : @CREATED : November 24, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void acr_dump_group_list(FILE *file_pointer, Acr_Group group_list) { Acr_Group cur_group; /* Check for empty list */ cur_group = group_list; if (cur_group == NULL) { (void) fprintf(file_pointer,"\nEmpty group list\n\n"); return; } /* Loop over groups */ while (cur_group != NULL) { /* Print the group id */ (void) fprintf(file_pointer, "\nGroup 0x%04x :\n\n", acr_get_group_group(cur_group)); /* Print the elements */ acr_dump_element_list(file_pointer, acr_get_group_element_list(cur_group)); /* Go to the next group */ cur_group = acr_get_group_next(cur_group); } /* Print a blank line after dump */ (void) fprintf(file_pointer, "\n"); /* Flush the buffer */ (void) fflush(file_pointer); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_short @INPUT : group_list elid default_value @OUTPUT : (none) @RETURNS : Element value or default_value if element not found @DESCRIPTION: Find an element in a group list and return its value (assuming that it is stored as a binary short). @METHOD : @GLOBALS : @CALLS : @CREATED : December 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Short acr_find_short(Acr_Group group_list, Acr_Element_Id elid, Acr_Short default_value) { Acr_Element element; element = acr_find_group_element(group_list, elid); if (element != NULL && acr_get_element_length(element) > 0) return acr_get_element_short(element); else return default_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_long @INPUT : group_list elid default_value @OUTPUT : (none) @RETURNS : Element value or default_value if element not found @DESCRIPTION: Find an element in a group list and return its value (assuming that it is stored as a binary long). @METHOD : @GLOBALS : @CALLS : @CREATED : December 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Long acr_find_long(Acr_Group group_list, Acr_Element_Id elid, Acr_Long default_value) { Acr_Element element; element = acr_find_group_element(group_list, elid); if (element != NULL && acr_get_element_length(element) > 0) return acr_get_element_long(element); else return default_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_int @INPUT : group_list elid default_value @OUTPUT : (none) @RETURNS : Element value or default_value if element not found @DESCRIPTION: Find an element in a group list and return its value (assuming that it is stored as an ascii integer). @METHOD : @GLOBALS : @CALLS : @CREATED : December 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_find_int(Acr_Group group_list, Acr_Element_Id elid, int default_value) { Acr_Element element; element = acr_find_group_element(group_list, elid); if (element != NULL && acr_get_element_length(element) > 0) return (int) acr_get_element_numeric(element); else return default_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_double @INPUT : group_list elid default_value @OUTPUT : (none) @RETURNS : Element value or default_value if element not found @DESCRIPTION: Find an element in a group list and return its value (assuming that it is stored as an ascii double). @METHOD : @GLOBALS : @CALLS : @CREATED : December 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Double acr_find_double(Acr_Group group_list, Acr_Element_Id elid, Acr_Double default_value) { Acr_Element element; element = acr_find_group_element(group_list, elid); if (element != NULL && acr_get_element_length(element) > 0) return (Acr_Double)acr_get_element_numeric(element); else return default_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_find_string @INPUT : group_list elid default_value @OUTPUT : (none) @RETURNS : Element value or default_value if element not found @DESCRIPTION: Find an element in a group list and return its value (assuming that it is stored as an ascii string). @METHOD : @GLOBALS : @CALLS : @CREATED : December 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_String acr_find_string(Acr_Group group_list, Acr_Element_Id elid, Acr_String default_value) { Acr_Element element; element = acr_find_group_element(group_list, elid); if (element != NULL) /* Allow zero-length strings */ return acr_get_element_string(element); else return default_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_insert_element_into_group_list @INPUT : group_list - list in which element should be inserted (can be NULL) element - element to insert @OUTPUT : group_list - modified group list @RETURNS : Acr_Status @DESCRIPTION: Insert an element into a group list. If the group_list is NULL, then it is created. Note that the element is not copied, it is just inserted into the list, so it should not be modified after insertion into the list. If an element of the same id already exists in the list, it is removed and deleted. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_insert_element_into_group_list(Acr_Group *group_list, Acr_Element element) { Acr_Group group, next_group, prev_group; int group_id; /* Get group and element id */ group_id = acr_get_element_group(element); /* Search for the appropriate group */ prev_group = NULL; next_group = *group_list; while ((next_group != NULL) && (acr_get_group_group(next_group) < group_id)) { prev_group = next_group; next_group = acr_get_group_next(next_group); } /* Check if we have the right group */ if ((next_group != NULL) && (acr_get_group_group(next_group) == group_id)) { group = next_group; } /* If not, create a new group and insert it in the list */ else { /* Create a group */ group = acr_create_group(group_id); /* Insert it in the list */ acr_set_group_next(group, next_group); if (prev_group != NULL) { acr_set_group_next(prev_group, group); } else { *group_list = group; } } /* Insert the element into the appropriate group */ return acr_group_insert_element(group, element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_insert_short @INPUT : group_list - may be NULL if list empty elid value @OUTPUT : group_list - modified group list @RETURNS : Acr_Status @DESCRIPTION: Creates and inserts an element into a group list. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_insert_short(Acr_Group *group_list, Acr_Element_Id elid, Acr_Short value) { Acr_Element element; element = acr_create_element_short(elid, value); return acr_insert_element_into_group_list(group_list, element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_insert_long @INPUT : group_list - may be NULL if list empty elid value @OUTPUT : group_list - modified group list @RETURNS : Acr_Status @DESCRIPTION: Creates and inserts an element into a group list. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_insert_long(Acr_Group *group_list, Acr_Element_Id elid, Acr_Long value) { Acr_Element element; element = acr_create_element_long(elid, value); return acr_insert_element_into_group_list(group_list, element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_insert_double @INPUT : group_list - may be NULL if list empty elid nvalues values @OUTPUT : group_list - modified group list @RETURNS : Acr_Status @DESCRIPTION: Creates and inserts an element into a group list. @METHOD : @GLOBALS : @CALLS : @CREATED : April 8, 2006 (Bert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_insert_double(Acr_Group *group_list, Acr_Element_Id elid, int nvalues, Acr_Double *values) { Acr_Element element; element = acr_create_element_double(elid, nvalues, values); return acr_insert_element_into_group_list(group_list, element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_insert_numeric @INPUT : group_list - may be NULL if list empty elid value @OUTPUT : group_list - modified group list @RETURNS : Acr_Status @DESCRIPTION: Creates and inserts an element into a group list. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_insert_numeric(Acr_Group *group_list, Acr_Element_Id elid, double value) { Acr_Element element; element = acr_create_element_numeric(elid, value); return acr_insert_element_into_group_list(group_list, element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_insert_string @INPUT : group_list - may be NULL if list empty elid value @OUTPUT : group_list - modified group list @RETURNS : Acr_Status @DESCRIPTION: Creates and inserts an element into a group list. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_insert_string(Acr_Group *group_list, Acr_Element_Id elid, Acr_String value) { Acr_Element element; element = acr_create_element_string(elid, value); return acr_insert_element_into_group_list(group_list, element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_insert_sequence @INPUT : group_list - may be NULL if list empty elid itemlist @OUTPUT : group_list - modified group list @RETURNS : Acr_Status @DESCRIPTION: Creates and inserts an element into a group list. @METHOD : @GLOBALS : @CALLS : @CREATED : June 17, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_insert_sequence(Acr_Group *group_list, Acr_Element_Id elid, Acr_Element itemlist) { Acr_Element element; element = acr_create_element_sequence(elid, itemlist); return acr_insert_element_into_group_list(group_list, element); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_test_dicom_file @INPUT : afp @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Tests for a dicom file input, as well as setting the byte order and VR encoding. @METHOD : Check the byte order and t This function is in this file because it does not really have a better place to live: It depends on the group reading code (and so should not live in acr_io.c) and is independent of the other dicom code (and so should not live there). @GLOBALS : @CALLS : acr_test_byte_order, acr_input_group_list @CREATED : November 8, 2001 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_test_dicom_file(Acr_File *afp) { #define DICOM_FILE_MAGIC_OFFSET 128 #define DICOM_MAGIC_STRING "DICM" #define DICOM_MAGIC_LEN 4 #define DICOM_FILE_GROUP 0x2 unsigned char buffer[DICOM_FILE_MAGIC_OFFSET+DICOM_MAGIC_LEN]; Acr_Status status; long buflen; Acr_Group group_list; /* Read in up to magic */ status = acr_read_buffer(afp, buffer, sizeof(buffer), &buflen); if (status != ACR_OK) return status; /* Check for the magic. If it is not there, put the data back and then test the byte order. */ if (strncmp((char *) &buffer[DICOM_FILE_MAGIC_OFFSET], DICOM_MAGIC_STRING, DICOM_MAGIC_LEN) != 0) { status = acr_unget_buffer(afp, buffer, buflen); if (status != ACR_OK) return status; return acr_test_byte_order(afp); } /* Read in group 2. We could get the transfer syntax in the group at this point, or just use the test heuristic from acr_test_byte_order. It seems safer to trust the heuristic than the file writer, so we will ignore the contents of the group. */ status = acr_test_byte_order(afp); if (status != ACR_OK) return status; status = acr_input_group_list(afp, &group_list, DICOM_FILE_GROUP); acr_delete_group_list(group_list); if (status != ACR_OK) return status; /* Test the byte order for the remainder of the file */ status = acr_test_byte_order(afp); if (status != ACR_OK) return status; return status; } minc-2.2.00/conversion/Acr_nema/message.c0000644000265600003100000004750012027132660015126 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : message.c @DESCRIPTION: Routines for doing acr_nema message operations. @METHOD : @GLOBALS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : * $Log: message.c,v $ * Revision 6.8 2008-08-12 05:00:22 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.7 2004/10/29 13:08:42 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.6 2002/12/08 21:43:08 neelin * Fixed excessive memory freeing on error when reading message (seen in linux) * * Revision 6.5 2002/11/13 03:00:27 neelin * Fixed an unterminated comment * * Revision 6.4 1999/10/29 17:51:53 neelin * Fixed Log keyword * * Revision 6.3 1998/03/10 17:06:29 neelin * Added code to acr_input_message so that if we reach the watchpoint and * more message is expected, we keep on reading. * * Revision 6.2 1998/03/09 19:30:23 neelin * Fixed bug in acr_input_message where the last group added to the input * message was being deleted followed by the message itself when a * message length error occurred. When an input error occurs the message * should not be deleted. * * Revision 6.1 1998/02/18 20:27:13 neelin * Minor bug fix. * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.1 1997/06/13 21:27:16 neelin * Made use of message length to figure out how much to read in - * previously was not checking it, so if watchpoint was not set, we would * read indefinitely. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:17 neelin * Release of minc version 0.2 * * Revision 1.6 94/09/28 10:35:49 neelin * Pre-release * * Revision 1.5 94/05/18 08:48:12 neelin * Changed some ACR_OTHER_ERROR's to ACR_ABNORMAL_END_OF_OUTPUT. * * Revision 1.4 94/04/07 10:05:06 neelin * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs * to that or ACR_OTHER_ERROR. * Added #ifdef lint to DEFINE_ELEMENT. * * Revision 1.3 93/11/24 11:25:59 neelin * Added dump_message. * * Revision 1.2 93/11/22 13:12:09 neelin * Changed to use new Acr_Element_Id stuff * * Revision 1.1 93/11/19 12:49:09 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include /* Message length group and element id */ #define ACR_GID_MESSLEN 0 #define ACR_EID_MESSLEN 1 DEFINE_ELEMENT(static, ACR_Message_length, ACR_GID_MESSLEN, ACR_EID_MESSLEN, UL); /* Private functions */ private void update_message_length_element(Acr_Message message, Acr_VR_encoding_type vr_encoding); /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_create_message @INPUT : (none) @OUTPUT : (none) @RETURNS : Pointer to message structure @DESCRIPTION: Creates an acr-nema message structure. @METHOD : No groups are created here. Message length is checked when groups are added. @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Acr_Message acr_create_message(void) { Acr_Message message; /* Allocate the message */ message = MALLOC(sizeof(*message)); /* Assign fields */ acr_message_reset(message); return message; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_delete_message @INPUT : message @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Deletes an acr-nema message structure (freeing the group list) @METHOD : @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_delete_message(Acr_Message message) { if (message->list_head != NULL) { acr_delete_group_list(message->list_head); } FREE(message); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_message_reset @INPUT : message @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Resets the message to empty without freeing any existing group list. Thus the group list can be used elsewhere without being deleted when the message is deleted. @METHOD : @GLOBALS : @CALLS : @CREATED : February 18, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_message_reset(Acr_Message message) { message->ngroups = 0; message->implicit_total_length = 0; message->explicit_total_length = 0; message->message_implicit_offset = 0; message->message_explicit_offset = 0; message->message_length_element = NULL; message->list_head = NULL; message->list_tail = NULL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_message_add_group @INPUT : message group @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Add a group to an acr-nema message @METHOD : If this is the first group, then look for a message length element. If none is found, then report an error. @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : February 7, 1997 (P.N.) ---------------------------------------------------------------------------- */ public void acr_message_add_group(Acr_Message message, Acr_Group group) { Acr_Element length_element; int element_id; long message_implicit_offset, message_explicit_offset; /* If first message, then check for message length element */ if (message->ngroups == 0) { length_element = NULL; message_implicit_offset = 0; message_explicit_offset = 0; if (acr_get_group_group(group) == ACR_GID_MESSLEN) { length_element = acr_get_group_element_list(group); if (length_element != NULL) { element_id = acr_get_element_element(length_element); message_implicit_offset = acr_get_element_total_length(length_element, ACR_IMPLICIT_VR); message_explicit_offset = acr_get_element_total_length(length_element, ACR_EXPLICIT_VR); } else { element_id = 0; message_implicit_offset = 0; message_explicit_offset = 0; } while ((element_id != ACR_EID_MESSLEN) && (length_element != NULL)) { length_element = acr_get_element_next(length_element); if (length_element != NULL) { element_id = acr_get_element_element(length_element); message_implicit_offset += acr_get_element_total_length(length_element, ACR_IMPLICIT_VR); message_explicit_offset += acr_get_element_total_length(length_element, ACR_EXPLICIT_VR); } } } /* Check for length element found but not of correct length */ if ((length_element != NULL) && (acr_get_element_length(length_element) != ACR_SIZEOF_LONG)) { (void) fprintf(stderr, "ACR error: First message group contains length element of wrong size\n"); exit(EXIT_FAILURE); } /* Set up the message length info */ message->message_implicit_offset = message_implicit_offset; message->message_explicit_offset = message_explicit_offset; message->message_length_element = length_element; } /* Add group (check for empty list) */ if (message->ngroups == 0) { message->list_head = group; message->list_tail = group; } else { acr_set_group_next(message->list_tail, group); message->list_tail = group; acr_set_group_next(group, NULL); } message->ngroups++; message->implicit_total_length += acr_get_group_total_length(group, ACR_IMPLICIT_VR); message->explicit_total_length += acr_get_group_total_length(group, ACR_EXPLICIT_VR); /* Update the length element */ if (message->message_length_element != NULL) { update_message_length_element(message, acr_get_element_vr_encoding(message->message_length_element)); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_message_length_element @INPUT : message vr_encoding - ACR_IMPLICIT_VR or ACR_EXPLICIT_VR @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Update the length element of the message according to the VR type @METHOD : @GLOBALS : @CALLS : @CREATED : February 14, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private void update_message_length_element(Acr_Message message, Acr_VR_encoding_type vr_encoding) { Acr_Long message_length; Acr_Element length_element; void *message_length_data; /* Get the element */ length_element = message->message_length_element; if (length_element == NULL) return; /* Calculate the appropriate length */ if (vr_encoding == ACR_IMPLICIT_VR) { message_length = message->implicit_total_length - message->message_implicit_offset; } else { message_length = message->explicit_total_length - message->message_explicit_offset; } /* Update the element */ message_length_data = acr_get_element_data(length_element); acr_put_long(acr_get_element_byte_order(length_element), 1, &message_length, message_length_data); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_message_add_group_list @INPUT : message group_list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Add a group list to an acr-nema message @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_message_add_group_list(Acr_Message message, Acr_Group group_list) { Acr_Group next_group, group; /* Loop through groups, adding them to the message */ group = group_list; while (group != NULL) { next_group = acr_get_group_next(group); acr_set_group_next(group, NULL); acr_message_add_group(message, group); group = next_group; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_message_group_list @INPUT : message @OUTPUT : (none) @RETURNS : group list @DESCRIPTION: Get group list for message @METHOD : @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Acr_Group acr_get_message_group_list(Acr_Message message) { return message->list_head; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_message_total_length @INPUT : message vr_encoding - ACR_EXPLICIT_VR or ACR_IMPLICIT_VR @OUTPUT : (none) @RETURNS : total length of message @DESCRIPTION: Get total length of message depending on type of VR encoding @METHOD : @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public long acr_get_message_total_length(Acr_Message message, Acr_VR_encoding_type vr_encoding) { if (vr_encoding == ACR_IMPLICIT_VR) return message->implicit_total_length; else return message->explicit_total_length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_message_ngroups @INPUT : message @OUTPUT : (none) @RETURNS : number of groups in message @DESCRIPTION: Get number of groups in message @METHOD : @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int acr_get_message_ngroups(Acr_Message message) { return message->ngroups; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_input_message @INPUT : afp - acr file pointer @OUTPUT : message @RETURNS : status @DESCRIPTION: Read in an acr-nema message. The amount of input to read is determined either by setting a watchpoint or by having messages that contain their own length. One cannot rely on finding an EOF (as for a file) since messages usually come over a connection. @METHOD : @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : February 7, 1997 (P.N.) ---------------------------------------------------------------------------- */ public Acr_Status acr_input_message(Acr_File *afp, Acr_Message *message) { Acr_Status status; Acr_Group group; Acr_Element length_element; Acr_Long lvalue; long message_length; long group_length; long watchpoint; int get_more_groups; /* Initialize the message pointer */ *message = NULL; /* Read in the first group */ status = acr_input_group(afp, &group); /* Check status */ if (status != ACR_OK) { if (group != NULL) acr_delete_group(group); return status; } /* Check whether it contains the message length. If there is no watchpoint, then it must contain the length, otherwise we don't know when to stop reading (we would if the input was from a file, but messages don't usually come from a file) */ length_element = acr_find_group_element(group, ACR_Message_length); if ((acr_get_io_watchpoint(afp) == ACR_NO_WATCHPOINT) && ((length_element == NULL) || (acr_get_element_length(length_element) != ACR_SIZEOF_LONG))) { acr_delete_group(group); status = ACR_PROTOCOL_ERROR; return status; } /* Get the message length from the element */ if (length_element != NULL) { acr_get_long(acr_get_element_byte_order(length_element), (long) 1, acr_get_element_data(length_element), &lvalue); message_length = (long)lvalue; } /* Create the message and add the group (this will modify the message length element value to include only the first group) */ *message = acr_create_message(); acr_message_add_group(*message, group); /* Correct message_length for the length of the first group. Note that adding the group had the side effect of changing the message length to include only the first group */ if (length_element != NULL) { acr_get_long(acr_get_element_byte_order(length_element), (long) 1, acr_get_element_data(length_element), &lvalue); group_length = (long)lvalue; message_length -= group_length; } /* Loop through elements, adding them to the list */ get_more_groups = ((length_element != NULL) ? (message_length > 0) : TRUE); while (get_more_groups) { /* Check for a watchpoint. If we have reached it, but the message length indicates that there is more to come, then move it along so that we can keep reading. */ watchpoint = acr_get_io_watchpoint(afp); if ((watchpoint == 0) && (length_element != NULL) && (message_length > 0)) { acr_set_io_watchpoint(afp, LONG_MAX-1); } else if (watchpoint <= 0) { get_more_groups = FALSE; break; } /* If we reach the end of a fragment and PDU, but we need more data */ /* Read in the next group and check for an error */ status = acr_input_group(afp, &group); /* Add the group to the message */ if (group != NULL) { acr_message_add_group(*message, group); } /* Check the status */ if (status != ACR_OK) { if (status == ACR_END_OF_INPUT) status = ACR_ABNORMAL_END_OF_INPUT; return status; } /* Keep track of remaining bytes to read, if necessary */ if (length_element != NULL) { message_length -= acr_get_group_total_length(group, acr_get_vr_encoding(afp)); get_more_groups = (message_length > 0); } } /* Check that we got a full message */ if ((length_element != NULL) && (message_length != 0)) { status = ACR_PROTOCOL_ERROR; return status; } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_output_message @INPUT : afp - acr file pointer message @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Write out an acr-nema message @METHOD : @GLOBALS : @CALLS : @CREATED : November 16, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Acr_Status acr_output_message(Acr_File *afp, Acr_Message message) { long igroup, ngroups; Acr_Group cur, next; Acr_Status status; /* Update the length element */ update_message_length_element(message, acr_get_vr_encoding(afp)); /* Loop through the groups of the message, writing them out */ ngroups = acr_get_message_ngroups(message); next = acr_get_message_group_list(message); for (igroup=0; igroup < ngroups && next != NULL; igroup++) { cur = next; next = cur->next; status = acr_output_group(afp, cur); if (status != ACR_OK) { return status; } } /* Flush the buffer */ if (acr_file_flush(afp) == EOF) { status = ACR_ABNORMAL_END_OF_OUTPUT; return status; } /* Check for a bogus message (the true number of groups is different from ngroups) */ if ((igroup < ngroups) || (next != NULL)) { status = ACR_OTHER_ERROR; return status; } return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_dump_message @INPUT : file_pointer - where output should go group_list @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Dump information from an acr-nema message @METHOD : @GLOBALS : @CALLS : @CREATED : November 24, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void acr_dump_message(FILE *file_pointer, Acr_Message message) { acr_dump_group_list(file_pointer, acr_get_message_group_list(message)); return; } minc-2.2.00/conversion/Acr_nema/value_repr.c0000644000265600003100000005074012027132660015646 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : value_repr.c @DESCRIPTION: Routines for doing acr_nema VR and value conversion operations. @METHOD : @GLOBALS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : * $Log: value_repr.c,v $ * Revision 6.5 2008-08-12 05:00:22 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 6.4 2005/03/04 00:08:37 bert * Lose private and public * * Revision 6.3 2004/10/29 13:08:42 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.2 2000/08/16 15:53:46 neelin * Added VR type UN (unknown) which has a length field similar to OB. * * Revision 6.1 1999/10/29 17:51:54 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.1 1997/07/10 17:13:53 neelin * Fixed lookup of VR names so that both letters are used. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 1.2 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 1.1 1997/02/11 16:23:43 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include /* Types for VR table entries and conversion functions */ typedef struct Acr_VR_Entry Acr_VR_Entry; typedef double (*Acr_VR_Numeric_Function) (Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); typedef char * (*Acr_VR_String_Function) (Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); struct Acr_VR_Entry { Acr_VR_Type vr_code; char *vr_name; Acr_VR_Numeric_Function convert_to_numeric; Acr_VR_String_Function convert_to_string; }; /* Private functions */ static void check_table_integrity(); static Acr_VR_Entry *get_vr_entry(Acr_VR_Type vr_code); static Acr_VR_Type find_vr_name(char *vr_name); static double return_zero(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static double string_to_numeric(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static double get_short(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static double get_long(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static double get_float(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static double get_double(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static double guess_numeric_type(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static void extend_internal_buffer(int length); static char *return_empty_string(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static char *return_the_string(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); static char *numeric_to_string(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length); /* Table of VRs and conversion routines */ static Acr_VR_Entry VR_table[] = { {ACR_VR_UNKNOWN, "\0\0", guess_numeric_type, return_the_string }, {ACR_VR_AE, "AE", return_zero, return_the_string }, {ACR_VR_AS, "AS", string_to_numeric, return_the_string }, {ACR_VR_AT, "AT", get_long, numeric_to_string }, {ACR_VR_CS, "CS", string_to_numeric, return_the_string }, {ACR_VR_DA, "DA", string_to_numeric, return_the_string }, {ACR_VR_DS, "DS", string_to_numeric, return_the_string }, {ACR_VR_DT, "DT", string_to_numeric, return_the_string }, {ACR_VR_FL, "FL", get_float, numeric_to_string }, {ACR_VR_FD, "FD", get_double, numeric_to_string }, {ACR_VR_IS, "IS", string_to_numeric, return_the_string }, {ACR_VR_LO, "LO", string_to_numeric, return_the_string }, {ACR_VR_LT, "LT", string_to_numeric, return_the_string }, {ACR_VR_OB, "OB", return_zero, return_empty_string }, {ACR_VR_OW, "OW", return_zero, return_empty_string }, {ACR_VR_PN, "PN", return_zero, return_the_string }, {ACR_VR_SH, "SH", string_to_numeric, return_the_string }, {ACR_VR_SL, "SL", get_long, numeric_to_string }, {ACR_VR_SQ, "SQ", return_zero, return_empty_string }, {ACR_VR_SS, "SS", get_short, numeric_to_string }, {ACR_VR_ST, "ST", string_to_numeric, return_the_string }, {ACR_VR_TM, "TM", string_to_numeric, return_the_string }, {ACR_VR_UI, "UI", return_zero, return_the_string }, {ACR_VR_UL, "UL", get_long, numeric_to_string }, {ACR_VR_US, "US", get_short, numeric_to_string }, {ACR_VR_UN, "UN", return_zero, return_empty_string }, {ACR_VR_NUM_TYPES, NULL, NULL, NULL} }; /* Table for unknown VRs */ static Acr_VR_Entry *unknown_VR_table = NULL; static int unknown_VR_table_length = 0; static int table_integrity_checked = FALSE; /* Macros */ #define CHECK_TABLE_INTEGRITY \ {if (!table_integrity_checked) {check_table_integrity();}} /* ----------------------------- MNI Header ----------------------------------- @NAME : check_table_integrity @INPUT : (none) @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Checks the table for consistency and exits with failure if a problem is found. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void check_table_integrity() { int ientry; /* Don't do anything if check has already been performed */ if (table_integrity_checked) return; /* Check size of table */ if (sizeof(VR_table)/sizeof(VR_table[0]) != ACR_VR_NUM_TYPES+1) { (void) fprintf(stderr, "Internal error: VR table size is wrong!\n"); exit(EXIT_FAILURE); } /* Check each entry for the correct VR code */ for (ientry=0; ientry < ACR_VR_NUM_TYPES+1; ientry++) { if (VR_table[ientry].vr_code != ientry) { (void) fprintf(stderr, "Internal error: VR code mismatch in table\n"); exit(EXIT_FAILURE); } } /* Set flag */ table_integrity_checked = TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_vr_entry @INPUT : vr_code - the internal VR code to look up @OUTPUT : (none) @RETURNS : Pointer to VR table entry @DESCRIPTION: Looks up a VR table entry in the appropriate table based on the internal VR code. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static Acr_VR_Entry *get_vr_entry(Acr_VR_Type vr_code) { CHECK_TABLE_INTEGRITY; /* Check to see if we have a bogus vr_code */ if ((vr_code < 0) || (vr_code >= ACR_VR_NUM_TYPES+unknown_VR_table_length)) { return NULL; } /* Check to see if vr_code is in standard table or not */ if (vr_code < ACR_VR_NUM_TYPES) { return &VR_table[vr_code]; } else { return &unknown_VR_table[vr_code-ACR_VR_NUM_TYPES]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : find_vr_name @INPUT : vr_name - the 2-letter VR name to look up @OUTPUT : (none) @RETURNS : Internal VR code @DESCRIPTION: Looks up a VR table entry in the appropriate table based on the 2-letter VR name. If nothing is found, -1 is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static Acr_VR_Type find_vr_name(char *vr_name) { int ientry; CHECK_TABLE_INTEGRITY; /* Loop through standard VR table */ for (ientry=0; ientry < ACR_VR_NUM_TYPES; ientry++) { if ((VR_table[ientry].vr_name[0] == vr_name[0]) && (VR_table[ientry].vr_name[1] == vr_name[1])) { return (Acr_VR_Type) ientry; } } /* Loop through unknown VR table */ for (ientry=0; ientry < unknown_VR_table_length; ientry++) { if ((unknown_VR_table[ientry].vr_name[0] == vr_name[0]) && (unknown_VR_table[ientry].vr_name[1] == vr_name[1])) { return (Acr_VR_Type) ientry+ACR_VR_NUM_TYPES; } } return (Acr_VR_Type) -1; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_vr_name @INPUT : vr_code - the internal VR code @OUTPUT : (none) @RETURNS : VR name @DESCRIPTION: Gets the name corresponding to a VR code, returning a pointer to the table string (don't free it!). NULL is returned if the code is not found. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ char *acr_get_vr_name(Acr_VR_Type vr_code) { Acr_VR_Entry *entry; if ((entry = get_vr_entry(vr_code)) == NULL) { return NULL; } return entry->vr_name; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_test_vr_name @INPUT : vr_name - the 2-letter VR name to look up @OUTPUT : (none) @RETURNS : TRUE if vr_name is found @DESCRIPTION: Checks to see if VR name is standard. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int acr_test_vr_name(char *vr_name) { Acr_VR_Type vr_code; vr_code = find_vr_name(vr_name); return ((vr_code >= 0) && (vr_code < ACR_VR_NUM_TYPES)); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_lookup_vr_name @INPUT : vr_name - the 2-letter VR name to look up @OUTPUT : (none) @RETURNS : Internal VR code @DESCRIPTION: Looks up a VR name in the table. If it does not exist, the name is added to the unknown table. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_VR_Type acr_lookup_vr_name(char *vr_name) { Acr_VR_Type vr_code; int ientry; char *string; /* Look up the name and return the matching code if found */ vr_code = find_vr_name(vr_name); if (vr_code >= 0) { return vr_code; } /* If name is not found, add it to the unknown table */ if (unknown_VR_table_length <= 0) { unknown_VR_table_length = 1; unknown_VR_table = MALLOC((size_t) unknown_VR_table_length * sizeof(*unknown_VR_table)); } else { unknown_VR_table_length++; unknown_VR_table = REALLOC(unknown_VR_table, (size_t) unknown_VR_table_length * sizeof(*unknown_VR_table)); } /* Fill in the entry */ ientry = unknown_VR_table_length-1; unknown_VR_table[ientry].vr_code = ientry + ACR_VR_NUM_TYPES; string = MALLOC(3); string[0] = vr_name[0]; string[1] = vr_name[1]; string[2] = '\0'; unknown_VR_table[ientry].vr_name = string; unknown_VR_table[ientry].convert_to_numeric = return_zero; unknown_VR_table[ientry].convert_to_string = return_empty_string; /* Return the code */ return unknown_VR_table[ientry].vr_code; } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_numeric_vr @INPUT : vr_code - the internal VR code byte_order - ACR_BIG_ENDIAN or ACR_LITTLE_ENDIAN data - the data to convert data_length - the length of the data @OUTPUT : (none) @RETURNS : The converted value. @DESCRIPTION: Convert a value to a number according to its VR. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ double acr_get_numeric_vr(Acr_VR_Type vr_code, Acr_byte_order byte_order, char *data, long data_length) { Acr_VR_Entry *entry; if ((entry = get_vr_entry(vr_code)) == NULL) { return return_zero(entry, byte_order, data, data_length); } return entry->convert_to_numeric(entry, byte_order, data, data_length); } /* ----------------------------- MNI Header ----------------------------------- @NAME : acr_get_string_vr @INPUT : vr_code - the internal VR code byte_order - ACR_BIG_ENDIAN or ACR_LITTLE_ENDIAN data - the data to convert data_length - the length of the data @OUTPUT : (none) @RETURNS : The converted value. @DESCRIPTION: Convert a value to a string according to its VR. The pointer returned is to an internal buffer. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ char *acr_get_string_vr(Acr_VR_Type vr_code, Acr_byte_order byte_order, char *data, long data_length) { Acr_VR_Entry *entry; if ((entry = get_vr_entry(vr_code)) == NULL) { return return_empty_string(entry, byte_order, data, data_length); } return entry->convert_to_string(entry, byte_order, data, data_length); } /* ----------------------------- MNI Header ----------------------------------- @NAME : return_zero string_to_numeric get_short get_long get_float get_double @INPUT : vr_entry - pointer to VR table entry byte_order - ACR_BIG_ENDIAN or ACR_LITTLE_ENDIAN data - a pointer to the actual data data_length - number of bytes in the data @OUTPUT : (none) @RETURNS : Numeric equivalent of data @DESCRIPTION: Routines to convert values from a DICOM form to a number @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ /* ARGSUSED */ static double return_zero(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { return 0.0; } /* ARGSUSED */ static double string_to_numeric(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { return atof((char *) data); } /* ARGSUSED */ static double get_short(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { Acr_Short value; if (data_length == ACR_SIZEOF_SHORT) { acr_get_short(byte_order, 1, data, &value); return (double) value; } else { return 0.0; } } /* ARGSUSED */ static double get_long(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { Acr_Long value; if (data_length == ACR_SIZEOF_LONG) { acr_get_long(byte_order, 1, data, &value); return (double) value; } else { return 0.0; } } /* ARGSUSED */ static double get_float(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { Acr_Float value; if (data_length == ACR_SIZEOF_FLOAT) { acr_get_float(byte_order, 1, data, &value); return (double) value; } else { return 0.0; } } /* ARGSUSED */ static double get_double(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { Acr_Double value; if (data_length == ACR_SIZEOF_DOUBLE) { acr_get_double(byte_order, 1, data, &value); return (double) value; } else { return 0.0; } } /* ARGSUSED */ static double guess_numeric_type(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { switch (data_length) { case ACR_SIZEOF_SHORT: return get_short(vr_entry, byte_order, data, data_length); break; case ACR_SIZEOF_LONG: return get_long(vr_entry, byte_order, data, data_length); break; default: return string_to_numeric(vr_entry, byte_order, data, data_length); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : return_empty_string return_the_string numeric_to_string @INPUT : vr_entry - pointer to VR table entry byte_order - ACR_BIG_ENDIAN or ACR_LITTLE_ENDIAN data - a pointer to the actual data data_length - number of bytes in the data @OUTPUT : (none) @RETURNS : String equivalent of data @DESCRIPTION: Routines to convert values from a DICOM form to a string. If temporary space is needed, an internal buffer is used. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ #define LINE_LENGTH 256 static char *internal_string_buffer = NULL; static int length_of_internal_string = 0; static void extend_internal_buffer(int length) { if (length+1 > length_of_internal_string) { length_of_internal_string = length+1; if (internal_string_buffer == NULL) internal_string_buffer = MALLOC((size_t) length_of_internal_string); else internal_string_buffer = REALLOC(internal_string_buffer, (size_t) length_of_internal_string); } } /* ARGSUSED */ static char *return_empty_string(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { extend_internal_buffer(LINE_LENGTH); internal_string_buffer[0] = '\0'; return internal_string_buffer; } /* ARGSUSED */ static char *return_the_string(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { return (char *) data; } /* ARGSUSED */ static char *numeric_to_string(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { extend_internal_buffer(LINE_LENGTH); (void) sprintf(internal_string_buffer, "%.6g", vr_entry->convert_to_numeric(vr_entry, byte_order, data, data_length)); return internal_string_buffer; } minc-2.2.00/conversion/Acr_nema/acr_test.c0000644000265600003100000000436412027132657015315 00000000000000#include #include #include #define GLOBAL_ELEMENT_DEFINITION #include GLOBAL_ELEMENT(ACR_Recognition_code, 0x0, 0x10, LO); GLOBAL_ELEMENT(Shadow_Recognition_code, 0x1, 0x10, LO); GLOBAL_ELEMENT(Shadow_Command_code, 0x1, 0x18, US); int main(int argc, char *argv[]) /* ARGSUSED */ { Acr_File *afpin, *afpout; Acr_Message message; Acr_Status status; Acr_Element element; char *error_type, *error_string; afpin=acr_file_initialize(stdin, 0, acr_stdio_read); (void) acr_test_byte_order(afpin); acr_set_io_watchpoint(afpin, 102382L); #if 0 afpout=acr_file_initialize(stdout, 0, acr_stdio_write); #else afpout=acr_initialize_dicom_output(stdout, 0, acr_stdio_write); #endif error_type = "reading"; while ((status=acr_input_message(afpin, &message)) == ACR_OK) { #if 0 if ((status=acr_output_message(afpout, message)) != ACR_OK) { #else acr_set_dicom_pres_context_id(afpout, 19); if ((status=acr_output_dicom_message(afpout, message)) != ACR_OK) { #endif error_type = "writing"; break; } element = acr_find_group_element(acr_get_message_group_list(message), ACR_Recognition_code); if (element != NULL) (void) fprintf(stderr, "ACR-NEMA recognition code: '%s'\n", acr_get_element_string(element)); element = acr_find_group_element(acr_get_message_group_list(message), Shadow_Recognition_code); if (element != NULL) (void) fprintf(stderr, "Shadow recognition code: '%s'\n", acr_get_element_string(element)); element = acr_find_group_element(acr_get_message_group_list(message), Shadow_Command_code); if (element != NULL) (void) fprintf(stderr, "Shadow command code: 0x%x\n", (int) acr_get_element_short(element)); } error_string = acr_status_string(status); (void) fprintf(stderr, "Terminated while %s: %s\n", error_type, error_string); /* Free the afp */ acr_file_free(afpin); #if 0 acr_file_free(afpout); #else acr_close_dicom_file(afpout); #endif exit(EXIT_SUCCESS); } minc-2.2.00/conversion/Acr_nema/copy_acr_nema.c0000644000265600003100000001454212027132657016307 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : cat_acr_nema.c @DESCRIPTION: Program to read in an ACR-NEMA file and then dump it out. This can fix a buggy file. @METHOD : @GLOBALS : @CREATED : November 9, 2000 (Peter Neelin) @MODIFIED : * $Log: copy_acr_nema.c,v $ * Revision 6.6 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.5 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.4 2001/11/08 14:17:05 neelin * Added acr_test_dicom_file to allow reading of DICOM part 10 format * files. This function also calls acr_test_byte_order to set up the stream * properly and can be used as a direct replacement for that function. * This set of changes does NOT include the ability to write part 10 files. * * Revision 6.3 2000/11/09 17:00:03 neelin * Minor lint fix. * * Revision 6.2 2000/11/09 16:57:23 neelin * Fixed bug in writing to stdout. * * Revision 6.1 2000/11/09 15:56:49 neelin * Added new program copy_acr_nema to read in acr-nema file, ignoring errors, * and then write it out again. This will fix any errors in group lengths, * etc. * @COPYRIGHT : Copyright 2000 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #define UNKNOWN_VR_ENCODING ((Acr_VR_encoding_type) -1) int main(int argc, char *argv[]) { char *pname; char *infile = NULL; char *outfile = NULL; int ignore_errors = TRUE; Acr_byte_order byte_order = ACR_UNKNOWN_ENDIAN; Acr_VR_encoding_type vr_encoding = UNKNOWN_VR_ENCODING; FILE *fp; Acr_File *afp; Acr_Group group_list, cur_group; Acr_Status status, tmpstatus, outstatus; char *status_string; int iarg, argcounter; char *arg; char *usage = "Usage: %s [-h] [-b] [-l] [-e] \n"; /* Check arguments */ pname = argv[0]; argcounter = 0; for (iarg=1; iarg < argc; iarg++) { arg = argv[iarg]; if ((arg[0] == '-') && (arg[1] != '\0')) { if (arg[2] != '\0') { (void) fprintf(stderr, "Unrecognized option %s\n", arg); exit(EXIT_FAILURE); } switch (arg[1]) { case 'h': (void) fprintf(stderr, "Options:\n"); (void) fprintf(stderr, " -h:\tPrint this message\n"); (void) fprintf(stderr, " -b:\tAssume big-endian data\n"); (void) fprintf(stderr, " -l:\tAssume little-endian data\n"); (void) fprintf(stderr, " -e:\tAssume explicit VR encoding\n\n"); (void) fprintf(stderr, usage, pname); exit(EXIT_FAILURE); break; case 'l': byte_order = ACR_LITTLE_ENDIAN; break; case 'b': byte_order = ACR_BIG_ENDIAN; break; case 'e': vr_encoding = ACR_EXPLICIT_VR; break; default: (void) fprintf(stderr, "Unrecognized option %s\n", arg); exit(EXIT_FAILURE); } } else { switch (argcounter) { case 0: infile = arg; break; case 1: outfile = arg; break; default: (void) fprintf(stderr, usage, pname); exit(EXIT_FAILURE); } argcounter++; } } /* Open input file */ if ((infile != NULL) && (strcmp(infile, "-") != 0)) { fp = fopen(infile, "r"); if (fp == NULL) { (void) fprintf(stderr, "%s: Error opening file %s\n", pname, infile); exit(EXIT_FAILURE); } } else { fp = stdin; } /* Connect to input stream */ afp=acr_file_initialize(fp, 0, acr_stdio_read); acr_set_ignore_errors(afp, ignore_errors); (void) acr_test_dicom_file(afp); if (byte_order != ACR_UNKNOWN_ENDIAN) { acr_set_byte_order(afp, byte_order); } byte_order = acr_get_byte_order(afp); if (vr_encoding != UNKNOWN_VR_ENCODING) { acr_set_vr_encoding(afp, vr_encoding); } vr_encoding = acr_get_vr_encoding(afp); /* Read in group list */ status = acr_input_group_list(afp, &group_list, 0); /* Free the afp */ acr_file_free(afp); /* Open the output file */ if ((outfile != NULL) && (strcmp(outfile, "-") != 0)) { fp = fopen(outfile, "w"); if (fp == NULL) { (void) fprintf(stderr, "%s: Error opening output file %s\n", pname, outfile); exit(EXIT_FAILURE); } } else { fp = stdout; } /* Connect to output stream */ afp=acr_file_initialize(fp, 0, acr_stdio_write); acr_set_ignore_errors(afp, ignore_errors); acr_set_byte_order(afp, byte_order); acr_set_vr_encoding(afp, vr_encoding); /* Write out the groups */ outstatus = ACR_OK; for (cur_group=group_list; cur_group != NULL; cur_group = acr_get_group_next(cur_group)) { /* Read in the next group */ tmpstatus = acr_output_group(afp, cur_group); if (tmpstatus != ACR_OK) outstatus = tmpstatus; } /* Free the afp */ acr_file_free(afp); /* Print status information */ if ((status != ACR_END_OF_INPUT) && (status != ACR_OK)) { status_string = acr_status_string(status); (void) fprintf(stderr, "Finished with input status '%s'\n", status_string); } if (outstatus != ACR_OK) { status_string = acr_status_string(outstatus); (void) fprintf(stderr, "Finished with output status '%s'\n", status_string); } exit(EXIT_SUCCESS); } minc-2.2.00/conversion/Acr_nema/dicom_test.c0000644000265600003100000000221212027132657015631 00000000000000#include #include #include #include #if 0 #define WRITING #endif int main(int argc, char *argv[]) /* ARGSUSED */ { Acr_File *afpin; Acr_Message message; Acr_Status status; char *error_type, *error_string; afpin=acr_initialize_dicom_input(stdin, 0, acr_stdio_read); #ifdef WRITING afpout=acr_initialize_dicom_output(stdout, 0, acr_stdio_write); #endif error_type = "reading"; /* Loop over messages */ while ((status=acr_input_dicom_message(afpin, &message)) == ACR_OK) { /* Dump the values */ acr_dump_group_list(stderr, acr_get_message_group_list(message)); #ifdef WRITING /* Write out message */ if ((status=acr_output_dicom_message(afpout, message)) != ACR_OK) { error_type = "writing"; break; } #endif acr_delete_message(message); } error_string = acr_status_string(status); (void) fprintf(stderr, "Terminated while %s: %s\n", error_type, error_string); /* Free the afp */ acr_close_dicom_file(afpin); #ifdef WRITING acr_close_dicom_file(afpout); #endif exit(EXIT_SUCCESS); } minc-2.2.00/conversion/Acr_nema/dump_acr_nema.c0000644000265600003100000002300212027132657016271 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dump_acr_nema.c @DESCRIPTION: Program to dump the contents of an acr-nema file. @METHOD : @GLOBALS : @CREATED : November 24, 1993 (Peter Neelin) @MODIFIED : * $Log: dump_acr_nema.c,v $ * Revision 6.8 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.7 2005/03/11 22:19:59 bert * add '-t' option to parse files which contain lists of field names with corresponding group and element id's. * * Revision 6.6 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.5 2001/11/08 14:17:05 neelin * Added acr_test_dicom_file to allow reading of DICOM part 10 format * files. This function also calls acr_test_byte_order to set up the stream * properly and can be used as a direct replacement for that function. * This set of changes does NOT include the ability to write part 10 files. * * Revision 6.4 2000/05/01 17:54:45 neelin * Fixed handling of test for byte order. * * Revision 6.3 2000/05/01 13:59:55 neelin * Added -e option to allow reading data streams with explicit VR. * * Revision 6.2 2000/04/28 15:02:01 neelin * Added more general argument processing (but not with ParseArgv). * Added support for ignoring non-fatal protocol errors. * Added support for user-specified byte-order. * * Revision 6.1 1999/10/29 17:51:51 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.1 1997/07/10 17:14:38 neelin * Added more status codes and function to return status string. * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.1 1995/02/06 14:12:55 neelin * Added argument to specify maximum group id to dump. * * Revision 2.0 94/09/28 10:36:09 neelin * Release of minc version 0.2 * * Revision 1.6 94/09/28 10:35:53 neelin * Pre-release * * Revision 1.5 94/05/18 08:48:05 neelin * Changed some ACR_OTHER_ERROR's to ACR_ABNORMAL_END_OF_OUTPUT. * * Revision 1.4 94/04/07 10:04:58 neelin * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs * to that or ACR_OTHER_ERROR. * Added #ifdef lint to DEFINE_ELEMENT. * * Revision 1.3 93/11/25 10:35:33 neelin * Added byte-order test and file free. * * Revision 1.2 93/11/24 12:05:00 neelin * Write output to stdout instead of stderr. * * Revision 1.1 93/11/24 11:25:01 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #define N_NAME 31 struct table_element { struct table_element *next; unsigned short el_id; char name[N_NAME+1]; }; struct table_group { struct table_group *next; struct table_element *list; unsigned short grp_id; }; struct table_group *_head; char *get_name(unsigned short grp_id, unsigned short el_id) { struct table_group *tg_ptr; struct table_element *te_ptr; for (tg_ptr = _head; tg_ptr; tg_ptr = tg_ptr->next) { if (tg_ptr->grp_id == grp_id) { for (te_ptr = tg_ptr->list; te_ptr; te_ptr = te_ptr->next) { if (te_ptr->el_id == el_id) { return (te_ptr->name); } } } } return (NULL); } void parse_table(char *filename) { FILE *fp; char line[1024]; char name[1024]; unsigned int el_id; /* Must be int for sscanf */ unsigned int grp_id; /* Must be int for sscanf */ char vr[1024]; struct table_element *te_ptr; struct table_group *tg_ptr; fp = fopen(filename, "r"); if (fp == NULL) { return; } while (fgets(line, sizeof(line), fp)) { if (!isalnum(line[0])) { continue; /* Ignore */ } if (sscanf(line, "%s %x %x %s\n", name, &grp_id, &el_id, vr) != 4) { continue; } for (tg_ptr = _head; tg_ptr; tg_ptr = tg_ptr->next) { if (tg_ptr->grp_id == grp_id) { break; } } if (tg_ptr == NULL) { tg_ptr = malloc(sizeof(struct table_group)); tg_ptr->next = _head; _head = tg_ptr; tg_ptr->list = NULL; tg_ptr->grp_id = (unsigned short) grp_id; } te_ptr = malloc(sizeof(struct table_element)); te_ptr->el_id = (unsigned short) el_id; te_ptr->next = tg_ptr->list; tg_ptr->list = te_ptr; strncpy(te_ptr->name, name, N_NAME); } fclose(fp); } #define UNKNOWN_VR_ENCODING ((Acr_VR_encoding_type) -1) int main(int argc, char *argv[]) { char *pname; char *file = NULL; char *maxidstr = NULL; int ignore_errors = FALSE; Acr_byte_order byte_order = ACR_UNKNOWN_ENDIAN; Acr_VR_encoding_type vr_encoding = UNKNOWN_VR_ENCODING; FILE *fp; Acr_File *afp; Acr_Group group_list; Acr_Status status; char *status_string; int maxid; char *ptr; int iarg, argcounter; char *arg; char *usage = "Usage: %s [-h] [-i] [-b] [-l] [-e] [-t ] [ []]\n"; /* Check arguments */ pname = argv[0]; argcounter = 0; for (iarg=1; iarg < argc; iarg++) { arg = argv[iarg]; if ((arg[0] == '-') && (arg[1] != '\0')) { if (arg[2] != '\0') { (void) fprintf(stderr, "Unrecognized option %s\n", arg); exit(EXIT_FAILURE); } switch (arg[1]) { case 't': if (iarg < argc - 1) { parse_table(argv[++iarg]); _acr_name_proc = get_name; break; } /* Fall through */ case 'h': (void) fprintf(stderr, "Options:\n"); (void) fprintf(stderr, " -h:\tPrint this message\n"); (void) fprintf(stderr, " -t
:\tUse table to decode element names\n"); (void) fprintf(stderr, " -i:\tIgnore protocol errors\n"); (void) fprintf(stderr, " -b:\tAssume big-endian data\n"); (void) fprintf(stderr, " -l:\tAssume little-endian data\n"); (void) fprintf(stderr, " -e:\tAssume explicit VR encoding\n\n"); (void) fprintf(stderr, usage, pname); exit(EXIT_FAILURE); break; case 'i': ignore_errors = TRUE; break; case 'l': byte_order = ACR_LITTLE_ENDIAN; break; case 'b': byte_order = ACR_BIG_ENDIAN; break; case 'e': vr_encoding = ACR_EXPLICIT_VR; break; default: (void) fprintf(stderr, "Unrecognized option %s\n", arg); exit(EXIT_FAILURE); } } else { switch (argcounter) { case 0: file = arg; break; case 1: maxidstr = arg; break; default: (void) fprintf(stderr, usage, pname); exit(EXIT_FAILURE); } argcounter++; } } /* Open input file */ if ((file != NULL) && (strcmp(file, "-") != 0)) { fp = fopen(file, "r"); if (fp == NULL) { (void) fprintf(stderr, "%s: Error opening file %s\n", pname, file); exit(EXIT_FAILURE); } } else { fp = stdin; } /* Look for max group id */ if (maxidstr != NULL) { maxid = strtol(maxidstr, &ptr, 0); if (ptr == maxidstr) { (void) fprintf(stderr, "%s: Error in max group id (%s)\n", pname, maxidstr); exit(EXIT_FAILURE); } } else { maxid = 0; } /* Connect to input stream */ afp=acr_file_initialize(fp, 0, acr_stdio_read); acr_set_ignore_errors(afp, ignore_errors); (void) acr_test_dicom_file(afp); if (byte_order != ACR_UNKNOWN_ENDIAN) { acr_set_byte_order(afp, byte_order); } if (vr_encoding != UNKNOWN_VR_ENCODING) { acr_set_vr_encoding(afp, vr_encoding); } /* Read in group list */ status = acr_input_group_list(afp, &group_list, maxid); /* Free the afp */ acr_file_free(afp); /* Dump the values */ acr_dump_group_list(stdout, group_list); /* Print status information */ if ((status != ACR_END_OF_INPUT) && (status != ACR_OK)) { status_string = acr_status_string(status); (void) fprintf(stderr, "Finished with status '%s'\n", status_string); } exit(EXIT_SUCCESS); } minc-2.2.00/conversion/Acr_nema/extract_acr_nema.c0000644000265600003100000001617312027132660017003 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : extract_acr_nema.c @DESCRIPTION: Program to extract an element from an acr-nema file. @METHOD : @GLOBALS : @CREATED : November 24, 1993 (Peter Neelin) @MODIFIED : * $Log: extract_acr_nema.c,v $ * Revision 6.7 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.6 2004/10/29 13:08:41 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.5 2001/11/08 14:17:05 neelin * Added acr_test_dicom_file to allow reading of DICOM part 10 format * files. This function also calls acr_test_byte_order to set up the stream * properly and can be used as a direct replacement for that function. * This set of changes does NOT include the ability to write part 10 files. * * Revision 6.4 2000/05/01 17:54:45 neelin * Fixed handling of test for byte order. * * Revision 6.3 2000/05/01 13:59:55 neelin * Added -e option to allow reading data streams with explicit VR. * * Revision 6.2 2000/04/28 15:02:01 neelin * Added more general argument processing (but not with ParseArgv). * Added support for ignoring non-fatal protocol errors. * Added support for user-specified byte-order. * * Revision 6.1 1999/10/29 17:51:52 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:12 neelin * Release of minc version 0.2 * * Revision 1.4 94/09/28 10:35:54 neelin * Pre-release * * Revision 1.3 94/03/14 16:13:04 neelin * Changed name in header. * * Revision 1.2 93/11/25 10:36:05 neelin * Added byte-order test and file free. * * Revision 1.1 93/11/24 11:25:23 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #define UNKNOWN_VR_ENCODING ((Acr_VR_encoding_type) -1) int main(int argc, char *argv[]) { char *pname; char *filename = NULL; char *grpstr = NULL; char *elemstr = NULL; int ignore_errors = FALSE; Acr_byte_order byte_order = ACR_UNKNOWN_ENDIAN; Acr_VR_encoding_type vr_encoding = UNKNOWN_VR_ENCODING; FILE *fp; Acr_File *afp; Acr_Group group_list; Acr_Element element; long element_length; char *ptr; Acr_Element_Id element_id; int iarg, argcounter; char *arg; char *usage = "Usage: %s [-h] [-i] [-b] [-l] [-e] [] \n"; /* Check arguments */ pname = argv[0]; argcounter = 0; for (iarg=1; iarg < argc; iarg++) { arg = argv[iarg]; if ((arg[0] == '-') && (arg[1] != '\0')) { if (arg[2] != '\0') { (void) fprintf(stderr, "Unrecognized option %s\n", arg); exit(EXIT_FAILURE); } switch (arg[1]) { case 'h': (void) fprintf(stderr, "Options:\n"); (void) fprintf(stderr, " -h:\tPrint this message\n"); (void) fprintf(stderr, " -i:\tIgnore protocol errors\n"); (void) fprintf(stderr, " -b:\tAssume big-endian data\n"); (void) fprintf(stderr, " -l:\tAssume little-endian data\n"); (void) fprintf(stderr, " -e:\tAssume explicit VR encoding\n\n"); (void) fprintf(stderr, usage, pname); exit(EXIT_FAILURE); break; case 'i': ignore_errors = TRUE; break; case 'l': byte_order = ACR_LITTLE_ENDIAN; break; case 'b': byte_order = ACR_BIG_ENDIAN; break; case 'e': vr_encoding = ACR_EXPLICIT_VR; break; default: (void) fprintf(stderr, "Unrecognized option %s\n", arg); exit(EXIT_FAILURE); } } else { switch (argcounter) { case 0: grpstr = arg; break; case 1: elemstr = arg; break; case 2: filename = grpstr; grpstr = elemstr; elemstr = arg; break; default: (void) fprintf(stderr, usage, pname); exit(EXIT_FAILURE); } argcounter++; } } /* Get element id (group and element) */ if ((grpstr == NULL) || (elemstr == NULL)) { (void) fprintf(stderr, usage, pname); exit(EXIT_FAILURE); } element_id = MALLOC(sizeof(*element_id)); element_id->group_id = strtol(grpstr, &ptr, 0); if (ptr == grpstr) { (void) fprintf(stderr, "%s: Error in group id (%s)\n", pname, grpstr); exit(EXIT_FAILURE); } element_id->element_id = strtol(elemstr, &ptr, 0); if (ptr == elemstr) { (void) fprintf(stderr, "%s: Error in element id (%s)\n", pname, elemstr); exit(EXIT_FAILURE); } /* Open input file */ if ((filename != NULL) && (strcmp(filename,"-") != 0)) { fp = fopen(filename, "r"); if (fp == NULL) { (void) fprintf(stderr, "%s: Error opening file %s\n", pname, filename); exit(EXIT_FAILURE); } } else { fp = stdin; } /* Connect to input stream */ afp=acr_file_initialize(fp, 0, acr_stdio_read); acr_set_ignore_errors(afp, ignore_errors); (void) acr_test_dicom_file(afp); if (byte_order != ACR_UNKNOWN_ENDIAN) { acr_set_byte_order(afp, byte_order); } if (vr_encoding != UNKNOWN_VR_ENCODING) { acr_set_vr_encoding(afp, vr_encoding); } /* Read in group list up to group */ (void) acr_input_group_list(afp, &group_list, element_id->group_id); /* Free the afp */ acr_file_free(afp); /* Look for element */ element = acr_find_group_element(group_list, element_id); /* Print out value of element */ if (element != NULL) { element_length = acr_get_element_length(element); if (element_length > 0) { (void) fwrite(acr_get_element_data(element), sizeof(char), (size_t) element_length, stdout); } } exit(EXIT_SUCCESS); } minc-2.2.00/conversion/Acr_nema/read_acr_nema.c0000644000265600003100000001252512027132660016241 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : read_acr_nema.c @DESCRIPTION: Program to read an image from an acr-nema file and write it on stdout. @METHOD : @GLOBALS : @CREATED : March 14, 1994 (Peter Neelin) @MODIFIED : * $Log: read_acr_nema.c,v $ * Revision 6.4 2011-02-17 06:41:51 rotor * * Fixed a HDF5 error output bug in testing code * * Revision 6.3 2004/10/29 13:08:42 rotor * * rewrote Makefile with no dependency on a minc distribution * * removed all references to the abominable minc_def.h * * I should autoconf this really, but this is old code that * is now replaced by Jon Harlaps PERL version.. * * Revision 6.2 2001/11/08 14:17:06 neelin * Added acr_test_dicom_file to allow reading of DICOM part 10 format * files. This function also calls acr_test_byte_order to set up the stream * properly and can be used as a direct replacement for that function. * This set of changes does NOT include the ability to write part 10 files. * * Revision 6.1 1999/10/29 17:51:54 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:23:59 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:00 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:23 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/21 20:21:09 neelin * Updated the library to handle dicom messages. * * Revision 3.0 1995/05/15 19:32:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:19 neelin * Release of minc version 0.2 * * Revision 1.3 94/09/28 10:35:55 neelin * Pre-release * * Revision 1.2 94/04/07 10:05:08 neelin * Added status ACR_ABNORMAL_END_OF_INPUT and changed some ACR_PROTOCOL_ERRORs * to that or ACR_OTHER_ERROR. * Added #ifdef lint to DEFINE_ELEMENT. * * Revision 1.1 94/03/14 16:02:49 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include /* Define some constants */ #define ACR_IMAGE_EID 0x10 #define ACR_IMAGE_GID 0x7fe0 /* Define element id's */ DEFINE_ELEMENT(static, ACR_rows , 0x0028, 0x0010, US); DEFINE_ELEMENT(static, ACR_columns , 0x0028, 0x0011, US); DEFINE_ELEMENT(static, ACR_bits_allocated, 0x0028, 0x0100, US); DEFINE_ELEMENT(static, ACR_image_location, 0x0028, 0x0200, US); int main(int argc, char *argv[]) { char *pname, *filename; FILE *fp; Acr_File *afp; Acr_Group group_list; Acr_Element element; Acr_Element_Id element_id; unsigned short *image; int nrows, ncols, bits_alloc; /* Check arguments */ pname = argv[0]; if ((argc > 2) || (argc < 1)) { (void) fprintf(stderr, "Usage: %s []\n", pname); exit(EXIT_FAILURE); } /* Get file name */ if (argc == 2) filename = argv[1]; else filename = NULL; /* Open input file */ if (filename != NULL) { fp = fopen(filename, "r"); if (fp == NULL) { (void) fprintf(stderr, "%s: Error opening file %s\n", pname, filename); exit(EXIT_FAILURE); } } else { fp = stdin; } /* Connect to input stream */ afp=acr_file_initialize(fp, 0, acr_stdio_read); (void) acr_test_dicom_file(afp); /* Read in group list up to group */ (void) acr_input_group_list(afp, &group_list, 0); /* Free the afp */ acr_file_free(afp); /* Get image size and location */ nrows = acr_find_short(group_list, ACR_rows, 0); ncols = acr_find_short(group_list, ACR_columns, 0); bits_alloc = acr_find_short(group_list, ACR_bits_allocated, 0); if ((nrows <= 0) || (ncols <= 0)) { (void) fprintf(stderr, "%s: Invalid imaged size %d x %d\n", pname, nrows, ncols); exit(EXIT_FAILURE); } if (bits_alloc != 16) { (void) fprintf(stderr, "%s: Pixels not stored as short ints\n", pname); exit(EXIT_FAILURE); } element_id = MALLOC(sizeof(*element_id)); element_id->element_id = ACR_IMAGE_EID; element_id->group_id = acr_find_short(group_list, ACR_image_location, ACR_IMAGE_GID); /* Look for image and print it out */ image = (unsigned short *) MALLOC(nrows*ncols*sizeof(*image)); element = acr_find_group_element(group_list, element_id); if (element != NULL) { if (acr_get_element_short_array(element, (long) nrows*ncols, image) != nrows*ncols) { (void) fprintf(stderr, "Incorrect image size\n"); } (void) fwrite(image, sizeof(*image), (size_t) nrows*ncols, stdout); } FREE(element_id); FREE(image); exit(EXIT_SUCCESS); } minc-2.2.00/conversion/Acr_nema/dicom.txt0000644000265600003100000011601512027132657015176 00000000000000// Group 8 Specific_Character_Set 0x0008 0x0005 CS Image_Type 0x0008 0x0008 CS Instance_Creation_Date 0x0008 0x0012 DA Instance_Creation_Time 0x0008 0x0013 TM Instance_Creator_UID 0x0008 0x0014 UI SOP_Class_UID 0x0008 0x0016 UI SOP_Instance_UID 0x0008 0x0018 UI Related_General_SOP_Class_UID 0x0008 0x001A UI Original_Specialized_SOP_Class_UID 0x0008 0x001B UI Study_Date 0x0008 0x0020 DA Series_Date 0x0008 0x0021 DA Acquisition_Date 0x0008 0x0022 DA Content_Date 0x0008 0x0023 DA Overlay_Date 0x0008 0x0024 DA Curve_Date 0x0008 0x0025 DA Acquisition_Datetime 0x0008 0x002A DT Study_Time 0x0008 0x0030 TM Series_Time 0x0008 0x0031 TM Acquisition_Time 0x0008 0x0032 TM Content_Time 0x0008 0x0033 TM Overlay_Time 0x0008 0x0034 TM Curve_Time 0x0008 0x0035 TM Data_Set_Type 0x0008 0x0040 RET Data_Set_Subtype 0x0008 0x0041 RET Nuclear_Medicine_Series_Type 0x0008 0x0042 CS Accession_Number 0x0008 0x0050 SH Query/Retrieve_Level 0x0008 0x0052 CS Retrieve_AE_Title 0x0008 0x0054 AE Instance_Availability 0x0008 0x0056 CS Failed_SOP_Instance_UID_List 0x0008 0x0058 UI Modality 0x0008 0x0060 CS Modalities_in_Study 0x0008 0x0061 CS SOP_Classes_in_Study 0x0008 0x0062 UI Conversion_Type 0x0008 0x0064 CS Presentation_Intent_Type 0x0008 0x0068 CS Manufacturer 0x0008 0x0070 LO Institution_Name 0x0008 0x0080 LO Institution_Address 0x0008 0x0081 ST Institution_Code_Sequence 0x0008 0x0082 SQ Referring_Physician's_Name 0x0008 0x0090 PN Referring_Physician's_Address 0x0008 0x0092 ST Referring_Physician's_Telephone_Numbers 0x0008 0x0094 SH Referring_Physician_Identificiation_Sequence 0x0008 0x0096 SQ Code_Value 0x0008 0x0100 SH Coding_Scheme_Designator 0x0008 0x0102 SH Coding_Scheme_Version 0x0008 0x0103 SH Code_Meaning 0x0008 0x0104 LO Mapping_Resource 0x0008 0x0105 CS Context_Group_Version 0x0008 0x0106 DT Context_Group_Local_Version 0x0008 0x0107 DT // Some omitted fields Timezone_Offset_From_UTC 0x0008 0x0201 SH // Some fields omitted here... Network_ID 0x0008 0x1000 RET Station_Name 0x0008 0x1010 SH Study_Description 0x0008 0x1030 LO Procedure_Code_Sequence 0x0008 0x1032 SQ Series_Description 0x0008 0x103E LO Institutional_Department_Name 0x0008 0x1040 LO Physician(s)_of_Record 0x0008 0x1048 PN Physician(s)_of_Record_Identification_Sequence 0x0008 0x1049 SQ Performing_Physician's_Name 0x0008 0x1050 PN Performing_Physician_Idntification_Sequence 0x0008 0x1052 SQ Name_of_Physician(s)_Reading_Study 0x0008 0x1060 PN Physician(s)_Reading_Study_Identification_Sequence 0x0008 0x1062 SQ Operator's_Name 0x0008 0x1070 PN Operator_Identification_Sequence 0x0008 0x1072 SQ Admitting_Diagnoses_Description 0x0008 0x1080 LO Admitting_Diagnoses_Code_Sequence 0x0008 0x1084 SQ Manufacturer's_Model_Name 0x0008 0x1090 LO Referenced_Results_Sequence 0x0008 0x1100 SQ Referenced_Study_Sequence 0x0008 0x1110 SQ Referenced_Performed_Procedure_Step_Sequence 0x0008 0x1111 SQ Referenced_Series_Sequence 0x0008 0x1115 SQ Referenced_Patient_Sequence 0x0008 0x1120 SQ Referenced_Visit_Sequence 0x0008 0x1125 SQ Referenced_Overlay_Sequence 0x0008 0x1130 SQ Referenced_Waveform_Sequence 0x0008 0x113A SQ Referenced_Image_Sequence 0x0008 0x1140 SQ Referenced_Curve_Sequence 0x0008 0x1145 SQ Referenced_Instance_Sequence 0x0008 0x114A SQ Referenced_SOP_Class_UID 0x0008 0x1150 UI Referenced_SOP_Instance_UID 0x0008 0x1155 UI SOP_Classes_Supported 0x0008 0x115A UI Referenced_Frame_Number 0x0008 0x1160 IS Transaction_UID 0x0008 0x1195 UI Failure_Reason 0x0008 0x1197 US Failed_SOP_Sequence 0x0008 0x1198 SQ Referenced_SOP_Sequence 0x0008 0x1199 SQ Source_Image_Sequence 0x0008 0x2112 SQ Anatomic_Region_Sequence 0x0008 0x2218 SQ Frame_Type 0x0008 0x9007 CS Referenced_Image_Evidence_Sequence 0x0008 0x9092 SQ Referenced_Raw_Data_Sequence 0x0008 0x9121 SQ Creator-Version_UID 0x0008 0x9123 UI Derivation_Image_Sequence 0x0008 0x9124 SQ Source_Image_Evidence_Sequence 0x0008 0x9154 SQ Pixel_Presentation 0x0008 0x9205 CS Volumetric_Properties 0x0008 0x9206 CS Volume_Based_Calculation_Technique 0x0008 0x9207 CS Complex_Image_Component 0x0008 0x9208 CS Acquisition_Contrast 0x0008 0x9209 CS Derivation_Code_Sequence 0x0008 0x9215 SQ Referenced_Grayscale_Presentation_State_Sequence 0x0008 0x9237 SQ // More stuff omitted.. // Group 10 Patient's_Name 0x0010 0x0010 PN Patient_ID 0x0010 0x0020 LO Issuer_of_Patient_ID 0x0010 0x0021 LO Patient's_Birth_Date 0x0010 0x0030 DA Patient's_Birth_Time 0x0010 0x0032 TM Patient's_Sex 0x0010 0x0040 CS Patient's_Insurance_Plan_Code_Sequence 0x0010 0x0050 SQ Patient's_Primary_Language_Code_Sequence 0x0010 0x0101 SQ Patient's_Primary_Language_Code_Modifier_Sequence 0x0010 0x0102 SQ Other_Patient_IDs 0x0010 0x1000 LO Other_Patient_Names 0x0010 0x1001 PN Patient's_Birth_Name 0x0010 0x1005 PN Patient's_Age 0x0010 0x1010 AS Patient's_Size 0x0010 0x1020 DS Patient's_Weight 0x0010 0x1030 DS Patient's_Address 0x0010 0x1040 LO Insurance_Plan_Identification 0x0010 0x1050 RET Patient's_Mother's_Birth_Name 0x0010 0x1060 PN Military_Rank 0x0010 0x1080 LO Branch_of_Service 0x0010 0x1081 LO Medical_Record_Locator 0x0010 0x1090 LO Medical_Alerts 0x0010 0x2000 LO Contrast_Allergies 0x0010 0x2110 LO Country_of_Residence 0x0010 0x2150 LO Region_of_Residence 0x0010 0x2152 LO Patient's_Telephone_Numbers 0x0010 0x2154 SH Ethnic_Group 0x0010 0x2160 SH Occupation 0x0010 0x2180 SH Smoking_Status 0x0010 0x21A0 CS Additional_Patient_History 0x0010 0x21B0 LT Pregnancy_Status 0x0010 0x21C0 US Last_Menstrual_Date 0x0010 0x21D0 DA Patient's_Religious_Preference 0x0010 0x21F0 LO Patient_Comments 0x0010 0x4000 LT // Group 12 (clinical trial) Clinical_Trial_Sponsor_Name 0x0012 0x0010 LO Clinical_Trial_Protocol_ID 0x0012 0x0020 LO Clinical_Trial_Protocol_Name 0x0012 0x0021 LO Clinical_Trial_Site_ID 0x0012 0x0030 LO Clinical_Trial_Site_Name 0x0012 0x0031 LO Clinical_Trial_Subject_ID 0x0012 0x0040 LO Clinical_Trial_Subject_Reading_ID 0x0012 0x0042 LO Clinical_Trial_Time_Point_ID 0x0012 0x0050 LO Clinical_Trial_Time_Point_Description 0x0012 0x0051 ST Clinical_Trial_Coordinating_Center_Name 0x0012 0x0060 LO // Group 18 Contrast/Bolus_Agent 0x0018 0x0010 LO Contrast/Bolus_Agent_Sequence 0x0018 0x0012 SQ Contrast/Bolus_Agent_Administration_Route_Sequence 0x0018 0x0014 SQ Body_Part_Examined 0x0018 0x0015 CS Scanning_Sequence 0x0018 0x0020 CS Sequence_Variant 0x0018 0x0021 CS Scan_Options 0x0018 0x0022 CS MR_Acquisition_Type 0x0018 0x0023 CS Sequence_Name 0x0018 0x0024 SH Angio_Flag 0x0018 0x0025 CS Intervention_Drug_Information_Sequence 0x0018 0x0026 SQ Intervention_Drug_Stop_Time 0x0018 0x0027 TM Intervention_Drug_Dose 0x0018 0x0028 DS Intervention_Drug_Sequence 0x0018 0x0029 SQ Additional_Drug_Sequence 0x0018 0x002A SQ Radionuclide 0x0018 0x0030 LO Radiopharmaceutical 0x0018 0x0031 LO Energy_Window_Centerline 0x0018 0x0032 DS Energy_Window_Total_Width 0x0018 0x0033 DS Intervention_Drug_Name 0x0018 0x0034 LO Intervention_Drug_Start_Time 0x0018 0x0035 TM Intervention_Sequence 0x0018 0x0036 SQ Therapy_Type 0x0018 0x0037 CS Intervention_Status 0x0018 0x0038 CS Therapy_Description 0x0018 0x0039 CS Intervention_Description 0x0018 0x003A ST Cine_Rate 0x0018 0x0040 IS Slice_Thickness 0x0018 0x0050 DS KVP 0x0018 0x0060 DS Counts_Accumulated 0x0018 0x0070 IS Acquisition_Termination_Condition 0x0018 0x0071 CS Effective_Duration 0x0018 0x0072 DS Acquisition_Start_Condition 0x0018 0x0073 CS Acquisition_Start_Condition_Data 0x0018 0x0074 IS Acquisition_Termination_Condition_Data 0x0018 0x0075 IS Repetition_Time 0x0018 0x0080 DS Echo_Time 0x0018 0x0081 DS Inversion_Time 0x0018 0x0082 DS Number_of_Averages 0x0018 0x0083 DS Imaging_Frequency 0x0018 0x0084 DS Imaged_Nucleus 0x0018 0x0085 SH Echo_Number(s) 0x0018 0x0086 IS Magnetic_Field_Strength 0x0018 0x0087 DS Spacing_Between_Slices 0x0018 0x0088 DS Number_of_Phase_Encoding_Steps 0x0018 0x0089 IS Data_Collection_Diameter 0x0018 0x0090 DS Echo_Train_Length 0x0018 0x0091 IS Percent_Sampling 0x0018 0x0093 DS Percent_Phase_Field_of_View 0x0018 0x0094 DS Pixel_Bandwidth 0x0018 0x0095 DS Device_Serial_Number 0x0018 0x1000 LO Plate_ID 0x0018 0x1004 LO Secondary_Capture_Device_ID 0x0018 0x1010 LO Hardcopy_Creation_Device_ID 0x0018 0x1011 LO Date_of_Secondary_Capture 0x0018 0x1012 DA Time_of_Secondary_Capture 0x0018 0x1014 TM Secondary_Capture_Device_Manufacturer 0x0018 0x1016 LO Hardcopy_Device_Manufacturer 0x0018 0x1017 LO Secondary_Capture_Device_Manufacturer's_Model_name 0x0018 0x1018 LO Secondary_Capture_Device_Software_Version(s) 0x0018 0x1019 LO Hardcopy_Device_Software_Version 0x0018 0x101A LO Hardcopy_Device_Manufacturer's_Model_Name 0x0018 0x101B LO Software_Version 0x0018 0x1020 LO Video_Image_Format_Acquired 0x0018 0x1022 SH Digital_Image_Format_Acquired 0x0018 0x1022 LO Protocol_Name 0x0018 0x1030 LO Contrast/Bolus_Route 0x0018 0x1040 LO Contrast/Bolus_Volume 0x0018 0x1041 DS Contrast/Bolus_Start_Time 0x0018 0x1042 TM Contrast/Bolus_Stop_Time 0x0018 0x1043 TM Contrast/Bolus_Total_Dose 0x0018 0x1044 DS Syringe_Counts 0x0018 0x1045 IS Contrast_Flow_Rate 0x0018 0x1046 DS Contrast_Flow_Duration 0x0018 0x1047 DS Contrast/Bolus_Ingredient 0x0018 0x1048 CS Contrast/Bolus_Ingredient_Concentration 0x0018 0x1049 DS Spatial_Resolution 0x0018 0x1050 DS Trigger_Time 0x0018 0x1060 DS Trigger_Source_or_Type 0x0018 0x1061 LO Nominal_Interval 0x0018 0x1062 IS Frame_Time 0x0018 0x1063 DS Framing_Type 0x0018 0x1064 LO Frame_Time_Vector 0x0018 0x1065 DS Frame_Delay 0x0018 0x1066 DS Image_Trigger_Delay 0x0018 0x1067 DS Multiplex_Group_Time_Offset 0x0018 0x1068 DS Trigger_Time_Offset 0x0018 0x1069 DS Synchronization_Trigger 0x0018 0x106A CS Synchronization_Channel 0x0018 0x106C US Trigger_Sample_Position 0x0018 0x106E UL Radiopharmaceutical_Route 0x0018 0x1070 LO Radiopharmaceutical_Volume 0x0018 0x1071 DS Radiopharmaceutical_Start_Time 0x0018 0x1072 TM Radiopharmaceutical_Stop_Time 0x0018 0x1073 TM Radionuclide_Total_Dose 0x0018 0x1074 DS Radionuclide_Half_Life 0x0018 0x1075 DS Radionuclide_Positron_Fraction 0x0018 0x1076 DS Radiopharmaceutical_Specific_Activity 0x0018 0x1077 DS Beat_Rejection_Flag 0x0018 0x1080 CS Low_R-R_Value 0x0018 0x1081 IS High_R-R_Value 0x0018 0x1082 IS Intervals_Acquired 0x0018 0x1083 IS Intervals_Rejected 0x0018 0x1084 IS PVC_Rejection 0x0018 0x1085 LO Skip_Beats 0x0018 0x1086 IS Heart_Rate 0x0018 0x1088 IS Cardiac_Number_of_Images 0x0018 0x1090 IS // ... Reconstruction_Diameter 0x0018 0x1100 DS Distance_Source_to_Detector 0x0018 0x1110 DS Distance_Source_to_Patient 0x0018 0x1111 DS Estimated_Radiographic_Magnification_Factor 0x0018 0x1114 DS Gantry/Detector_Tilt 0x0018 0x1120 DS Gantry/Detector_Slew 0x0018 0x1121 DS Table_Height 0x0018 0x1130 DS Table_Traverse 0x0018 0x1131 DS Table_Motion 0x0018 0x1134 CS Table_Vertical_Increment 0x0018 0x1135 DS Table_Lateral_Increment 0x0018 0x1136 DS Table_Longitudinal_Increment 0x0018 0x1137 DS Table_Angle 0x0018 0x1138 DS Table_Type 0x0018 0x113A CS Rotation_Direction 0x0018 0x1140 CS Angular_Position 0x0018 0x1141 DS Radial_Position 0x0018 0x1142 DS Scan_Arc 0x0018 0x1143 DS Angular_Step 0x0018 0x1144 DS Center_of_Rotation_Offset 0x0018 0x1145 DS // ... Collimator/Grid_Name 0x0018 0x1180 SH Collimator_Type 0x0018 0x1181 CS // ... Date_of_Last_Calibration 0x0018 0x1200 DA Time_of_Last_Calibration 0x0018 0x1201 TM Convolution_Kernel 0x0018 0x1210 SH Upper/Lower_Pixel_Values 0x0018 0x1240 RET Actual_Frame_Duration 0x0018 0x1242 IS Count_Rate 0x0018 0x1243 IS Preferred_Playback_Sequencing 0x0018 0x1244 US Receive_Coil_Name 0x0018 0x1250 SH Transmit_Coil_Name 0x0018 0x1251 SH Plate_Type 0x0018 0x1260 SH Phosphor_Type 0x0018 0x1261 LO Scan_Velocity 0x0018 0x1300 DS Whole_Body_Technique 0x0018 0x1301 CS Scan_Length 0x0018 0x1302 IS Acquisition_Matrix 0x0018 0x1310 US In-plane_Phase_Encoding_Direction 0x0018 0x1312 CS Flip_Angle 0x0018 0x1314 DS Variable_Flip_Angle_Flag 0x0018 0x1315 CS SAR 0x0018 0x1316 DS dB/dt 0x0018 0x1318 DS Acquisition_Device_Processing_Description 0x0018 0x1400 LO Acquisition_Device_Processing_Code 0x0018 0x1401 LO Cassette_Orientation 0x0018 0x1402 CS Cassette_Size 0x0018 0x1403 CS Exposures_on_Plate 0x0018 0x1404 US //... Patient_Position 0x0018 0x5100 CS //... Content_Qualification 0x0018 0x9004 CS Pulse_Sequence_Name 0x0018 0x9005 SH MR_Imaging_Modifier_Sequence 0x0018 0x9006 SQ Echo_Pulse_Sequence 0x0018 0x9008 CS Inversion_Recovery 0x0018 0x9009 CS Flow_Compensation 0x0018 0x9010 CS Multiple_Spin_Echo 0x0018 0x9011 CS Multi-planar_Excitation 0x0018 0x9012 CS Phase_Contrast 0x0018 0x9014 CS Time_of_Flight_Contrast 0x0018 0x9015 CS Spoiling 0x0018 0x9016 CS Steady_State_Pulse_Sequence 0x0018 0x9017 CS Echo_Planar_Pulse_Sequence 0x0018 0x9018 CS Tag_Angle_First_Axis 0x0018 0x9019 FD Magnetization_Transfer 0x0018 0x9020 CS T2_Preparation 0x0018 0x9021 CS Blood_Signal_Nulling 0x0018 0x9022 CS Saturation_Recovery 0x0018 0x9024 CS Spectrally_Selected_Suppression 0x0018 0x9025 CS Spectrally_Selected_Excitation 0x0018 0x9026 CS Spatial_Pre-saturation 0x0018 0x9027 CS Tagging 0x0018 0x9028 CS Oversampled_Phase 0x0018 0x9029 CS Tag_Spacing_First_Dimension 0x0018 0x9030 FD Geometry_of_k-Space_Traversal 0x0018 0x9032 CS Segmented_k-Space_Traversal 0x0018 0x9033 CS Rectilinear_Phase_Encode_Reordering 0x0018 0x9034 CS Tag_Thickness 0x0018 0x9035 FD Partial_Fourier_Direction 0x0018 0x9036 CS Cardiac_Synchronization_Technique 0x0018 0x9037 CS Receive_Coil_Manufacturer_Name 0x0018 0x9041 LO MR_Receive_Coil_Sequence 0x0018 0x9042 SQ Receive_Coil_Type 0x0018 0x9043 CS Quadrature_Receive_Coil 0x0018 0x9044 CS Multi-Coil_Definition_Sequence 0x0018 0x9045 SQ Multi-Coil_Configuration 0x0018 0x9046 LO Multi-Coil_Element_Name 0x0018 0x9047 SH Multi-Coil_Element_Used 0x0018 0x9048 CS MR_Transmit_Coil_Sequence 0x0018 0x9049 SQ Transmit_Coil_Manufacturer_Name 0x0018 0x9050 LO Transmit_Coil_Type 0x0018 0x9051 CS Spectral_Width 0x0018 0x9052 FD Chemical_Shift_Reference 0x0018 0x9053 FD Volume_Localization_Technique 0x0018 0x9054 CS MR_Acquisition_Frequency_Encoding_Steps 0x0018 0x9058 US De-coupling 0x0018 0x9059 CS De-coupled_Nucleus 0x0018 0x9060 CS De-coupling_Frequency 0x0018 0x9061 FD De-coupling_Method 0x0018 0x9062 CS De-coupling_Chemical_Shift_Reference 0x0018 0x9063 FD k-space_Filtering 0x0018 0x9064 CS Time_Domain_Filtering 0x0018 0x9065 CS Number_of_Zero_fills 0x0018 0x9066 US Baseline_Correction 0x0018 0x9067 CS Parallel_Reduction_Factor_In-plane 0x0018 0x9069 FD Cardiac_R-R_Interval_Specified 0x0018 0x9070 FD Acquisition_Duration 0x0018 0x9073 FD Frame_Acquisition_Datetime 0x0018 0x9074 DT Diffusion_Directionality 0x0018 0x9075 CS Diffusion_Gradient_Direction_Sequence 0x0018 0x9076 SQ Parallel_Acquisition 0x0018 0x9077 CS Parallel_Acquisition_Technique 0x0018 0x9078 CS Inversion_Times 0x0018 0x9079 FD Metabolite_Map_Description 0x0018 0x9080 ST Partial_Fourier 0x0018 0x9081 CS Effective_Echo_Time 0x0018 0x9082 FD Metabolite_Map_Code_Sequence 0x0018 0x9083 SQ Chemical_Shift_Sequence 0x0018 0x9084 SQ Cardiac_Signal_Source 0x0018 0x9085 CS Diffusion_b-value 0x0018 0x9087 FD Diffusion_Gradient_Orientation 0x0018 0x9089 FD Velocity_Encoding_Direction 0x0018 0x9090 FD Velocity_Encoding_Minimum_Value 0x0018 0x9091 FD Number_of_k-Space_Trajectories 0x0018 0x9093 US Coverage_of_k-Space 0x0018 0x9094 CS Spectroscopy_Acquisition_Phase_Rows 0x0018 0x9095 UL Transmitter_Frequency 0x0018 0x9098 FD Resonant_Nucleus 0x0018 0x9100 CS Frequency_Correction 0x0018 0x9101 CS MR_Spectroscopy_FOV/Geometry_Sequence 0x0018 0x9103 SQ Slab_Thickness 0x0018 0x9104 FD Slab_Orientation 0x0018 0x9105 FD Mid_Slab_Position 0x0018 0x9106 FD MR_Spatial_Saturation_Sequence 0x0018 0x9107 SQ MR_Timing_and_Related_Parameters_Sequence 0x0018 0x9112 SQ MR_Echo_Sequence 0x0018 0x9114 SQ MR_Modifier_Sequence 0x0018 0x9115 SQ MR_Diffusion_Sequence 0x0018 0x9117 SQ Cardiac_Trigger_Sequence 0x0018 0x9118 SQ MR_Averages_Sequence 0x0018 0x9119 SQ MR_FOV/Geometry_Sequence 0x0018 0x9125 SQ Volume_Localization_Sequence 0x0018 0x9126 SQ Spectroscopy_Acquisition_Data_Columns 0x0018 0x9127 UL Diffusion_Anisotropy_Type 0x0018 0x9147 CS Frame_Reference_Datetime 0x0018 0x9151 DT MR_Metabolite_Map_Sequence 0x0018 0x9152 SQ Parallel_Reduction_Factor_Out-of-plane 0x0018 0x9155 FD Spectroscopy_Acquisition_Out-of-plane_Phase_Steps 0x0018 0x9159 UL Bulk_Motion_Status 0x0018 0x9166 CS Parallel_Reduction_Factor_Second_In-plane 0x0018 0x9168 FD Cardiac_Beat_Rejection_Technique 0x0018 0x9169 CS Respiratory_Motion_Compensation_Technique 0x0018 0x9170 CS Respiratory_Signal_Source 0x0018 0x9171 CS Bulk_Motion_Compensation_Technique 0x0018 0x9172 CS Bulk_Motion_Signal_Source 0x0018 0x9173 CS Applicable_Safety_Standard_Agency 0x0018 0x9174 CS Applicable_Safety_Standard_Description 0x0018 0x9175 LO Operating_Mode_Sequence 0x0018 0x9176 SQ Operating_Mode_Type 0x0018 0x9177 CS Operating_Mode 0x0018 0x9178 CS Specific_Absorption_Rate_Definition 0x0018 0x9179 CS Gradient_Output_Type 0x0018 0x9180 CS Specific_Absorption_Rate_Value 0x0018 0x9181 FD Gradient_Output 0x0018 0x9182 FD Flow_Compensation_Direction 0x0018 0x9183 CS Tagging_Delay 0x0018 0x9184 FD MR_Velocity_Encoding_Sequence 0x0018 0x9197 SQ First_Order_Phase_Correction 0x0018 0x9198 CS Water_Referenced_Phase_Correction 0x0018 0x9199 CS MR_Spectroscopy_Acquisition_Type 0x0018 0x9200 CS Respiratory_Cycle_Position 0x0018 0x9214 CS Velocity_Encoding_Maximum_Value 0x0018 0x9217 FD Tag_Spacing_Second_Dimension 0x0018 0x9218 FD Tag_Angle_Second_Axis 0x0018 0x9219 SS Frame_Acquisition_Duration 0x0018 0x9220 FD MR_Image_Frame_Type_Sequence 0x0018 0x9226 SQ MR_Spectroscopy_Frame_Type_Sequence 0x0018 0x9227 SQ MR_Acq_Phase_Encoding_Steps_in-plane 0x0018 0x9231 US MR_Acq_Phase_Encoding_Steps_out-of-plane 0x0018 0x9232 US Spectroscopy_Acquistion_Phase_Columns 0x0018 0x9234 UL Cardiac_Cycle_Position 0x0018 0x9236 CS Specific_Absorption_Rate_Sequence 0x0018 0x9239 SQ Chemical_Shifts_Minimum_Integration_Limit 0x0018 0x9295 FD Chemical_Shifts_Maximum_Integration_Limit 0x0018 0x9296 FD RF_Echo_Train_Length 0x0018 0x9240 US Gradient_Echo_Train_Length 0x0018 0x9241 US //... Contrast/Bolus_Agent_Number 0x0018 0x9337 US Contrast/Bolus_Ingredient_Code_Sequence 0x0018 0x9338 SQ Contrast/Bolus_Usage_Sequence 0x0018 0x9341 SQ Contrast/Bolus_Agent_Administered 0x0018 0x9342 CS Contrast/Bolus_Agent_Detected 0x0018 0x9343 CS Contrast/Bolus_Agent_Phase 0x0018 0x9344 CS //... // Group 20 (study) Study_Instance_UID 0x0020 0x000D UI Series_Instance_UID 0x0020 0x000E UI Study_ID 0x0020 0x0010 SH Series_Number 0x0020 0x0011 IS Acquisition_Number 0x0020 0x0012 IS Instance_Number 0x0020 0x0013 IS Isotope_Number 0x0020 0x0014 IS Phase_Number 0x0020 0x0015 IS Interval_Number 0x0020 0x0016 IS Time_Slot_Number 0x0020 0x0017 IS Angle_Number 0x0020 0x0018 IS Item_Number 0x0020 0x0019 IS Patient_Orientation 0x0020 0x0020 CS Overlay_Number 0x0020 0x0022 IS Curve_Number 0x0020 0x0024 IS Lookup_Table_Number 0x0020 0x0026 IS Image_Position 0x0020 0x0030 RET Image_Position_(Patient) 0x0020 0x0032 DS Image_Orientation 0x0020 0x0035 RET Image_Orientation_(Patient) 0x0020 0x0037 DS Location 0x0020 0x0050 RET Frame_of_Reference_UID 0x0020 0x0052 UI Laterality 0x0020 0x0060 CS Image_Laterality 0x0020 0x0062 CS Image_Geometry_Type 0x0020 0x0070 RET Masking_Image 0x0020 0x0080 RET Temporal_Position_Identifier 0x0020 0x0100 IS Number_of_Temporal_Positions 0x0020 0x0105 IS Temporal_Resolution 0x0020 0x0110 DS Synchronization_Frame_of_Refernence_UID 0x0020 0x0200 UI Series_in_Study 0x0020 0x1000 IS Acquisitions_in_Series 0x0020 0x1001 RET Images_in_Acquisition 0x0020 0x1002 IS Acquisitions_in_Study 0x0020 0x1004 IS Reference 0x0020 0x1020 RET Position_Reference_Indicator 0x0020 0x1040 LO Slice_Location 0x0020 0x1041 DS Other_Study_Numbers 0x0020 0x1070 IS Number_of_Patient_Related_Studies 0x0020 0x1200 IS Number_of_Patient_Related_Series 0x0020 0x1202 IS Number_of_Patient_Related_Instances 0x0020 0x1204 IS Number_of_Study_Related_Series 0x0020 0x1206 IS Number_of_Study_Related_Instances 0x0020 0x1208 IS //... Image_Comments 0x0020 0x4000 LT //... Stack_ID 0x0020 0x9056 SH In-Stack_Position_Number 0x0020 0x9057 UL Frame_Anatomy_Sequence 0x0020 0x9071 SQ Frame_Laterality 0x0020 0x9072 CS Frame_Content_Sequence 0x0020 0x9111 SQ Plane_Position_Sequence 0x0020 0x9113 SQ Plane_Orientation_Sequence 0x0020 0x9116 SQ Temporal_Position_Index 0x0020 0x9128 UL Trigger_Delay_Time 0x0020 0x9153 FD Frame_Acquisition_Number 0x0020 0x9156 US Dimension_Index_Values 0x0020 0x9157 UL Frame_Comments 0x0020 0x9158 LT Concatenation_UID 0x0020 0x9161 UI In-concatenation_Number 0x0020 0x9162 US In-concatenation_Total_Number 0x0020 0x9163 US Dimension_Organization_UID 0x0020 0x9164 UI Dimension_Index_Pointer 0x0020 0x9165 AT Functional_Group_Pointer 0x0020 0x9167 AT Dimension_Index_Private_Creator 0x0020 0x9213 LO Dimension_Organization_Sequence 0x0020 0x9221 SQ Dimension_Index_Sequence 0x0020 0x9222 SQ //... //Group 28 Samples_per_Pixel 0x0028 0x0002 US Samples_per_Pixel_Used 0x0028 0x0003 US Photometric_Interpretation 0x0028 0x0004 CS Image_Dimensions 0x0028 0x0005 RET Planar_Configuration 0x0028 0x0006 US Number_of_Frames 0x0028 0x0008 IS Frame_Increment_Pointer 0x0028 0x0009 AT Frame_Dimension_Pointer 0x0028 0x000A AT Rows 0x0028 0x0010 US Columns 0x0028 0x0011 US Planes 0x0028 0x0012 US Ultrasound_Color_Data_Present 0x0028 0x0014 US Pixel_Spacing 0x0028 0x0030 DS Zoom_Factor 0x0028 0x0031 DS Zoom_Center 0x0028 0x0032 DS Pixel_Aspect_Ratio 0x0028 0x0034 IS Image_Format 0x0028 0x0040 RET Manipulated_Image 0x0028 0x0050 RET Corrected_Image 0x0028 0x0051 CS Compression_Code 0x0028 0x0060 RET Bits_Allocated 0x0028 0x0100 US Bits_Stored 0x0028 0x0101 US High_Bit 0x0028 0x0102 US Pixel_Representation 0x0028 0x0103 US Smallest_Valid_Pixel_Value 0x0028 0x0104 RET Largest_Valid_Pixel_Value 0x0028 0x0105 RET Smallest_Image_Pixel_Value 0x0028 0x0106 US Largest_Image_Pixel_Value 0x0028 0x0107 US Smallest_Pixel_Value_in_Series 0x0028 0x0108 US Largest_Pixel_Value_in_Series 0x0028 0x0109 US Smallest_Pixel_Value_in_Plane 0x0028 0x0110 US Largest_Pixel_Value_in_Plane 0x0028 0x0111 US Pixel_Padding_Value 0x0028 0x0120 US Image_Location 0x0028 0x0200 RET Quality_Control_Image 0x0028 0x0300 CS Burned_In_Annotation 0x0028 0x0301 CS Pixel_Intensity_Relationship 0x0028 0x1040 CS Pixel_Intensity_Relationship_Sign 0x0028 0x1041 SS Window_Center 0x0028 0x1050 DS Window_Width 0x0028 0x1051 DS Rescale_Intercept 0x0028 0x1052 DS Rescale_Slope 0x0028 0x1053 DS Rescale_Type 0x0028 0x1054 LO Window_Center&Width_Explanation 0x0028 0x1055 LO Gray_Scale 0x0028 0x1080 RET Recommended_Viewing_Mode 0x0028 0x1090 CS Gray_Lookup_Table_Descriptor 0x0028 0x1100 RET Red_Palette_Lookup_Table_Descriptor 0x0028 0x1101 US Green_Palette_Lookup_Table_Descriptor 0x0028 0x1102 US Blue_Palette_Lookup_Table_Descriptor 0x0028 0x1103 US Palette_Color_Lookup_Table_UID 0x0028 0x1199 UI Gray_Lookup_Table_Data 0x0028 0x1200 RET Red_Palette_Color_Lookup_Table_Data 0x0028 0x1201 OW Green_Palette_Color_Lookup_Table_Data 0x0028 0x1202 OW Blue_Palette_Color_Lookup_Table_Data 0x0028 0x1203 OW //... Lossy_Image_Compression 0x0028 0x2110 CS Lossy_Image_Compression_Ratio 0x0028 0x2112 DS Lossy_Image_Compression_Method 0x0028 0x2114 CS LUT_Explanation 0x0028 0x3003 LO Pixel_Measures_Sequence 0x0028 0x9110 SQ Frame_VOI_LUT_Sequence 0x0028 0x9132 SQ Pixel_Value_Transformation_Sequence 0x0028 0x9145 SQ //... //Group 32 Requested_Procedure_Description 0x0032 0x1060 LO Study_Comments 0x0032 0x4000 LT //Group 40 Performed_Procedure_Step_Start_Date 0x0040 0x0244 DA Performed_Procedure_Step_Start_Time 0x0040 0x0245 TM Performed_Procedure_Step_ID 0x0040 0x0253 SH Acquisition_Context_Sequence 0x0040 0x0555 SQ Measurement_Units_Code_Sequence 0x0040 0x08EA SQ Real_World_Value_Mapping_Sequence 0x0040 0x9096 SQ LUT_Label 0x0040 0x9210 SH Real_World_Value_Last_Value_Mapped 0x0040 0x9211 US Real_World_Value_LUT_Data 0x0040 0x9212 FD Real_World_Value_First_Value_Mapped 0x0040 0x9216 US Real_World_Value_Intercept 0x0040 0x9224 FD Real_World_Value_Slope 0x0040 0x9225 FD Purpose_of_Reference_Code_Sequence 0x0040 0xA170 SQ //Group 54 Energy_Window_Vector 0x0054 0x0010 US Number_of_Energy_Windows 0x0054 0x0011 US Energy_Window_Information_Sequence 0x0054 0x0012 SQ Energy_Window_Range_Sequence 0x0054 0x0013 SQ Energy_Window_Lower_Limit 0x0054 0x0014 DS Energy_Window_Upper_Limit 0x0054 0x0015 DS Radiopharmaceutical_Information_Sequence 0x0054 0x0016 SQ Residual_Syringe_Counts 0x0054 0x0017 IS Energy_Window_Name 0x0054 0x0018 SH Detector_Vector 0x0054 0x0020 US Number_of_Detectors 0x0054 0x0021 US Detector_Information_Sequence 0x0054 0x0022 SQ Phase_Vector 0x0054 0x0030 US Number_of_Phases 0x0054 0x0031 US Phase_Information_Sequence 0x0054 0x0032 SQ Number_of_Frames_in_Phase 0x0054 0x0033 US Phase_Delay 0x0054 0x0036 IS Pause_Between_Frames 0x0054 0x0038 IS Phase_Description 0x0054 0x0039 CS Rotation_Vector 0x0054 0x0050 US Number_of_Rotations 0x0054 0x0051 US Rotation_Information_Sequence 0x0054 0x0052 SQ Number_of_Frames_in_Rotation 0x0054 0x0053 US R-R_Interval_Vector 0x0054 0x0060 US Number_of_R-R_Intervals 0x0054 0x0061 US Gated_Information_Sequence 0x0054 0x0062 SQ Data_Information_Sequence 0x0054 0x0063 SQ Time_Slot_Vector 0x0054 0x0070 US Number_of_Time_Slots 0x0054 0x0071 US Time_Slot_Information_Sequence 0x0054 0x0072 SQ Time_Slot_Time 0x0054 0x0073 DS Slice_Vector 0x0054 0x0080 US Number_of_Slices 0x0054 0x0081 US Angular_View_Vector 0x0054 0x0090 US Time_Slice_Vector 0x0054 0x0100 US Number_of_Time_Slices 0x0054 0x0101 US Start_Angle 0x0054 0x0200 DS Type_of_Detector_Motion 0x0054 0x0202 CS Trigger_Vector 0x0054 0x0210 IS Number_of_Triggers_in_Phase 0x0054 0x0211 US View_Code_Sequence 0x0054 0x0220 SQ View_Modifier_Code_Sequence 0x0054 0x0222 SQ Radionuclide_Code_Sequence 0x0054 0x0300 SQ Administration_Route_Code_Sequence 0x0054 0x0302 SQ Radiopharmaceutical_Code_Sequence 0x0054 0x0304 SQ Calibration_Data_Sequence 0x0054 0x0306 SQ Energy_Window_Number 0x0054 0x0308 US Image_ID 0x0054 0x0400 SH Patient_Orientation_Code_Sequence 0x0054 0x0410 SQ Patient_Orientation_Modifier_Code_Sequence 0x0054 0x0412 SQ Patient_Gantry_Relationship_Code_Sequence 0x0054 0x0414 SQ Slice_Progression_Direction 0x0054 0x0500 CS Series_Type 0x0054 0x1000 CS Units 0x0054 0x1001 CS Counts_Source 0x0054 0x1002 CS Reprojection_Method 0x0054 0x1004 CS Randoms_Correction_Method 0x0054 0x1100 CS Attenuation_Correction_Method 0x0054 0x1101 LO Decay_Correction 0x0054 0x1102 CS Reconstruction_Method 0x0054 0x1103 LO Detector_Lines_of_Response_Used 0x0054 0x1104 LO Scatter_Correction_Method 0x0054 0x1105 LO Axial_Acceptance 0x0054 0x1200 DS Axial_Mash 0x0054 0x1201 IS Transverse_Mash 0x0054 0x1202 IS Detector_Element_Size 0x0054 0x1203 DS Concidence_Window_Width 0x0054 0x1210 DS Secondary_Counts_Type 0x0054 0x1220 CS Frame_Reference_Time 0x0054 0x1300 DS Primary_(Prompts)_Counts_Accumulated 0x0054 0x1310 IS Secondary_Counts_Accumulated 0x0054 0x1311 IS Slice_Sensitivity_Factor 0x0054 0x1320 DS Decay_Factor 0x0054 0x1321 DS Dose_Calibration_Factor 0x0054 0x1322 DS Scatter_Fraction_Factor 0x0054 0x1323 DS Dead_Time_Factor 0x0054 0x1324 DS Image_Index 0x0054 0x1330 US Counts_Included 0x0054 0x1400 CS Dead_Time_Correction_Flag 0x0054 0x1401 CS //Group 0x2050 Presentation_LUT_Sequence 0x2050 0x0010 SQ Presentation_LUT_Shape 0x2050 0x0020 CS Referenced_Presentation_LUT_Sequence 0x2050 0x0500 SQ //Group 0x5200 Shared_Functional_Groups_Sequence 0x5200 0x9229 SQ Per_Frame_Functional_Groups_Sequence 0x5200 0x9230 SQ //Group 0x7fe0 Pixel_Data 0x7fe0 0x0010 OW minc-2.2.00/conversion/dcm2mnc/0000755000265600003100000000000012030114723013220 500000000000000minc-2.2.00/conversion/dcm2mnc/acr_element_defs.h0000644000265600003100000002266112027132660016605 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_element_defs.h @DESCRIPTION: Element definitions for DICOM @METHOD : @GLOBALS : @CALLS : @CREATED : January 28, 1997 (Peter Neelin) @MODIFIED : @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Define standard UID's */ #define FAVORITE_ABSTRACT_SYNTAX ACR_MR_IMAGE_STORAGE_UID #define ACR_MR_IMAGE_STORAGE_UID "1.2.840.10008.5.1.4.1.1.4" #define ACR_EXPLICIT_VR_BIG_END_UID "1.2.840.10008.1.2.2" #define ACR_EXPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2.1" #define ACR_IMPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2" #define ACR_APPLICATION_CONTEXT_UID "1.2.840.10008.3.1.1.1" #define ACR_IMAGE_GID 0x7fe0 #define ACR_IMAGE_EID 0x0010 /* Define acr-nema constants */ #define ACR_MODALITY_MR "MR" #define ACR_MODALITY_PT "PT" /* Defined values for pixel representation (0028,0103) */ #define ACR_PIXEL_REP_UNSIGNED 0 /* Unsigned magnitude */ #define ACR_PIXEL_REP_SIGNED 1 /* 2's complement signed */ /* Element id's for DICOM */ GLOBAL_ELEMENT(ACR_Affected_SOP_class_UID , 0x0000, 0x0002, UI); GLOBAL_ELEMENT(ACR_Command , 0x0000, 0x0100, US); GLOBAL_ELEMENT(ACR_Message_id , 0x0000, 0x0110, US); GLOBAL_ELEMENT(ACR_Message_id_brt , 0x0000, 0x0120, US); GLOBAL_ELEMENT(ACR_Priority , 0x0000, 0x0700, US); GLOBAL_ELEMENT(ACR_Dataset_type , 0x0000, 0x0800, US); GLOBAL_ELEMENT(ACR_Status , 0x0000, 0x0900, US); GLOBAL_ELEMENT(ACR_Affected_SOP_instance_UID , 0x0000, 0x1000, UI); GLOBAL_ELEMENT(ACR_Move_originator_AE_title , 0x0000, 0x1031, AE); GLOBAL_ELEMENT(ACR_Image_type , 0x0008, 0x0008, CS); GLOBAL_ELEMENT(ACR_SOP_Class_UID , 0x0008, 0x0016, UI); GLOBAL_ELEMENT(ACR_Study_date , 0x0008, 0x0020, DA); GLOBAL_ELEMENT(ACR_Series_date , 0x0008, 0x0021, DA); GLOBAL_ELEMENT(ACR_Acquisition_date , 0x0008, 0x0022, DA); GLOBAL_ELEMENT(ACR_Study_time , 0x0008, 0x0030, TM); GLOBAL_ELEMENT(ACR_Series_time , 0x0008, 0x0031, TM); GLOBAL_ELEMENT(ACR_Acquisition_time , 0x0008, 0x0032, TM); GLOBAL_ELEMENT(ACR_Image_time , 0x0008, 0x0033, TM); GLOBAL_ELEMENT(ACR_Modality , 0x0008, 0x0060, CS); GLOBAL_ELEMENT(ACR_Manufacturer , 0x0008, 0x0070, LO); GLOBAL_ELEMENT(ACR_Institution_id , 0x0008, 0x0080, LO); GLOBAL_ELEMENT(ACR_Referring_physician , 0x0008, 0x0090, PN); GLOBAL_ELEMENT(ACR_Station_id , 0x0008, 0x1010, SH); GLOBAL_ELEMENT(ACR_Procedure_description , 0x0008, 0x1030, LO); GLOBAL_ELEMENT(ACR_Series_description , 0x0008, 0x103E, LO); GLOBAL_ELEMENT(ACR_Performing_physician , 0x0008, 0x1050, PN); GLOBAL_ELEMENT(ACR_Operators_name , 0x0008, 0x1070, PN); GLOBAL_ELEMENT(ACR_Manufacturer_model , 0x0008, 0x1090, LO); /* See C.8.12.3.1.6 for full list of possible values, but for DTI * images this field _should_ equal "DIFFUSION" */ GLOBAL_ELEMENT(ACR_Acquisition_contrast , 0x0008, 0x9209, CS); GLOBAL_ELEMENT(ACR_Patient_name , 0x0010, 0x0010, PN); GLOBAL_ELEMENT(ACR_Patient_identification, 0x0010, 0x0020, LO); GLOBAL_ELEMENT(ACR_Patient_birth_date , 0x0010, 0x0030, DA); GLOBAL_ELEMENT(ACR_Patient_sex , 0x0010, 0x0040, CS); GLOBAL_ELEMENT(ACR_Patient_age , 0x0010, 0x1010, AS); GLOBAL_ELEMENT(ACR_Patient_weight , 0x0010, 0x1030, DS); GLOBAL_ELEMENT(ACR_Scanning_sequence , 0x0018, 0x0020, CS); GLOBAL_ELEMENT(ACR_MR_acquisition_type , 0x0018, 0x0023, CS); GLOBAL_ELEMENT(ACR_Sequence_name , 0x0018, 0x0024, CS); GLOBAL_ELEMENT(ACR_Slice_thickness , 0x0018, 0x0050, DS); GLOBAL_ELEMENT(ACR_Repetition_time , 0x0018, 0x0080, DS); GLOBAL_ELEMENT(ACR_Echo_time , 0x0018, 0x0081, DS); GLOBAL_ELEMENT(ACR_Inversion_time , 0x0018, 0x0082, DS); GLOBAL_ELEMENT(ACR_Nr_of_averages , 0x0018, 0x0083, DS); GLOBAL_ELEMENT(ACR_Imaging_frequency , 0x0018, 0x0084, DS); GLOBAL_ELEMENT(ACR_Imaged_nucleus , 0x0018, 0x0085, SH); GLOBAL_ELEMENT(ACR_Echo_number , 0x0018, 0x0086, IS); GLOBAL_ELEMENT(ACR_Magnetic_field_strength,0x0018, 0x0087, DS); GLOBAL_ELEMENT(ACR_Spacing_between_slices, 0x0018, 0x0088, DS); GLOBAL_ELEMENT(ACR_Number_of_phase_encoding_steps, 0x0018, 0x0089, IS); GLOBAL_ELEMENT(ACR_Echo_train_length , 0x0018, 0x0091, IS); GLOBAL_ELEMENT(ACR_Percent_sampling , 0x0018, 0x0093, DS); GLOBAL_ELEMENT(ACR_Percent_phase_field_of_view, 0x0018, 0x0094, DS); GLOBAL_ELEMENT(ACR_Pixel_bandwidth , 0x0018, 0x0095, DS); GLOBAL_ELEMENT(ACR_Device_serial_number , 0x0018, 0x1000, LO); GLOBAL_ELEMENT(ACR_Software_versions , 0x0018, 0x1020, LO); GLOBAL_ELEMENT(ACR_Protocol_name , 0x0018, 0x1030, LO); GLOBAL_ELEMENT(ACR_Cardiac_number_of_images , 0x0018, 0x1090, IS); /*added ilana*/ GLOBAL_ELEMENT(ACR_Calibration_date , 0x0018, 0x1200, DA); GLOBAL_ELEMENT(ACR_Calibration_time , 0x0018, 0x1201, TM); /*added ilana*/ GLOBAL_ELEMENT(ACR_Actual_frame_duration , 0x0018, 0x1242, IS); GLOBAL_ELEMENT(ACR_Receive_coil_name , 0x0018, 0x1250, SH); GLOBAL_ELEMENT(ACR_Transmit_coil_name , 0x0018, 0x1251, SH); GLOBAL_ELEMENT(ACR_Acquisition_matrix , 0x0018, 0x1310, US); GLOBAL_ELEMENT(ACR_Phase_encoding_direction, 0x0018, 0x1312, CS); GLOBAL_ELEMENT(ACR_Flip_angle , 0x0018, 0x1314, DS); GLOBAL_ELEMENT(ACR_SAR , 0x0018, 0x1316, DS); GLOBAL_ELEMENT(ACR_Acq_comments , 0x0018, 0x4000, LT); GLOBAL_ELEMENT(ACR_Patient_position , 0x0018, 0x5100, CS); /* Supplement 49 stuff, section C.8.12.5.9 pp 94-95. */ GLOBAL_ELEMENT(ACR_Diffusion_directionality, 0x0018, 0x9075, CS); GLOBAL_ELEMENT(ACR_Diffusion_gradient_direction_seq, 0x0018, 0x9076, SQ); GLOBAL_ELEMENT(ACR_Diffusion_b_value , 0x0018, 0x9087, FD); GLOBAL_ELEMENT(ACR_Diffusion_gradient_orientation, 0x0018, 0x9089, FD); GLOBAL_ELEMENT(ACR_MR_Diffusion_seq , 0x0018, 0x9117, SQ); GLOBAL_ELEMENT(ACR_Diffusion_anisotropy_type, 0x0018, 0x9147, CS); GLOBAL_ELEMENT(ACR_B_matrix, 0x0019, 0x1027, FD); /*added by ilana, seems to exits for software >= VB*/ GLOBAL_ELEMENT(ACR_Series_instance_UID , 0x0020, 0x000E, UI); GLOBAL_ELEMENT(ACR_Study , 0x0020, 0x0010, SH); GLOBAL_ELEMENT(ACR_Series , 0x0020, 0x0011, IS); GLOBAL_ELEMENT(ACR_Acquisition , 0x0020, 0x0012, IS); GLOBAL_ELEMENT(ACR_Image , 0x0020, 0x0013, IS); GLOBAL_ELEMENT(ACR_Image_position_patient_old, 0x0020, 0x0030, DS); GLOBAL_ELEMENT(ACR_Image_position_patient, 0x0020, 0x0032, DS); GLOBAL_ELEMENT(ACR_Image_orientation_patient_old, 0x0020, 0x0035, DS); GLOBAL_ELEMENT(ACR_Image_orientation_patient, 0x0020, 0x0037, DS); GLOBAL_ELEMENT(ACR_Number_of_temporal_positions, 0x0020, 0x0105, IS); GLOBAL_ELEMENT(ACR_Acquisitions_in_series, 0x0020, 0x1001, IS); GLOBAL_ELEMENT(ACR_Images_in_acquisition, 0x0020, 0x1002, IS); GLOBAL_ELEMENT(ACR_Slice_location, 0x0020, 0x1041, DS); GLOBAL_ELEMENT(ACR_Image_comments, 0x0020, 0x4000, DS); GLOBAL_ELEMENT(ACR_Number_of_frames , 0x0028, 0x0008, IS); GLOBAL_ELEMENT(ACR_Frame_increment_ptr , 0x0028, 0x0009, AT); GLOBAL_ELEMENT(ACR_Rows , 0x0028, 0x0010, US); GLOBAL_ELEMENT(ACR_Columns , 0x0028, 0x0011, US); GLOBAL_ELEMENT(ACR_Pixel_size , 0x0028, 0x0030, DS); GLOBAL_ELEMENT(ACR_Bits_allocated , 0x0028, 0x0100, US); GLOBAL_ELEMENT(ACR_Bits_stored , 0x0028, 0x0101, US); GLOBAL_ELEMENT(ACR_High_bit , 0x0028, 0x0102, US); GLOBAL_ELEMENT(ACR_Pixel_representation , 0x0028, 0x0103, US); GLOBAL_ELEMENT(ACR_Smallest_pixel_value , 0x0028, 0x0106, US); GLOBAL_ELEMENT(ACR_Largest_pixel_value , 0x0028, 0x0107, US); GLOBAL_ELEMENT(ACR_Image_location , 0x0028, 0x0200, US); GLOBAL_ELEMENT(ACR_Window_centre , 0x0028, 0x1050, DS); GLOBAL_ELEMENT(ACR_Window_width , 0x0028, 0x1051, DS); GLOBAL_ELEMENT(ACR_Rescale_intercept , 0x0028, 0x1052, DS); GLOBAL_ELEMENT(ACR_Rescale_slope , 0x0028, 0x1053, DS); GLOBAL_ELEMENT(ACR_Detector_information_seq, 0x0054, 0x0022, SQ); GLOBAL_ELEMENT(ACR_Number_of_slices , 0x0054, 0x0081, US); GLOBAL_ELEMENT(ACR_Number_of_time_slices , 0x0054, 0x0101, US); GLOBAL_ELEMENT(ACR_Units , 0x0054, 0x1001, CS); GLOBAL_ELEMENT(ACR_Frame_reference_time , 0x0054, 0x1300, DS); GLOBAL_ELEMENT(ACR_Shared_func_groups_seq, 0x5200, 0x9229, SQ); GLOBAL_ELEMENT(ACR_Plane_orientation_seq , 0x0020, 0x9116, SQ); GLOBAL_ELEMENT(ACR_Pixel_measurement_seq , 0x0020, 0x9118, SQ); GLOBAL_ELEMENT(ACR_Perframe_func_groups_seq, 0x5200, 0x9230, SQ); GLOBAL_ELEMENT(ACR_Plane_position_seq , 0x0020, 0x9113, SQ); GLOBAL_ELEMENT(ACR_Pixel_data , ACR_IMAGE_GID, ACR_IMAGE_EID, OW); minc-2.2.00/conversion/dcm2mnc/dcm2mnc.h0000644000265600003100000002117112027132660014644 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dcm2mnc.h @DESCRIPTION: Header file that includes things needed for dicomserver. @METHOD : @GLOBALS : @CREATED : January 28, 1997 (Peter Neelin) @MODIFIED : * $Log: dcm2mnc.h,v $ * Revision 1.15 2007-05-30 15:17:34 ilana * fix so that diffusion images all written into 1 4d volume, gradient directions and bvalues are written to mincheader, some fixes for TIM diffusion images * * Revision 1.14 2005/11/11 18:42:54 bert * Latest fixes to dcm2mnc * * Revision 1.13 2005/08/26 21:25:54 bert * Latest changes ported from 1.0 branch * * Revision 1.10.2.4 2005/08/18 18:17:36 bert * Add -usecoordinates option * * Revision 1.10.2.3 2005/06/09 20:46:11 bert * Fairly major fixes to use integers for all arguments, add filename_format and dirname_format to global options, always include math.h, and defined OPTS_NO_RESCALE for testing converter without ICV * * Revision 1.10.2.2 2005/05/16 19:45:23 bert * Add config.h, sys/types.h, other config.h conditionals for float.h, int32_t and int16_t. Also fix definitions of Name and command_line in the globals structure. * * Revision 1.10.2.1 2005/05/12 21:16:47 bert * Initial checkin * * Revision 1.10 2005/04/29 23:09:36 bert * Add support for -stdin option to read file list from standard input * * Revision 1.9 2005/04/18 16:38:09 bert * Add comments and defines for both DICOM and IMA file detection * * Revision 1.8 2005/04/05 21:50:11 bert * Add comment * * Revision 1.7 2005/03/18 19:10:39 bert * Scan coordinate and location information for validity before relying on it * * Revision 1.6 2005/03/13 19:34:41 bert * Add pms_element_defs.h to the header * * Revision 1.5 2005/03/03 20:10:14 bert * Consider patient_id and patient_name when sorting into series * * Revision 1.4 2005/03/03 18:59:15 bert * Fix handling of image position so that we work with the older field (0020, 0030) as well as the new (0020, 0032) * * Revision 1.3 2005/03/02 18:23:33 bert * Added mosaic sequence and bitwise options * * Revision 1.2 2005/02/23 18:28:11 bert * Minor updates * * Revision 1.1 2005/02/17 16:38:09 bert * Initial checkin, revised DICOM to MINC converter * * Revision 1.1.1.1 2003/08/15 19:52:55 leili * Leili's dicom server for sonata * * Revision 1.5 2002/03/19 13:13:56 rhoge * initial working mosaic support - I think time is scrambled though. * * Revision 1.4 2001/12/31 18:27:21 rhoge * modifications for dicomreader processing of Numaris 4 dicom files - at * this point code compiles without warning, but does not deal with * mosaiced files. Also will probably not work at this time for Numaris * 3 .ima files. dicomserver may also not be functional... * * Revision 1.3 2000/12/14 21:17:34 rhoge * cleanup of log messages * * Revision 1.2 2000/12/14 21:15:58 rhoge * added ACQ and MEAS constants as flags for type of (non-standard) * dynamic scan looping * * Revision 1.1.1.1 2000/11/30 02:13:15 rhoge * imported sources to CVS repository on amoeba * added num_slices_nominal to Data_Object_Info * (for support of acquisition loop scans) * * Revision 6.1 1999/10/29 17:51:55 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:27 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:26 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:20 neelin * Release of minc version 0.4 * * Revision 1.2 1997/03/11 13:10:48 neelin * Working version of dicomserver. * * Revision 1.1 1997/03/04 20:56:47 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #if HAVE_SYS_TYPES_H #include #endif #include #include #include #include #include #include #include #if HAVE_FLOAT_H #include #endif #include #include #include "acr_element_defs.h" #include "spi_element_defs.h" #include "ext_element_defs.h" #include "pms_element_defs.h" /* Philips Medical Systems */ #include "gems_element_defs.h" /* GE Medical Systems */ #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif /* Constants for "standard" DICOM files (herein referred to as * CD/Export files). For more details of this, see section 7.1 "DICOM * FILE META INFORMATION" of the DICOM specification section 3.10. */ #define DICM_MAGIC_SIZE 4 #define DICM_MAGIC_OFFS 0x0080 #define DICM_MAGIC_STR "DICM" /* Constants for Siemens IMA file format detection. These are somewhat * arbitrary - I test for IMA format by looking for the manufacturer string * SIEMENS at offset 0x0060 */ #define IMA_MAGIC_SIZE 7 #define IMA_MAGIC_OFFS 0x0060 #define IMA_MAGIC_STR "SIEMENS" /* Test to see if two floating-point numbers are very close in value. */ extern int fcmp(double x, double y, double delta); #define NEARLY_EQUAL(x, y) (fcmp(x, y, 1e-6)) #if !HAVE_INT16_T typedef short int16_t; #endif #if !HAVE_INT32_T typedef int int32_t; #endif typedef char string_t[511+1]; #define STRING_T_LEN (sizeof(string_t) - 1) /* Define logging constants */ #define NO_LOGGING 0 #define LO_LOGGING 1 #define HI_LOGGING 2 /* added by rhoge for ACQ and MEAS loop handling */ typedef enum { NONE = 0 , ACQ , MEAS } Loop_Type; /* supported file types */ typedef enum { UNDEF, IMA, N3DCM, N4DCM } File_Type; /* Type for carrying around object information */ typedef struct { int file_index; /* input file index */ char *file_name; /* input file name */ double study_id; /* yyyymmdd.hhmmss */ int study_date; int study_time; int scanner_serialno; int acq_id; int rec_num; int image_type; int num_echoes; int echo_number; int num_dyn_scans; int dyn_scan_number; int global_image_number; int num_slices_nominal; int slice_number; int acq_rows; int acq_cols; int rec_rows; int rec_cols; int num_mosaic_rows; int num_mosaic_cols; int num_slices_in_file; string_t sequence_name; string_t protocol_name; string_t patient_name; string_t patient_id; double slice_location; int coord_found; } Data_Object_Info; #include "dicom_to_minc.h" #include "dicom_read.h" #include "minc_file.h" #include "progress.h" #include "siemens_to_dicom.h" #include "string_to_filename.h" typedef enum { MOSAIC_SEQ_UNKNOWN, MOSAIC_SEQ_INTERLEAVED, MOSAIC_SEQ_ASCENDING, MOSAIC_SEQ_DESCENDING } mosaic_seq_t; /* Globals */ struct globals { char *minc_history; /* Global for minc history */ char *pname; /* program name */ File_Type file_type; /* type of input files */ int Debug; /* Debug on/off */ int Anon; /* "Anonymize" the output */ int List; int useMinMax; /* TRUE if need to use pixel min/max values */ int splitEcho; /* TRUE if echos in separate files */ int splitDynScan; /* TRUE if dynamic scans in separate files */ int clobber; char * command_line; int opts; mosaic_seq_t mosaic_seq; int use_stdin; int use_filelist; /*use file with list of filenames ilana*/ char * filename_format; char * dirname_format; int prefer_coords; /* In event of slice thickness conflict, use the coordinate information rather than the slice thickness or spacing. */ }; /* Values for options flags */ #define OPTS_NO_MOSAIC 0x00000001 /* Don't parse mosaic information. */ #define OPTS_KEEP_COORD 0x00000002 /* Don't flip DICOM coordinates */ #define OPTS_NO_LOCATION 0x00000004 /* Never rely on slice location */ #define OPTS_NO_RESCALE 0x00000008 /* Do NOT rescale pixel data in any way! */ extern struct globals G; #define CHKMEM(x) \ if ((x) == NULL) \ (fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__), \ exit(-1)) minc-2.2.00/conversion/dcm2mnc/dicom_read.h0000644000265600003100000000123612027132660015407 00000000000000extern void get_dicom_image_data(Acr_Group group_list, Image_Data *image); extern void parse_dicom_groups(Acr_Group group_list, Data_Object_Info *di_ptr); extern void get_file_info(Acr_Group group_list, File_Info *file_info, General_Info *general_info); #define DICOM_POSITION_LOCAL 2 #define DICOM_POSITION_GLOBAL 1 #define DICOM_POSITION_NONE 0 extern int dicom_read_position(Acr_Group group_list, int n, double position[3]); extern int dicom_read_orientation(Acr_Group group_list, double orientation[6]); extern int dicom_read_pixel_size(Acr_Group group_list, double pixel_size[2]); extern void convert_dicom_coordinate(double coord[]); minc-2.2.00/conversion/dcm2mnc/dicom_to_minc.h0000644000265600003100000002243012027132660016123 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_to_minc.h @DESCRIPTION: Header file for dicom_to_minc.h @METHOD : @GLOBALS : @CALLS : @CREATED : January 28, 1997 (Peter Neelin) @MODIFIED : * $Log: dicom_to_minc.h,v $ * Revision 1.10 2010-11-23 23:30:50 claude * dcm2mnc: fixed seg fault bug (Claude) and added b-matrix (Ilana) * * Revision 1.9 2007-06-08 20:28:57 ilana * added several fields to mincheader (dicom elements and found in ASCONV header) * * Revision 1.8 2006/04/09 15:33:10 bert * Add flags and fields for DTI * * Revision 1.7 2005/11/04 22:25:34 bert * Change COORDINATE_EPSILON again, now set to 0.005 * * Revision 1.6 2005/10/26 23:43:55 bert * Fix COORDINATE_EPSILON at 0.0001 * * Revision 1.5 2005/07/14 19:00:30 bert * Changes ported from 1.X branch * * Revision 1.4.2.2 2005/06/20 22:00:26 bert * Simplify Image_Data structure, add is_siemens_mosaic() function declaration * * Revision 1.4.2.1 2005/05/12 21:16:47 bert * Initial checkin * * Revision 1.4 2005/04/28 17:10:22 bert * Added width information to General_Info and File_Info structures * * Revision 1.3 2005/04/20 23:14:32 bert * Remove unnecessary fields, add copy_spi_to_acr() function definition * * Revision 1.2 2005/03/02 18:25:13 bert * Add Mri_Names and Volume_Names * * Revision 1.1 2005/02/17 16:38:10 bert * Initial checkin, revised DICOM to MINC converter * * Revision 1.1.1.1 2003/08/15 19:52:55 leili * Leili's dicom server for sonata * * Revision 1.6 2002/04/26 03:27:03 rhoge * fixed MrProt problem - replaced fixed lenght char array with malloc * * Revision 1.5 2002/04/08 17:26:34 rhoge * added additional sequence info to minc header * * Revision 1.4 2002/03/27 18:57:50 rhoge * added diffusion b value * * Revision 1.3 2002/03/19 13:13:57 rhoge * initial working mosaic support - I think time is scrambled though. * * Revision 1.2 2001/12/31 18:27:21 rhoge * modifications for dicomreader processing of Numaris 4 dicom files - at * this point code compiles without warning, but does not deal with * mosaiced files. Also will probably not work at this time for Numaris * 3 .ima files. dicomserver may also not be functional... * * Revision 1.1.1.1 2000/11/30 02:13:15 rhoge * imported sources to CVS repository on amoeba * * Revision 6.1 1999/10/29 17:51:59 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:27 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:26 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:20 neelin * Release of minc version 0.4 * * Revision 1.1 1997/03/04 20:56:47 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* General constants */ #define SECONDS_PER_MINUTE 60 #define MINUTES_PER_HOUR 60 #define SECONDS_PER_HOUR (MINUTES_PER_HOUR*SECONDS_PER_MINUTE) #define HOURS_PER_DAY 24 #define SECONDS_PER_DAY (HOURS_PER_DAY*SECONDS_PER_HOUR) #define MS_PER_SECOND 1000 #define COORDINATE_EPSILON (0.005) /* bert- relaxed from 1.0e-5 */ /* Default value for ncopts */ #define NCOPTS_DEFAULT NC_VERBOSE /* MINC variable for dicom elements */ #define DICOM_ROOT_VAR "dicom_groups" /* Possible MRI dimensions */ typedef enum { SLICE = 0, ECHO, TIME, PHASE, CHEM_SHIFT, MRI_NDIMS } Mri_Index; extern const char *Mri_Names[MRI_NDIMS]; /* World dimensions */ typedef enum { XCOORD = 0, YCOORD, ZCOORD, WORLD_NDIMS } World_Index; extern const char *World_Names[WORLD_NDIMS]; /* Volume dimensions */ typedef enum { VSLICE = 0, VROW, VCOLUMN, VOL_NDIMS } Volume_Index; extern const char *Volume_Names[VOL_NDIMS]; /* Orientations */ typedef enum {TRANSVERSE = 0, SAGITTAL, CORONAL, NUM_ORIENTATIONS} Orientation; /* Structure for general info about files */ typedef struct { int initialized; double study_id; int acq_id; /* Time of scan */ int rec_num; string_t image_type_string; int nrows; int ncolumns; int default_index[MRI_NDIMS]; /* Index for dimensions with size == 1 */ int cur_size[MRI_NDIMS]; /* Size of dimension across these files */ int max_size[MRI_NDIMS]; /* Size of dimension across acquisition */ int *indices[MRI_NDIMS]; /* List of indices found for each dimension. Only allocated when size > 1 */ /* */ int search_start[MRI_NDIMS]; /* Indices into lists for starting searches */ double *coordinates[MRI_NDIMS]; /* Array indicating coordinate of each index in indices array */ double *widths[MRI_NDIMS]; /* Array indicating width of each index in indices array */ int image_index[MRI_NDIMS]; /* Mapping from MRI dim to output image dim */ World_Index slice_world; World_Index row_world; World_Index column_world; double step[WORLD_NDIMS]; double start[WORLD_NDIMS]; double dircos[WORLD_NDIMS][WORLD_NDIMS]; nc_type datatype; /* netCDF (and therefore MINC) datatype */ int is_signed; /* TRUE of 2's compliment data */ double pixel_min; double pixel_max; string_t units; double window_min; double window_max; int num_mosaic_rows; int num_mosaic_cols; int num_slices_in_file; int sub_image_rows; int sub_image_columns; struct { string_t name; string_t identification; string_t birth_date; string_t age; string_t sex; string_t reg_date; string_t reg_time; double weight; string_t position; /*added ilana*/ } patient; struct { string_t start_time; string_t modality; string_t manufacturer; string_t model; double field_value; string_t software_version; string_t serial_no; string_t calibration_date; string_t calibration_time; string_t institution; string_t station_id; string_t referring_physician; string_t performing_physician; string_t operator; string_t procedure; string_t study_id; string_t acquisition_id; } study; struct { string_t scan_seq; string_t acquisition_time; /*added by ilana*/ string_t image_time; /*added by ilana*/ string_t series_time; /*added by ilana*/ string_t protocol_name; string_t series_description; /*added by ilana*/ string_t receive_coil; string_t transmit_coil; double rep_time; double slice_thickness; double num_slices; string_t slice_order; double echo_time; double echo_train_length; /*added by ilana*/ double echo_number; double inv_time; double delay_in_TR; /*added by ilana*/ double b_value; double flip_angle; double num_avg; double num_dyn_scans; double imaging_freq; string_t imaged_nucl; double win_center; double win_width; double num_phase_enc_steps; double percent_sampling; double percent_phase_fov; double pixel_bandwidth; string_t phase_enc_dir; string_t mr_acq_type; string_t image_type; double sar; string_t comments; char *MrProt; // Siemens Numaris 4 specific short dti; /* TRUE if we think this is DTI */ } acq; Acr_Group group_list; } General_Info; /* Structure for file-specific info */ typedef struct { int valid; int bits_alloc; int bits_stored; int index[MRI_NDIMS]; double pixel_max; double pixel_min; double slice_max; double slice_min; double window_max; double window_min; double coordinate[MRI_NDIMS]; double width[MRI_NDIMS]; /* Sample width along each MRI dimension */ double b_value; /* DTI b-value, if present */ double grad_direction[WORLD_NDIMS]; /* DTI gradient direction */ double b_matrix[6]; } File_Info; /* Structure for storing the actual image data */ typedef struct { unsigned short *data; } Image_Data; /* function definitions */ extern int dicom_to_minc(int num_files, const char **file_list, const char *minc_file, int clobber, const char *file_prefix, char **output_file_name); extern Acr_Group read_std_dicom(const char *filename, int max_group); extern Acr_Group read_numa4_dicom(const char *filename, int max_group); extern int search_list(int value, const int *list_ptr, int list_length, int start_index); extern Acr_Group copy_spi_to_acr(Acr_Group group_list); extern int is_siemens_mosaic(Acr_Group group_list); minc-2.2.00/conversion/dcm2mnc/ext_element_defs.h0000644000265600003100000000425612027132660016640 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : ext_element_defs.h @DESCRIPTION: Element definitions for extra elements needed for mosaics, etc. @METHOD : @GLOBALS : @CALLS : @CREATED : December 2001 (Rick Hoge) @MODIFIED : @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Element id's for EXT */ /* bert- These appear to be completely nonstandard - I believe they were * created by Peter and Rick to facilitate communication among the various * pieces of Siemens Mosaic handling code. They do not represent any * externally defined DICOM standard and therefore they may conflict with * other manufacturer's proprietary fields. */ GLOBAL_ELEMENT(EXT_Mosaic_rows , 0x0023, 0x0001, LO); GLOBAL_ELEMENT(EXT_Mosaic_columns , 0x0023, 0x0002, LO); GLOBAL_ELEMENT(EXT_Slices_in_file , 0x0023, 0x0003, LO); GLOBAL_ELEMENT(EXT_Sub_image_rows , 0x0023, 0x0004, US); GLOBAL_ELEMENT(EXT_Sub_image_columns , 0x0023, 0x0005, US); GLOBAL_ELEMENT(EXT_MrProt_dump , 0x0023, 0x0006, LO); GLOBAL_ELEMENT(EXT_Diffusion_b_value , 0x0023, 0x0007, LO); GLOBAL_ELEMENT(EXT_Delay_in_TR , 0x0023, 0x0008, LO); /*add for fMRI scans*/ /*Can't find slice acquisition in any standard fields; using ASCONV header sSliceArray.ucMode ilana*/ /*0x1 ascending 0x2 descending 0x3 interleaved*/ GLOBAL_ELEMENT(EXT_Slice_order , 0x0023, 0x0009, LO); minc-2.2.00/conversion/dcm2mnc/minc_file.h0000644000265600003100000000106412027132660015245 00000000000000extern int create_minc_file(const char *minc_file, int clobber, General_Info *general_info, const char *file_prefix, char **output_file_name, Loop_Type loop_type); extern void setup_minc_variables(int mincid, General_Info *general_info, Loop_Type loop_type); extern void save_minc_image(int icvid, General_Info *general_info, File_Info *file_info, Image_Data *image); extern void close_minc_file(int icvid); minc-2.2.00/conversion/dcm2mnc/progress.h0000644000265600003100000000010012027132660015152 00000000000000extern void progress(long index, int end, const char *message); minc-2.2.00/conversion/dcm2mnc/siemens_to_dicom.h0000644000265600003100000000020312027132660016632 00000000000000extern Acr_Group siemens_to_dicom(const char *filename, int max_group); extern void update_coordinate_info(Acr_Group group_list); minc-2.2.00/conversion/dcm2mnc/siemens_header_defs.h0000644000265600003100000004150412027132660017277 00000000000000#ifndef _SIEMENS_HEADER_DEFS_H_ #define _SIEMENS_HEADER_DEFS_H_ 1 /* CONSTANTS */ #define N_STRING 26 #define N_AGE 4 #define N_DIAGNOSIS 40 #define N_NUCLEUS 8 #define N_MANUFACTURER 8 #define N_ORIENTATION 3 #define N_PATIENTID 12 #define N_SWVERSION 8 typedef double flt64_t; /* ACR-NEMA specific types */ /* Analogous to DICOM field (0028, 0030) */ typedef struct pixel_spacing { flt64_t row; flt64_t col; } pixel_spacing_t; /* Analogous to DICOM fields (0028, 1050) and (0028, 1051) */ typedef struct window { int32_t x; int32_t y; } window_t; /* IMA specific types */ typedef struct ima_date { int32_t year; /* Full year including century */ int32_t month; /* Month from 1(Jan) to 12(Dec) */ int32_t day; /* Day of month from 1 to 31 */ } ima_date_t; typedef struct ima_time { int32_t hour; /* Hour from 0 to 23 */ int32_t minute; /* Minute from 0 to 59 */ int32_t second; /* Second from 0 to 59 */ int32_t msec; /* Milliseconds from 0 to 999 */ } ima_time_t; typedef struct ima_vector { flt64_t x; flt64_t y; flt64_t z; } ima_vector_t; typedef enum ima_slice_order { SO_ASCENDING = 1, SO_DESCENDING = 2, SO_FREE = 3, SO_INTERLEAVED = 4, SO_NONE = 5 } ima_slice_order_t; typedef enum ima_position { PP_LEFT = 1, PP_PRONE = 2, PP_RIGHT = 3, PP_SUPINE = 4, } ima_position_t; typedef enum { RD_FEET = 1, RD_HEAD = 2 } ima_rest_direction_t; typedef enum { VD_FEET = 1, VD_HEAD = 2, VD_AtoP = 3, VD_LtoR = 4, VD_PtoA = 5, VD_RtoL = 6 } ima_view_direction_t; typedef struct { flt64_t height; flt64_t width; } ima_field_of_view_t; typedef struct { char y[N_ORIENTATION + 1]; /* up - down */ char x[N_ORIENTATION + 1]; /* left - right */ char z[N_ORIENTATION + 1]; /* back - front */ } ima_orientation_t; /* * Identifying information group 0x0008 */ struct ima_acr_0008 /* Item# FOffs SOffs */ { ima_date_t StudyDate; /* 0020 0000 */ ima_date_t AcquisitionDate; /* 0022 000C */ ima_date_t ContentDate; /* 0023 0018 */ ima_time_t StudyTime; /* 0030 0024 */ ima_time_t AcquisitionTime; /* 0032 0034 */ ima_time_t ContentTime; /* 0033 0044 */ char pad1[8]; int32_t Modality; /* 0060 005C */ char Manufacturer[N_MANUFACTURER + 1]; /* 0070 0060 */ char InstitutionName[N_STRING + 1]; /* 0080 0069 */ char PhysicianName[N_STRING + 1]; /* 0090 0084 */ char StationName[N_STRING + 1]; /* 1010 009F */ char StudyDescription[N_STRING + 1]; /* 1030 00BA */ char pad2[N_STRING + 1]; char AdmittingDiagnoses[N_DIAGNOSIS + 1]; /* 1080 00F0 */ char ModelName[N_STRING + 1]; /* 1090 0119 */ char pad3[76]; }; /* * Patient information group 0x0010 */ struct ima_acr_0010 /* Item# FOffs SOffs */ { char PatientName[N_STRING + 1]; /* 0010 0300 */ char PatientID[N_PATIENTID + 1]; /* 0020 031B */ ima_date_t PatientDOB; /* 0030 0328 */ int32_t PatientSex; /* 0040 0334 */ char PatientBirthName[N_STRING + 1]; /* 1005 0338 */ char PatientAge[N_AGE + 1]; /* 1010 0353 */ flt64_t PatientSize; /* 1020 0358 */ int32_t PatientWeight; /* 1030 0360 */ char pad1[156]; }; /* * Acquisition information group 0x0018 */ struct ima_acr_0018 { /* Item# FOffs SOffs */ char pad1[8]; /* Dummy padding */ flt64_t SliceThickness; /* 0050 0608 */ char pad2[8]; flt64_t RepetitionTime; /* 0080 0618 */ flt64_t EchoTime; /* 0081 0620 */ flt64_t InversionTime; /* 0082 0628 */ int32_t NumberOfAverages; /* 0083 0630 */ char pad3[4]; /* Dummy padding */ flt64_t ImagingFrequency; /* 0084 0638 */ char pad4[4]; /* 0085 0640 */ int32_t EchoNumber; /* 0086 0644 */ int32_t DataCollectionDiameter; /* 0090 0648 */ char SerialNumber[N_STRING + 1]; /* 1000 064C */ char SoftwareVersion[N_SWVERSION + 1]; /* 1020 0667 */ char pad5[61]; /* Dummy padding */ ima_date_t CalibrationDate; /* 1200 06B0 */ ima_time_t CalibrationTime; /* 1201 06BC */ char pad6[N_STRING + 1]; char ReceiveCoilName[N_STRING + 1]; /* 1250 06E7 */ char pad7[N_STRING + 1]; ima_position_t PatientPosition; /* 5100 0720 */ char ImagedNucleus[N_NUCLEUS + 1]; /* 0085 0724 */ char pad8[80]; /* Pad to 384 bytes */ }; /* * Relationship information group 0x0020 */ struct ima_acr_0020 { /* Item# FOffs */ int32_t StudyID; /* 0010 0C80 */ char pad1[4]; /* */ int32_t AcquisitionNumber; /* 0012 0C88 */ int32_t InstanceNumber; /* 0013 0C8C */ int32_t ImagePosition[3]; /* 0030 0C90 */ char pad2[4]; /* Dummy padding */ flt64_t ImageOrientation[6]; /* 0035 0C94 */ int32_t Location; /* 0050 0CD0 */ int32_t Laterality; /* 0060 0CD4 */ char pad3[4]; int32_t AcquisitionsInSeries; /* 1001 0CDC */ char pad4[416]; /* Pad to 512 bytes */ }; /* * Image presentation Information group 0x0028 */ struct ima_acr_0028 { /* Item# FOffs */ int16_t ImageDimension; /* 0005 1380 */ int16_t Rows; /* 0010 1382 */ int16_t Columns; /* 0011 1384 */ char pad1[2]; pixel_spacing_t PixelSpacing; /* 0030 1388 */ char pad2[8]; int16_t BitsAllocated; /* 0100 13A0 */ int16_t BitsStored; /* 0101 13A2 */ int16_t HighBit; /* 0102 13A4 */ int16_t PixelRepresentation; /* 0103 13A6 */ window_t WindowCenter; /* 1050 13A8 */ window_t WindowWidth; /* 1051 13B0 */ int32_t RescaleIntercept; /* 1052 13B8 */ int32_t RescaleSlope; /* 1053 13BC */ char pad3[192]; /* Pad to 256 bytes */ }; /***** Siemens private group structures *****/ /* * Siemens acquisition group 0x0019 */ struct ima_siemens_0019 { char pad1[20]; /* Padding */ int32_t NumberOfDataBytes; /* 1060 */ char pad2[140]; int32_t FourierLinesNominal; /* 1220 */ char pad3[4]; int32_t FourierLinesAfterZero; /* 1226 */ int32_t FirstMeasuredFourierLine; /* 1228 */ int32_t AcquisitionColumns; /* 1230 */ int32_t ReconstructionColumns; /* 1231 */ int32_t NumberOfAverages; /* 1250 */ flt64_t FlipAngle; /* 1260 */ int32_t NumberOfPrescans; /* 1270 */ char pad4[116]; /* Dummy padding */ int32_t SaturationRegions; /* 1290 */ char pad5[316]; /* Dummy padding */ flt64_t MagneticFieldStrength; /* 1412 */ char pad6[631]; /* Dummy padding */ }; /* * Siemens Relationship group 0x0021 */ struct ima_siemens_0021 { char pad1[32]; /* Dummy padding */ ima_field_of_view_t FieldOfView; /* 1120 0EA0 */ ima_view_direction_t ViewDirection; /* 1130 0EB0 */ ima_rest_direction_t RestDirection; /* 1132 0EB4 */ ima_vector_t ImagePosition; /* 1160 0EB8 */ ima_vector_t ImageNormal; /* 1161 0ED0 */ flt64_t ImageDistance; /* 1163 0EE8 */ char pad3[8]; /* Dummy padding */ ima_vector_t ImageRow; /* 116A 0EF8 */ ima_vector_t ImageColumn; /* 116B 0F10 */ ima_orientation_t OrientationSet1; /* 1170 0F28 */ ima_orientation_t OrientationSet2; /* 1171 0F34 */ char StudyName[N_STRING + 1]; /* 1180 0F40 */ int32_t StudyType; /* 1182 */ flt64_t ImageMagnificationFactor; /* 1122 */ char pad4[40]; int32_t NumberOf3DRawPartNom; /* 1330 */ int32_t NumberOf3DRawPartCur; /* 1331 */ int32_t NumberOf3DImaPart; /* 1334 */ int32_t Actual3DImaPartNumber; /* 1336 */ char pad5[4]; int32_t NumberOfSlicesNom; /* 1340 */ int32_t NumberOfSlicesCur; /* 1341 */ int32_t CurrentSliceNumber; /* 1342 */ int32_t CurrentGroupNumber; /* 1343 */ char pad7[88]; /* Dummy padding */ int32_t NumberOfEchoes; /* 1370 */ char pad9[32]; /* Dummy padding */ ima_slice_order_t SliceOrder; /* 134F */ char pad10[4]; /* Dummy padding */ flt64_t SlabThickness; /* 1339 */ char pad11[829]; /* Padding */ }; /* this is a work in progress, based on David Clunie's website */ #define PATIENT_NUMBER_SIZE 12 #define PATIENT_DATE_SIZE 11 #define PATIENT_POSITION_SIZE 11 #define IMAGE_NUMBER_SIZE 11 #define IMAGE_NUMBER_TEXT "IMAGE" #define LABEL_SIZE 5 #define DATE_OF_MEASUREMENT_SIZE 11 #define TIME_OF_MEASUREMENT_SIZE 5 #define TIME_OF_ACQUISITION_SIZE 11 #define TIME_OF_ACQUISITION_TEXT_CT "TI" #define TIME_OF_ACQUISITION_TEXT_MR "TA " #define NUMBER_OF_ACQUISITIONS_SIZE 11 #define NUMBER_OF_ACQUISITIONS_TEXT "AC" #define COMMENT_NO1_SIZE 26 #define COMMENT_NO2_SIZE 26 #define INSTALLATION_NAME_SIZE 26 #define SOFTWARE_VERSION_SIZE 11 #define MATRIX_SIZE 11 #define TYPE_OF_MEASUREMENT_SIZE 11 #define SCAN_NUMBER_SIZE 11 #define SCAN_NUMBER_TEXT "SCAN" #define REPETITION_TIME_SIZE 11 #define REPETITION_TIME_TEXT "TR" #define ECHO_TIME_SIZE 11 #define ECHO_TIME_TEXT "TE" #define GATING_AND_TRIGGER_SIZE 11 #define GATING_AND_TRIGGER_TEXT "TD" #define TUBE_CURRENT_SIZE 11 #define TUBE_CURRENT_TEXT "mA" #define TUBE_VOLTAGE_SIZE 11 #define TUBE_VOLTAGE_TEXT "kV" #define SLICE_THICKNESS_SIZE 11 #define SLICE_THICKNESS_TEXT "SL" #define SLICE_POSITION_SIZE 11 #define SLICE_POSITION_TEXT "SP" #define SLICE_ORIENTATION_NO1_SIZE 11 #define SLICE_ORIENTATION_NO2_SIZE SLICE_ORIENTATION_NO1_SIZE #define COR_TEXT "Cor" #define SAG_TEXT "Sag" #define TRA_TEXT "Tra" #define FIELD_OF_VIEW_SIZE 11 #define FIELD_OF_VIEW_TEXT "FoV" #define ZOOM_CENTER_SIZE 11 #define ZOOM_CENTER_TEXT "CE" #define ZOOM_CENTER_TEXT_MR "MF" #define GANTRY_TILT_SIZE 11 #define GANTRY_TILT_TEXT "GT" #define TABLE_POSITION_SIZE 11 #define TABLE_POSITION_TEXT "TP" #define MIP_HEADLINE_SIZE 3 #define MIP_HEADLINE_TEXT "VOI" #define MIP_LINE_SIZE 15 #define MIP_LINE_TEXT "Lin" #define MIP_COLUMN_SIZE 15 #define MIP_COLUMN_TEXT "Col" #define MIP_SLICE_SIZE 15 #define MIP_SLICE_TEXT "Sli" #define STUDY_NUMBER_SIZE 11 #define STUDY_NUMBER_TEXT "STUDY" #define CONTRAST_SIZE 5 #define CONTRAST_TEXT_CT "+C IV" #define CONTRAST_TEXT_MR "+C " #define CONTRAST_TEXT_NONE " " #define PATIENT_BIRTHDATE_SIZE 11 #define SEQUENCE_INFO_SIZE 11 #define SATURATION_REGIONS_SIZE 11 #define SATURATION_REGIONS_TEXT "SAT" #define DATA_SET_ID_SIZE 26 #define DATA_SET_ID_TEXT_STUDY "STU" #define DATA_SET_ID_TEXT_IMAGE "IMA" #define DATA_SET_ID_TEXT_DELIMITER "/" #define MAGNIFICATION_FACTOR_SIZE 11 #define MAGNIFICATION_FACTOR_TEXT "MF" #define MANUFACTURER_MODEL_SIZE 26 #define PATIENT_NAME_SIZE 26 #define TIME_OF_SCANNING_SIZE 8 typedef struct text_info { char PatientNumber[PATIENT_NUMBER_SIZE + 1]; /* Patient Id */ char PatientSexAndAge[PATIENT_DATE_SIZE + 1]; /* Patient Sex, Patient Age */ char PatientPosition[PATIENT_POSITION_SIZE + 1]; /* Patient Rest Direction, ... */ char ImageNumber[IMAGE_NUMBER_SIZE + 1]; /* Image */ char Label[LABEL_SIZE + 1]; /* Archiving Mark Mask, ... */ char DateOfMeasurement[DATE_OF_MEASUREMENT_SIZE + 1]; /* Acquisition Date */ char TimeOfMeasurement[TIME_OF_MEASUREMENT_SIZE + 1]; /* Acquisition Time */ char TimeOfAcquisition[TIME_OF_ACQUISITION_SIZE + 1]; /* CT: Exposure Time MR: Total Measurement Time */ char NumberOfAcquisitions[NUMBER_OF_ACQUISITIONS_SIZE + 1]; /* Number of Averages */ char CommentNo1[COMMENT_NO1_SIZE + 1]; /* Procedure Description */ char CommentNo2[COMMENT_NO2_SIZE + 1]; char InstallationName[INSTALLATION_NAME_SIZE + 1]; /* Institution ID */ char SoftwareVersion[SOFTWARE_VERSION_SIZE + 1]; /* Software Version */ char Matrix[MATRIX_SIZE + 1]; /* Rows, Columns */ char TypeOfMeasurement[TYPE_OF_MEASUREMENT_SIZE + 1]; /* Calculation Mode */ char ScanNumber[SCAN_NUMBER_SIZE + 1]; /* Acquisition */ char RepetitionTime[REPETITION_TIME_SIZE + 1]; /* Repetition Time */ char EchoTime[ECHO_TIME_SIZE + 1]; /* Echo Time */ char GatingAndTrigger[GATING_AND_TRIGGER_SIZE + 1]; /* Signal Mask */ char TubeCurrent[TUBE_CURRENT_SIZE + 1]; /* Exposure */ char TubeVoltage[TUBE_VOLTAGE_SIZE + 1]; /* Generator Power */ char SliceThickness[SLICE_THICKNESS_SIZE + 1]; /* Slice Thickness */ char SlicePosition[SLICE_POSITION_SIZE + 1]; /* Image Distance */ char SliceOrientationNo1[SLICE_ORIENTATION_NO1_SIZE + 1]; /* Image Position, ... */ char SliceOrientationNo2[SLICE_ORIENTATION_NO2_SIZE + 1]; char FieldOfView[FIELD_OF_VIEW_SIZE + 1]; /* Field of View */ char ZoomCenter[ZOOM_CENTER_SIZE + 1]; /* Target */ char GantryTilt[GANTRY_TILT_SIZE + 1]; /* Gantry Tilt */ char TablePosition[TABLE_POSITION_SIZE + 1]; /* Location */ char MipHeadLine[MIP_HEADLINE_SIZE + 1]; /* */ char MipLine[MIP_LINE_SIZE + 1]; /* MIP x Row */ char MipColumn[MIP_COLUMN_SIZE + 1]; /* MIP x Column */ char MipSlice[MIP_SLICE_SIZE + 1]; /* MIP x Slice */ char StudyNumber[STUDY_NUMBER_SIZE + 1]; /* Study */ char Contrast[CONTRAST_SIZE + 1]; /* Contrast Agent */ char PatientBirthdate[PATIENT_BIRTHDATE_SIZE + 1]; /* Patient Birthday */ char SequenceInformation[SEQUENCE_INFO_SIZE + 1]; /* Sequence File Owner, ... */ char SaturationRegions[SATURATION_REGIONS_SIZE + 1]; /* Saturation Regions, ... */ char DataSetId[DATA_SET_ID_SIZE + 1]; /* Image, Study */ char MagnificationFactor[MAGNIFICATION_FACTOR_SIZE + 1]; /* Image Maginification Factor */ char ManufacturerModel[MANUFACTURER_MODEL_SIZE + 1]; /* Manufacturer Model */ char PatientName[PATIENT_NAME_SIZE + 1]; /* Patient Name */ char TimeOfScanning[TIME_OF_SCANNING_SIZE + 1]; /* Acquisition Time */ } text_info_t; #if 0 struct text_info { char PatientID[12+1]; /* 5504 */ char PatientSex[1]; /* 5517 */ char PatientAge[3]; /* 5518 */ char PatientAgeUnits[1]; /* 5521 */ char pad1[7]; /* 5522 */ char PatientPosition[12]; /* 5529 */ char ImageNumberFlag[5]; /* 5541 */ char ImageNumber[3]; /* 5546 */ char pad2[10]; /* 5551 */ char Date[11+1]; /* 5559 */ char Time[5+1]; /* 5571 */ char AcquisitionTimeFlag[6]; /* 5577 */ char AcquisitionTime[5+1]; /* 5583 */ char AcquisitionCountFlag[6]; /* 5589 */ char AcquisitionCount[5+1]; /* 5595 */ char Annotation[27]; /* 5601 */ char AdmittingDiagnosis[27]; /* 5628 */ char Organization[27]; /* 5655 */ char Station[12]; /* 5682 */ char AcquisitionMatrixPhase[3]; /* 5695 */ char AcquisitionMatrixPhaseAxis[1]; char AcquisitionMatrixFreq[3]; char AcquisitionMatrixFreq0[1]; char AcquisitionMatrixFreqS[1]; char Sequence[8]; char FlipAngle[3]; char ScanNumberFlag[4]; char ScanNumberA[3]; char ScanNumberB[3]; char RepetitionTimeFlag[2]; char RepetitionTime[7]; char EchoTimeFlag[2]; char EchoTime[5]; char EchoNumber[1]; char SliceThicknessFlag[2]; char SliceThickness[7]; char SlicePositionFlag[2]; char SlicePosition[7]; char AngleFlag1[3]; char AngleFlag2[1]; char AngleFlag3[3]; char Angle[4]; char FOVFlag[3]; char FOVH[3]; char FOVV[3]; char TablePositionFlag[2]; char TablePosition[7]; char StudyNumberFlag[5]; char StudyNumber[2]; char DOBDD[2]; char DOBMM[3]; char DOBYYYY[4]; char StudyNumberFlag2[3]; char ImageNumberFlag2[3]; char StudyNumber2[2]; char ImageNumber2[2]; char StudyImageNumber3[5]; char ModelName[15]; char PatientName[27]; /* 6058 */ char ScanStartTimeHH[3]; /* 6085 */ char ScanStartTimeMM[3]; /* 6088 */ char ScanStartTimeSS[3]; /* 6091 */ }; #endif /* Siemens IMA header - total size is 0x1800 bytes */ typedef struct { /* Offset - Description */ struct ima_acr_0008 G08; /* 0x0000 - Identifying Information */ char G09[0x0180]; /* 0x0180 - Siemens specific */ struct ima_acr_0010 G10; /* 0x0300 - Patient Information */ char G11[0x0080]; /* 0x0400 - Siemens specific */ char G13[0x0180]; /* 0x0480 - Siemens specific */ struct ima_acr_0018 G18; /* 0x0600 - Acquisition Information */ struct ima_siemens_0019 G19; /* 0x0780 - Siemens specific */ struct ima_acr_0020 G20; /* 0x0C80 - Relationship Information */ struct ima_siemens_0021 G21; /* 0x0E80 - Siemens specific */ struct ima_acr_0028 G28; /* 0x1380 - Image Presentation Information */ char G29[0x0100]; /* 0x1480 - Siemens specific */ text_info_t ti; } ima_header_t; #endif /* _SIEMENS_HEADER_DEFS_H_ */ minc-2.2.00/conversion/dcm2mnc/siemens_header_table.h0000644000265600003100000001502312027132660017442 00000000000000Siemens_hdr_entry Siemens_hdr_table[] = { {0x0008, 0x0020, &IMA_hdr.G08.StudyDate, create_ima_date_t_element, 1}, {0x0008, 0x0022, &IMA_hdr.G08.AcquisitionDate, create_ima_date_t_element, 1}, {0x0008, 0x0023, &IMA_hdr.G08.ContentDate, create_ima_date_t_element, 1}, {0x0008, 0x0030, &IMA_hdr.G08.StudyTime, create_ima_time_t_element, 1}, {0x0008, 0x0032, &IMA_hdr.G08.AcquisitionTime, create_ima_time_t_element, 1}, {0x0008, 0x0033, &IMA_hdr.G08.ContentTime, create_ima_time_t_element, 1}, {0x0008, 0x0060, &IMA_hdr.G08.Modality, create_modality_element, 1}, {0x0008, 0x0070, &IMA_hdr.G08.Manufacturer, create_char_element, N_MANUFACTURER+1}, {0x0008, 0x0080, &IMA_hdr.G08.InstitutionName, create_char_element, N_STRING+1}, {0x0008, 0x0090, &IMA_hdr.G08.PhysicianName, create_char_element, N_STRING+1}, {0x0008, 0x1010, &IMA_hdr.G08.StationName, create_char_element, N_STRING+1}, {0x0008, 0x1030, &IMA_hdr.G08.StudyDescription, create_char_element, N_STRING+1}, {0x0008, 0x1080, &IMA_hdr.G08.AdmittingDiagnoses, create_char_element, N_DIAGNOSIS+1}, {0x0008, 0x1090, &IMA_hdr.G08.ModelName, create_char_element, N_STRING+1}, {0x0010, 0x0010, &IMA_hdr.G10.PatientName, create_char_element, N_STRING+1}, {0x0010, 0x0020, &IMA_hdr.G10.PatientID, create_char_element, N_PATIENTID+1}, {0x0010, 0x0030, &IMA_hdr.G10.PatientDOB, create_ima_date_t_element, 1}, {0x0010, 0x0040, &IMA_hdr.G10.PatientSex, create_sex_element, 1}, {0x0010, 0x1005, &IMA_hdr.G10.PatientBirthName, create_char_element, N_STRING+1}, {0x0010, 0x1010, &IMA_hdr.G10.PatientAge, create_age_element, 1}, {0x0010, 0x1030, &IMA_hdr.G10.PatientWeight, create_long_element, 1}, {0x0018, 0x0050, &IMA_hdr.G18.SliceThickness, create_double_element, 1}, {0x0018, 0x0080, &IMA_hdr.G18.RepetitionTime, create_double_element, 1}, {0x0018, 0x0081, &IMA_hdr.G18.EchoTime, create_double_element, 1}, {0x0018, 0x0082, &IMA_hdr.G18.InversionTime, create_double_element, 1}, {0x0018, 0x0083, &IMA_hdr.G18.NumberOfAverages, create_long_element, 1}, {0x0018, 0x0084, &IMA_hdr.G18.ImagingFrequency, create_double_element, 1}, {0x0018, 0x0085, &IMA_hdr.G18.ImagedNucleus, create_char_element, N_NUCLEUS+1}, {0x0018, 0x0086, &IMA_hdr.G18.EchoNumber, create_long_element, 1}, {0x0018, 0x0090, &IMA_hdr.G18.DataCollectionDiameter, create_long_element, 1}, {0x0018, 0x1000, &IMA_hdr.G18.SerialNumber, create_char_element, N_STRING+1}, {0x0018, 0x1020, &IMA_hdr.G18.SoftwareVersion, create_char_element, N_SWVERSION+1}, {0x0018, 0x1200, &IMA_hdr.G18.CalibrationDate, create_ima_date_t_element, 1}, {0x0018, 0x1201, &IMA_hdr.G18.CalibrationTime, create_ima_time_t_element, 1}, {0x0018, 0x1250, &IMA_hdr.G18.ReceiveCoilName, create_char_element, N_STRING+1}, {0x0018, 0x5100, &IMA_hdr.G18.PatientPosition, create_ima_position_t_element, 1}, {0x0019, 0x1060, &IMA_hdr.G19.NumberOfDataBytes, create_long_element, 1}, {0x0019, 0x1220, &IMA_hdr.G19.FourierLinesNominal, create_long_element, 1}, {0x0019, 0x1226, &IMA_hdr.G19.FourierLinesAfterZero, create_long_element, 1}, {0x0019, 0x1228, &IMA_hdr.G19.FirstMeasuredFourierLine, create_long_element, 1}, {0x0019, 0x1230, &IMA_hdr.G19.AcquisitionColumns, create_long_element, 1}, {0x0019, 0x1231, &IMA_hdr.G19.ReconstructionColumns, create_long_element, 1}, {0x0019, 0x1250, &IMA_hdr.G19.NumberOfAverages, create_long_element, 1}, {0x0019, 0x1260, &IMA_hdr.G19.FlipAngle, create_double_element, 1}, {0x0019, 0x1270, &IMA_hdr.G19.NumberOfPrescans, create_long_element, 1}, {0x0019, 0x1290, &IMA_hdr.G19.SaturationRegions, create_long_element, 1}, {0x0019, 0x1412, &IMA_hdr.G19.MagneticFieldStrength, create_double_element, 1}, {0x0020, 0x0010, &IMA_hdr.G20.StudyID, create_long_element, 1}, {0x0020, 0x0012, &IMA_hdr.G20.AcquisitionNumber, create_long_element, 1}, {0x0020, 0x0013, &IMA_hdr.G20.InstanceNumber, create_long_element, 1}, {0x0020, 0x0050, &IMA_hdr.G20.Location, create_long_element, 1}, {0x0020, 0x0060, &IMA_hdr.G20.Laterality, create_laterality_element, 1}, {0x0020, 0x1001, &IMA_hdr.G20.AcquisitionsInSeries, create_long_element, 1}, {0x0021, 0x1120, &IMA_hdr.G21.FieldOfView, create_field_of_view_t_element, 1}, {0x0021, 0x1122, &IMA_hdr.G21.ImageMagnificationFactor, create_double_element, 1}, {0x0021, 0x1130, &IMA_hdr.G21.ViewDirection, create_view_direction_t_element, 1}, {0x0021, 0x1132, &IMA_hdr.G21.RestDirection, create_rest_direction_t_element, 1}, {0x0021, 0x1160, &IMA_hdr.G21.ImagePosition, create_ima_vector_t_element, 1}, {0x0021, 0x1161, &IMA_hdr.G21.ImageNormal, create_ima_vector_t_element, 1}, {0x0021, 0x1163, &IMA_hdr.G21.ImageDistance, create_double_element, 1}, {0x0021, 0x116a, &IMA_hdr.G21.ImageRow, create_ima_vector_t_element, 1}, {0x0021, 0x116b, &IMA_hdr.G21.ImageColumn, create_ima_vector_t_element, 1}, {0x0021, 0x1170, &IMA_hdr.G21.OrientationSet1, create_ima_orientation_t_element, 1}, {0x0021, 0x1171, &IMA_hdr.G21.OrientationSet2, create_ima_orientation_t_element, 1}, {0x0021, 0x1180, &IMA_hdr.G21.StudyName, create_char_element, N_STRING+1}, {0x0021, 0x1330, &IMA_hdr.G21.NumberOf3DRawPartNom, create_long_element, 1}, {0x0021, 0x1331, &IMA_hdr.G21.NumberOf3DRawPartCur, create_long_element, 1}, {0x0021, 0x1334, &IMA_hdr.G21.NumberOf3DImaPart, create_long_element, 1}, {0x0021, 0x1336, &IMA_hdr.G21.Actual3DImaPartNumber, create_long_element, 1}, {0x0021, 0x1339, &IMA_hdr.G21.SlabThickness, create_double_element, 1}, {0x0021, 0x1340, &IMA_hdr.G21.NumberOfSlicesNom, create_long_element, 1}, {0x0021, 0x1341, &IMA_hdr.G21.NumberOfSlicesCur, create_long_element, 1}, {0x0021, 0x1342, &IMA_hdr.G21.CurrentSliceNumber, create_long_element, 1}, {0x0021, 0x1343, &IMA_hdr.G21.CurrentGroupNumber, create_long_element, 1}, {0x0021, 0x134f, &IMA_hdr.G21.SliceOrder, create_slice_order_element, 1}, {0x0021, 0x1370, &IMA_hdr.G21.NumberOfEchoes, create_long_element, 1}, {0x0028, 0x0005, &IMA_hdr.G28.ImageDimension, create_short_element, 1}, {0x0028, 0x0010, &IMA_hdr.G28.Rows, create_short_element, 1}, {0x0028, 0x0011, &IMA_hdr.G28.Columns, create_short_element, 1}, {0x0028, 0x0030, &IMA_hdr.G28.PixelSpacing, create_pixel_spacing_t_element, 1}, {0x0028, 0x0100, &IMA_hdr.G28.BitsAllocated, create_short_element, 1}, {0x0028, 0x0101, &IMA_hdr.G28.BitsStored, create_short_element, 1}, {0x0028, 0x0102, &IMA_hdr.G28.HighBit, create_short_element, 1}, {0x0028, 0x0103, &IMA_hdr.G28.PixelRepresentation, create_short_element, 1}, {0x0028, 0x1050, &IMA_hdr.G28.WindowCenter, create_window_t_element, 1}, {0x0028, 0x1051, &IMA_hdr.G28.WindowWidth, create_window_t_element, 1}, {0x0028, 0x1052, &IMA_hdr.G28.RescaleIntercept, create_long_element, 1}, {0x0028, 0x1053, &IMA_hdr.G28.RescaleSlope, create_long_element, 1}, {0, 0, NULL, NULL, 0} }; minc-2.2.00/conversion/dcm2mnc/spi_element_defs.h0000644000265600003100000001334712027132660016634 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : spi_element_defs.h @DESCRIPTION: Element definitions for Siemens "Standard Product Interconnect" @METHOD : @GLOBALS : @CALLS : @CREATED : November 23, 1993 (Peter Neelin) @MODIFIED : @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Element id's for SPI */ /* Most of this information is available at David Clunie's medical imaging * website (www.dclunie.com). */ GLOBAL_ELEMENT(SPI_PMS_grp19_tag , 0x0019, 0x0010, CS); GLOBAL_ELEMENT(SPI_PMS_field_of_view , 0x0019, 0x1000, DS); GLOBAL_ELEMENT(SPI_PMS_cc_angle , 0x0019, 0x1005, DS); GLOBAL_ELEMENT(SPI_PMS_ap_angle , 0x0019, 0x1006, DS); GLOBAL_ELEMENT(SPI_PMS_lr_angle , 0x0019, 0x1007, DS); /* 0 undefined, 1 head first, 2 feet first */ GLOBAL_ELEMENT(SPI_PMS_patient_position , 0x0019, 0x1008, CS); /* 0 undefined, 1 supine, 2 prone, 3 left decubitus, 4 right decubitus */ GLOBAL_ELEMENT(SPI_PMS_patient_orientation , 0x0019, 0x1009, CS); /* 0 undefined 1 transverse 2 sagittal 3 coronal */ GLOBAL_ELEMENT(SPI_PMS_slice_orientation , 0x0019, 0x100a, CS); /* caudal-cranial position (MINC Z) */ GLOBAL_ELEMENT(SPI_PMS_cc_position , 0x0019, 0x100b, DS); /* anterior-posterior position (MINC Y) */ GLOBAL_ELEMENT(SPI_PMS_ap_position , 0x0019, 0x100c, DS); /* left-right position (MINC X) */ GLOBAL_ELEMENT(SPI_PMS_lr_position , 0x0019, 0x100d, DS); GLOBAL_ELEMENT(SPI_PMS_slice_count , 0x0019, 0x100f, IS); GLOBAL_ELEMENT(SPI_PMS_flip_angle , 0x0019, 0x101a, DS); /* caudal-cranial position (MINC X) */ GLOBAL_ELEMENT(SPI_PMS_lr_position2 , 0x0019, 0x110b, DS); /* anterior-posterior position (MINC Z) */ GLOBAL_ELEMENT(SPI_PMS_cc_position2 , 0x0019, 0x110c, DS); /* left-right position (MINC Z) */ GLOBAL_ELEMENT(SPI_PMS_ap_position2 , 0x0019, 0x110d, DS); GLOBAL_ELEMENT(SPI_Number_of_data_bytes , 0x0019, 0x1060, IS); GLOBAL_ELEMENT(SPI_Fourier_lines_nominal , 0x0019, 0x1220, IS); GLOBAL_ELEMENT(SPI_Fourier_lines_after_zero , 0x0019, 0x1226, IS); GLOBAL_ELEMENT(SPI_First_measured_fourier_line , 0x0019, 0x1228, IS); GLOBAL_ELEMENT(SPI_Acquisition_columns , 0x0019, 0x1230, LO); GLOBAL_ELEMENT(SPI_Reconstruction_columns , 0x0019, 0x1231, LO); GLOBAL_ELEMENT(SPI_Number_of_averages , 0x0019, 0x1250, IS); GLOBAL_ELEMENT(SPI_Flip_angle , 0x0019, 0x1260, DS); GLOBAL_ELEMENT(SPI_Number_of_prescans , 0x0019, 0x1270, IS); GLOBAL_ELEMENT(SPI_Saturation_regions , 0x0019, 0x1290, IS); GLOBAL_ELEMENT(SPI_Magnetic_field_strength , 0x0019, 0x1412, DS); GLOBAL_ELEMENT(SPI_Base_raw_matrix_size , 0x0019, 0x14d4, IS); GLOBAL_ELEMENT(SPI_Field_of_view , 0x0021, 0x1120, DS); GLOBAL_ELEMENT(SPI_Image_magnification_factor , 0x0021, 0x1122, DS); GLOBAL_ELEMENT(SPI_View_direction , 0x0021, 0x1130, CS); GLOBAL_ELEMENT(SPI_Rest_direction , 0x0021, 0x1132, CS); GLOBAL_ELEMENT(SPI_Image_position , 0x0021, 0x1160, DS); GLOBAL_ELEMENT(SPI_Image_normal , 0x0021, 0x1161, DS); GLOBAL_ELEMENT(SPI_Image_distance , 0x0021, 0x1163, DS); GLOBAL_ELEMENT(SPI_Image_row , 0x0021, 0x116a, DS); GLOBAL_ELEMENT(SPI_Image_column , 0x0021, 0x116b, DS); GLOBAL_ELEMENT(SPI_Patient_orientation_set1 , 0x0021, 0x1170, CS); GLOBAL_ELEMENT(SPI_Patient_orientation_set2 , 0x0021, 0x1171, CS); GLOBAL_ELEMENT(SPI_Study_name , 0x0021, 0x1180, CS); GLOBAL_ELEMENT(SPI_Study_type , 0x0021, 0x1182, CS); GLOBAL_ELEMENT(SPI_Number_of_3D_raw_partitions_nominal, 0x0021, 0x1330, IS); GLOBAL_ELEMENT(SPI_Number_of_3d_raw_part_cur , 0x0021, 0x1331, IS); GLOBAL_ELEMENT(SPI_Number_of_3D_image_partitions , 0x0021, 0x1334, IS); GLOBAL_ELEMENT(SPI_Actual_3D_partition_number , 0x0021, 0x1336, IS); GLOBAL_ELEMENT(SPI_Slab_thickness , 0x0021, 0x1339, DS); GLOBAL_ELEMENT(SPI_Number_of_slices_nominal , 0x0021, 0x1340, IS); GLOBAL_ELEMENT(SPI_Number_of_slices_cur , 0x0021, 0x1341, IS); GLOBAL_ELEMENT(SPI_Current_slice_number , 0x0021, 0x1342, IS); GLOBAL_ELEMENT(SPI_Order_of_slices , 0x0021, 0x134f, IS); GLOBAL_ELEMENT(SPI_Number_of_echoes , 0x0021, 0x1370, IS); /* These are the two large fields in Siemens files in which many parameters * are dumped. The ASCCONV block is located in the second (0029, 1020), but * many of the DTI parameters are available in the first. */ GLOBAL_ELEMENT(SPI_Protocol2 , 0x0029, 0x1010, CS); GLOBAL_ELEMENT(SPI_Protocol , 0x0029, 0x1020, CS); minc-2.2.00/conversion/dcm2mnc/string_to_filename.h0000644000265600003100000000023212027132660017164 00000000000000extern void string_to_filename(const char *string, char *filename, int maxlen); extern void string_to_initials(char *string, char *filename, int maxlen); minc-2.2.00/conversion/dcm2mnc/pms_element_defs.h0000644000265600003100000001073112027132660016632 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : pms_element_defs.h @DESCRIPTION: Element definitions for Philips Medical Systems (no, really) @METHOD : @GLOBALS : @CALLS : @CREATED : March 11, 2005 @MODIFIED : @COPYRIGHT : Copyright (C) 2005 Robert D. Vincent, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* This information was derived from the publically available "DICOM * Conformance Statement" for the Philips Medical Systems MR Intera * 10.1, 10 April 2003. * * However, not all Philips scanners use the fixed element numbers * implied here. The upper eight bits of the element ID's are not * entirely deterministic. It is necessary to root around in the * image for the private groups. */ #define PMS_PRIVATE_GROUP_ID 0x2001 GLOBAL_ELEMENT(PMS_Chemical_Shift , 0x2001, 0x1001, FL); GLOBAL_ELEMENT(PMS_Chemical_Shift_Number_MR , 0x2001, 0x1002, IS); GLOBAL_ELEMENT(PMS_Diffusion_B_Factor , 0x2001, 0x1003, FL); GLOBAL_ELEMENT(PMS_Diffusion_Direction , 0x2001, 0x1004, CS); GLOBAL_ELEMENT(PMS_Image_Enhanced , 0x2001, 0x1006, CS); GLOBAL_ELEMENT(PMS_Image_Type_ED_ES , 0x2001, 0x1007, CS); GLOBAL_ELEMENT(PMS_Phase_number , 0x2001, 0x1008, IS); /* xx09 is present but not defined */ GLOBAL_ELEMENT(PMS_Slice_Number_MR, /* Slice index in series */ 0x2001, 0x100a, IS); GLOBAL_ELEMENT(PMS_Slice_Orientation, /* SAGITTAL, TRANSVERSAL, e.g. */ 0x2001, 0x100b, CS); /* xx0c, xx0e, xx0f, xx10 are present but not defined */ GLOBAL_ELEMENT(PMS_Diffusion_Echo_Time , 0x2001, 0x1011, FL); GLOBAL_ELEMENT(PMS_Dynamic_Series , 0x2001, 0x1012, CS); GLOBAL_ELEMENT(PMS_EPI_Factor , 0x2001, 0x1013, SL); GLOBAL_ELEMENT(PMS_Number_of_Echoes , 0x2001, 0x1014, SL); GLOBAL_ELEMENT(PMS_Number_of_Locations , 0x2001, 0x1015, SS); GLOBAL_ELEMENT(PMS_Number_of_PC_Locations , 0x2001, 0x1016, SS); GLOBAL_ELEMENT(PMS_Number_of_Phases_MR , 0x2001, 0x1017, SL); GLOBAL_ELEMENT(PMS_Number_of_Slices_MR , 0x2001, 0x1018, SL); GLOBAL_ELEMENT(PMS_Partial_Matrix_Scanned , 0x2001, 0x1019, CS); GLOBAL_ELEMENT(PMS_PC_Velocity , 0x2001, 0x101a, FL); GLOBAL_ELEMENT(PMS_Prepulse_Delay , 0x2001, 0x101b, FL); GLOBAL_ELEMENT(PMS_Prepulse_Type , 0x2001, 0x101c, CS); GLOBAL_ELEMENT(PMS_Reconstruction_Number , 0x2001, 0x101d, IS); /* xx1e is present but not defined */ GLOBAL_ELEMENT(PMS_Respiration_Sync , 0x2001, 0x101f, CS); GLOBAL_ELEMENT(PMS_Scanning_Technique_Description_MR , 0x2001, 0x1020, CS); GLOBAL_ELEMENT(PMS_SPIR , 0x2001, 0x1021, CS); GLOBAL_ELEMENT(PMS_Water_Fat_Shift , 0x2001, 0x1022, FL); /* xx23 xx24 both present but undefined xx23 appears to be the flip angle, as in DICOM (0018,1314) */ GLOBAL_ELEMENT(PMS_Echo_Time_Display , 0x2001, 0x1025, SH); GLOBAL_ELEMENT(PMS_Number_of_Stack_Slices , 0x2001, 0x102d, SS); GLOBAL_ELEMENT(PMS_Stack_Radial_Angle , 0x2001, 0x1032, FL); GLOBAL_ELEMENT(PMS_Stack_Radial_Axis , 0x2001, 0x1033, CS); GLOBAL_ELEMENT(PMS_Stack_Slice_Number , 0x2001, 0x1035, SS); GLOBAL_ELEMENT(PMS_Stack_Type , 0x2001, 0x1036, CS); /* xx52, xx5f both present but undefined */ GLOBAL_ELEMENT(PMS_Number_of_Stacks , 0x2001, 0x1060, SL); GLOBAL_ELEMENT(PMS_Examination_Source , 0x2001, 0x1063, CS); /* additional undefined elements include: xx60-xx62, xx6e, xx7b, xx81-xx8b, 9000 xx83 appears to be the imaging frequency, as in DICOM (0018,0084) */ minc-2.2.00/conversion/dcm2mnc/gems_element_defs.h0000644000265600003100000000440212027132660016764 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : gems_element_defs.h @DESCRIPTION: Element definitions for GE Medical Systems @METHOD : @GLOBALS : @CALLS : @CREATED : March 14, 2005 @MODIFIED : @COPYRIGHT : Copyright (C) 2005 Robert D. Vincent, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* This information was derived from the publically available "Advance(TM) * 4.05 Conformance Statement for DICOM V3.0" from GE Medical Systems, * copyright 2000 by GE Medical Systems. */ GLOBAL_ELEMENT(GEMS_Acqu_private_creator_id, 0x0019, 0x0010, SH); GLOBAL_ELEMENT(GEMS_Frame_acq_start , 0x0019, 0x106c, DT); GLOBAL_ELEMENT(GEMS_Frame_acq_duration , 0x0019, 0x106d, SL); GLOBAL_ELEMENT(GEMS_Image_slice_number , 0x0019, 0x10a6, SL); GLOBAL_ELEMENT(GEMS_Fast_phases , 0x0019, 0x10f2, SS); GLOBAL_ELEMENT(GEMS_Sers_private_creator_id, 0x0025, 0x0010, SH); GLOBAL_ELEMENT(GEMS_Images_in_series , 0x0025, 0x1007, SL); /* not yet fully defined */ /* from http://www.gehealthcare.com/usen/interoperability/dicom/docs/5162373r1.pdf */ #if 0 /* If release 10.0 or above (0019,10e0) gives # diffusion directions, * otherwise (0019,10df) and/or (0019,10d9) are used. */ GLOBAL_ELEMENT(GEMS_DTI_diffusion_directions, 0x0019, 0x10e0, DS); GLOBAL_ELEMENT(GEMS_DTI_diffusion_directions, 0x0019, 0x10df, DS); GLOBAL_ELEMENT(GEMS_Concatenated_SAT, 0x0019, 0x10d9, DS); GLOBAL_ELEMENT(GEMS_Diffusion_direction, 0x0021, 0x105a, SL); /* this field apparently consists of 4 integers - the first gives the * b-value in DTI?? */ GLOBAL_ELEMENT(GEMS_Slop_int_69, 0x0049, 0x1039, IS); #endif minc-2.2.00/conversion/dcm2mnc/dcm2mnc.man10000644000265600003100000002160312027132660015251 00000000000000.TH dcm2mnc 1 "May 03 2005" "$Revision: 1.5 $" "" .SH NAME .B dcm2mnc - convert sets of DICOM files to one or more MINC format files. .SH SYNOPSIS .B dcm2mnc .I [] .B dcm2mnc .I -help .SH DESCRIPTION The .B dcm2mnc command is used to convert DICOM format files to MINC format. DICOM (Digital Imaging and Communications in Medicine) format is used by many vendors of medical imaging equipment as a standard means of data interchange. The DICOM specification is extremely complex and includes protocols for data interchange and communications as well as the specifics of the data format. In most cases, tens or even hundreds of DICOM files must be combined to produce a single MINC file. In normal operation, the .I input-list will consist of the names of one or more files or directories. The program scans all specified input files and directories and attempts to identify groups of files that should be combined into a single MINC file. Once these groups (or "series") of DICOM files are identified, the program analyzes the data for each series and attempts to determine the correct geometry and ancillary information to be incorporated into the MINC file. If all goes well, one or more MINC files will be created in one or more subdirectories created in the specified directory .IR output-dir . These directories and files will be automatically named according to the patient's name, the acquisition date, acquisition time, series identifier, and modality. For a variety of reasons, medical imaging manufacturers have chosen to implement a number of proprietary extensions to the DICOM format. This program attempts to be very general, but it does some extra checking for specific proprietary fields where useful or necessary. However, as device settings change and software is updated, the precise details of the DICOM output for a given device may shift. Different devices from the same manufacturer may produce substantially different DICOM output. .SH "OPTIONS" Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH "Output file options" .TP .BI -clobber Overwrite existing files. By default, .B dcm2mnc will not write over an existing file. .TP .BI -anon Do not store the patient name in the MINC file. The string "anonymous" will be used instead. Note that all other identifying information will still be stored in the file. .TP .BI -nosplitecho Do not split echoes into separate files. If multiple echoes are present in a series, they will all be stored in a single MINC file with a dimension named "echo". .TP .BI -splitdynamic Split dynamic scans into separate files. Normally dynamic scans are stored in a single MINC file with a "time" dimension. If this option is specified, each time slice will be saved in a separate file. .TP .BI -fname " " Set the format of the output file name. See FILENAMES section for details on this option. .TP .BI -dname " " Set the format of the output subdirectory name. See FILENAMES section for details on this option. Set this to the empty string to avoid creating a subdirectory. .SH "Siemens mosaic specific options" These two options control the manner in which Siemens mosaic data is converted. Siemens scanners commonly represent fMRI data as a "mosaic" of subimages combined into a single large image. Normally these are in what we call "ascending" order, but if your functional image is not converted properly, you may need to specify one of these options. NOTE that the mosaic order is often not the same as the slice acquisition order. .TP .BI -descending The mosaic image is stored in descending order. .TP .BI -interleaved The mosaic image is stored in alternating (odd/even) order. .SH "Other options" .TP .BI -stdin This option tells .B dcm2mnc to read a list of input files from the standard input in addition to any files specified on the command line. .TP .BI -cmd " " This option will apply the given command string to each output file after it is created. Can be used to run gzip or compress on each output file, for example. .TP .BI -minmax Use the values for the largest and smallest pixel value as stored in the DICOM file. This is useful especially with GE PET data, but may be needed to get a quantitatively accurate conversion with other manufacturers. If this option is not specified. .B dcm2mnc uses the full range of the datatype as specified by the number of bits stored per voxel (field # 0028,0101). When this option is specified, the 0028,0106 and 0028,0107 will be used to set the valid range of pixels. .TP .BI -list List files in series, but do not perform conversion. Sometimes useful for verifying the validity of a dataset, and for debugging problems with .BR dcm2mnc . .TP .BI -verbose Verbose operation. Prints a large amount of additional information about the program's operation. This information can probably only be interpreted by someone familiar with both this program and the DICOM standard. .TP .BI -debug Extremely verbose operation. Prints a huge amount of additional information about the program's operation. This information can probably only be interpreted by someone familiar with both this program and the DICOM standard. .TP .BI -usecoordinates This option requests that the conversion rely on the slice coordinates rather than the standard DICOM fields for slice thickness and spacing. It is useful if for some reason the standard DICOM fields for slice thickness and spacing are incorrect. .TP .BI -opts " " This is a private option intended only for debugging purposes. Please avoid using it. .SH "Generic options for all commands" .TP .BI -help Print summary of command\-line options and abort .TP .BI -version Print the program and library versions and abort .SH FILENAMES To avoid naming collisions when converting a large set of input DICOM files to a smaller set of MINC output files, .B dcm2mnc automatically generates the names of output files according to various parameters of the DICOM file information. The normal behavior is to place all of the output files in a subdirectory of the given output directory which has its name derived from the patient's name and the study date and time as follows: patientname\_yyyymmdd\_hhmmss/ The individual files are named according to the patient name, study date and time, series identifer, and modality information as follows: patientname\_yyyymmdd\_hhmmss\_series\_scan\_modality.mnc The optional scan information includes the echo number ('e'), slice number ('sl'), time series position ('d'), phase number ('p'), or chemical shift ('cs'). The optional modality information consists of either the string "_pet" or "_mri". No suffix is added for unrecognized modalities. The .B -fname and .B -dname commands allow the user to override the standard file naming behavior by specifying alternative output directory and file formats. The arguments to these options are template strings that will be expanded to include information from the DICOM sequences in specified locations. Replacements are specified by a '%' character followed by a single alphabetic character, as follows: %N - Name of patient %D - Date of scan %T - Time of scan %S - Study ID (typically 'yyyymmdd.hhmmss') %A - Acquisition or series ID %s - Optional slice label %e - Optional echo number %t - Optional dynamic scan number %p - Optional phase number %c - Optional chemical shift number %m - Optional modality The default file name convention is therefore given by the format string: %N_%D_%T_%A%s%e%t%p%c%m and the default directory name is given by the format string: %N_%D_%T If you wish to avoid creating a subdirectory, you may do so by giving a zero-length string as the argument to the .B -dname option: dcm2mnc -dname \'\' filenames... .SH AUTHORS Peter Neelin and Richard D. Hoge Please direct all complaints and inquiries to Robert Vincent (bert@bic.mni.mcgill.ca) .SH BUGS Probably many. For best results, output files should be checked by a competent human to verify that the conversion was performed properly. DICOM is a very complex format, and it is difficult to anticipate all of the possible combinations of fields and values that may be encountered. If you have a problem, please contact the maintainer. It will be extremely useful if you can provide an example dataset that exhibits the problem you have discovered. .SH "SEE ALSO" For more information on DICOM, visit the NEMA (National Electrical Manufacturer's Association) website at .B http://dicom.nema.org and also see David Clunie's excellent website on medical image formats at .B http://www.dclunie.com Many manufacturers create "DICOM Conformance Statements" for each software release associated with their medical imaging products. These can be useful sources of information. .SH "COPYRIGHTS" Copyrights 1993-2005 by Peter Neelin for the Montreal Neurological Institute. minc-2.2.00/conversion/dcm2mnc/dcm2mnc.c0000644000265600003100000010202412027132660014634 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dcm2mnc.c @DESCRIPTION: Program to convert dicom files to minc @GLOBALS : @CREATED : June 2001 (Rick Hoge) @MODIFIED : * $Log: dcm2mnc.c,v $ * Revision 1.24 2010-11-23 23:30:50 claude * dcm2mnc: fixed seg fault bug (Claude) and added b-matrix (Ilana) * * Revision 1.23 2008-08-12 05:00:23 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 1.22 2008/01/17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 1.21 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 1.20 2007/05/30 15:17:34 ilana * fix so that diffusion images all written into 1 4d volume, gradient directions and bvalues are written to mincheader, some fixes for TIM diffusion images * * Revision 1.19 2005/11/11 18:42:54 bert * Latest fixes to dcm2mnc * * Revision 1.18 2005/11/04 22:25:04 bert * Update version string to 2.0.07 * * Revision 1.17 2005/08/26 21:25:54 bert * Latest changes ported from 1.0 branch * * Revision 1.14.2.10 2005/08/18 18:17:36 bert * Add -usecoordinates option * * Revision 1.14.2.9 2005/07/22 20:03:16 bert * Minor change to consider sequence name when finding series boundaries * * Revision 1.14.2.8 2005/07/12 16:01:14 bert * Sort on filename if all else fails * * Revision 1.14.2.7 2005/06/20 22:03:31 bert * Add simple test for binary files to avoid choking on text files * * Revision 1.14.2.6 2005/06/09 20:48:36 bert * Remove obsolete -descr option, add shiny new -fname and -dname options. Also don't explicitly include math.h * * Revision 1.14.2.5 2005/06/02 18:35:32 bert * Change version to 2.0.06 * * Revision 1.14.2.4 2005/05/16 22:39:56 bert * Insert conditionals to make the file build properly under Windows * * Revision 1.14.2.3 2005/05/16 19:55:50 bert * Fix usage of G.command_line * * Revision 1.14.2.2 2005/05/16 19:45:52 bert * Minor fix to argument structure, to reflect correct usage of ARGV_STRING items * * Revision 1.14.2.1 2005/05/12 21:16:47 bert * Initial checkin * * Revision 1.14 2005/05/09 15:32:02 bert * Change version to 2.0.05 * * Revision 1.13 2005/04/29 23:09:36 bert * Add support for -stdin option to read file list from standard input * * Revision 1.12 2005/04/26 23:49:24 bert * Update version * * Revision 1.11 2005/04/18 16:38:42 bert * Fix up file type detection code * * Revision 1.10 2005/04/06 13:26:41 bert * Fix listing option * * Revision 1.9 2005/04/05 21:52:24 bert * Add -minmax option to enable use of explicit DICOM pixel min/max information, and updated version number * * Revision 1.8 2005/03/18 19:10:31 bert * Scan coordinate and location information for validity before relying on it * * Revision 1.7 2005/03/15 17:03:34 bert * Yet another directory expansion fix (sigh) * * Revision 1.6 2005/03/14 22:51:33 bert * Actually get the directory expansion working properly... * * Revision 1.5 2005/03/14 22:25:41 bert * If a directory is specified on the file list, expand it internally. This gets around shell limitations. * * Revision 1.4 2005/03/03 20:10:14 bert * Consider patient_id and patient_name when sorting into series * * Revision 1.3 2005/03/03 18:59:15 bert * Fix handling of image position so that we work with the older field (0020, 0030) as well as the new (0020, 0032) * * Revision 1.2 2005/03/02 18:23:32 bert * Added mosaic sequence and bitwise options * * Revision 1.1 2005/02/17 16:38:09 bert * Initial checkin, revised DICOM to MINC converter * * Revision 1.1.1.1 2003/08/15 19:52:55 leili * Leili's dicom server for sonata * * Revision 1.5 2002/04/26 12:02:50 rhoge * updated usage statement for new forking defaults * * Revision 1.4 2002/04/26 11:32:48 rhoge * made forking default * * Revision 1.3 2002/03/23 13:17:53 rhoge * added support for Bourget network pushed dicom files, cleaned up * file check and read_numa4_dicom vr check/assignment * * Revision 1.2 2002/03/22 19:19:36 rhoge * Numerous fixes - * - handle Numaris 4 Dicom patient name * - option to cleanup input files * - command option * - list-only option * - debug mode * - user supplied name, idstr * - anonymization * * Revision 1.1 2002/03/22 03:50:02 rhoge * new name for standalone dicom to minc converter * * Revision 1.3 2002/03/22 00:38:08 rhoge * Added progress bar, wait for children at end, updated feedback statements * * Revision 1.2 2002/03/19 13:13:56 rhoge * initial working mosaic support - I think time is scrambled though. * * Revision 1.1 2001/12/31 17:26:21 rhoge * adding file to repository- compiles without warning and converts non-mosaic * Numa 4 files. * Will probably not work for Numa 3 files yet. * ---------------------------------------------------------------------------- */ #define GLOBAL_ELEMENT_DEFINITION /* To define elements */ #include "dcm2mnc.h" #include #if HAVE_DIRENT_H #include #endif #include /* Function Prototypes */ static int dcm_sort_function(const void *entry1, const void *entry2); static void use_the_files(int num_files, Data_Object_Info *data_info[], const char *out_dir); static void usage(void); static void free_list(int num_files, const char **file_list, Data_Object_Info **file_info_list); static int check_file_type_consistency(int num_files, const char *file_list[]); struct globals G; #define VERSION_STRING "2.0.07 built " __DATE__ " " __TIME__ #ifndef S_ISDIR #define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) #endif #ifndef S_ISREG #define S_ISREG(x) (((x) & _S_IFMT) == _S_IFREG) #endif ArgvInfo argTable[] = { {NULL, ARGV_VERINFO, VERSION_STRING, NULL, NULL }, {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &G.clobber, "Overwrite output files"}, {"-list", ARGV_CONSTANT, (char *) TRUE, (char *) &G.List, "Print list of series (don't create files)"}, {"-anon", ARGV_CONSTANT, (char *) TRUE, (char *) &G.Anon, "Exclude subject name from file header"}, #if HAVE_POPEN {"-cmd", ARGV_STRING, (char *) 1, (char *) &G.command_line, "Apply to output files (e.g. gzip)"}, #endif {"-verbose", ARGV_CONSTANT, (char *) LO_LOGGING, (char *) &G.Debug, "Print debugging information"}, {"-debug", ARGV_CONSTANT, (char *) HI_LOGGING, (char *) &G.Debug, "Print lots of debugging information"}, {"-nosplitecho", ARGV_CONSTANT, (char *) FALSE, (char *) &G.splitEcho, "Combine all echoes into a single file."}, {"-splitdynamic", ARGV_CONSTANT, (char *) TRUE, (char *)&G.splitDynScan, "Split dynamic scans into a separate files."}, {"-opts", ARGV_INT, (char *) 1, (char *) &G.opts, "Set debugging options"}, {"-descending", ARGV_CONSTANT, (char *) MOSAIC_SEQ_DESCENDING, (char *) &G.mosaic_seq, "Mosaic sequence is in descending slice order."}, {"-interleaved", ARGV_CONSTANT, (char *) MOSAIC_SEQ_INTERLEAVED, (char *) &G.mosaic_seq, "Mosaic sequence is in interleaved slice order."}, {"-minmax", ARGV_CONSTANT, (char *)TRUE, (char *) &G.useMinMax, "Honor DICOM pixel minimum and pixel maximum values."}, {"-stdin", ARGV_CONSTANT, (char *)TRUE, (char *)&G.use_stdin, "Read file list from standard input."}, {"-fname", ARGV_STRING, (char *)1, (char *)&G.filename_format, "Set format for output file name."}, {"-dname", ARGV_STRING, (char *)1, (char *)&G.dirname_format, "Set format for output directory name."}, {"-usecoordinates", ARGV_CONSTANT, (char *) TRUE, (char *) &G.prefer_coords, "Derive step value from coordinates rather than slice spacing."}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char *argv[]) { int ifile; Acr_Group group_list; const char **file_list; /* List of file names */ Data_Object_Info **file_info_list; int num_file_args; /* Number of files on command line */ int num_files; /* Total number of files */ string_t out_dir; /* Output directory */ string_t message; /* Generic message */ int num_files_ok; /* Actual number of DICOM/IMA files */ struct stat st; int length; G.mosaic_seq = MOSAIC_SEQ_ASCENDING; /* Assume ascending by default. */ G.splitDynScan = FALSE; /* Don't split dynamic scans by default */ G.splitEcho = TRUE; /* Do split by echo by default */ G.use_stdin = FALSE; /* Do not read file list from stdin */ G.filename_format = NULL; G.dirname_format = NULL; G.minc_history = time_stamp(argc, argv); /* Create minc history string */ G.prefer_coords = FALSE; G.pname = argv[0]; /* get program name */ /* Get the input parameters and file names. */ if (ParseArgv(&argc, argv, argTable, 0)) { usage(); } if (argc < 2) { usage(); } if (G.List) { num_file_args = argc - 1; /* Assume no directory given. */ } else { num_file_args = argc - 2; /* Assume last arg is directory. */ strcpy(out_dir, argv[argc - 1]); /* make sure path ends with slash */ length = strlen(out_dir); if (out_dir[length - 1] != '/') { out_dir[length++] = '/'; out_dir[length++] = '\0'; } if (stat(out_dir, &st) != 0 || !S_ISDIR(st.st_mode)) { fprintf(stderr, "The final argument, '%s', is not a directory\n", out_dir); exit(EXIT_FAILURE); } } /* Get space for file lists */ /* Allocate the array of pointers used to implement the * list of filenames. */ file_list = malloc(1 * sizeof(char *)); CHKMEM(file_list); /* Go through the list of files, expanding directories where they * are encountered... */ num_files = 0; for (ifile = 0 ; ifile < num_file_args; ifile++) { #if HAVE_DIRENT_H if (stat(argv[ifile + 1], &st) == 0 && S_ISDIR(st.st_mode)) { DIR *dp; struct dirent *np; char *tmp_str; if (G.Debug) { printf("Expanding directory '%s'\n", argv[ifile + 1]); } length = strlen(argv[ifile + 1]); dp = opendir(argv[ifile + 1]); if (dp != NULL) { while ((np = readdir(dp)) != NULL) { /* Generate the full path to the file. */ tmp_str = malloc(length + strlen(np->d_name) + 2); strcpy(tmp_str, argv[ifile + 1]); if (tmp_str[length-1] != '/') { tmp_str[length] = '/'; tmp_str[length+1] = '\0'; } strcat(&tmp_str[length], np->d_name); if (stat(tmp_str, &st) == 0 && S_ISREG(st.st_mode)) { file_list = realloc(file_list, (num_files + 1) * sizeof(char *)); file_list[num_files++] = tmp_str; } else { free(tmp_str); } } closedir(dp); } else { fprintf(stderr, "Error opening directory '%s'\n", argv[ifile + 1]); } } else { file_list = realloc(file_list, (num_files + 1) * sizeof(char *)); file_list[num_files++] = strdup(argv[ifile + 1]); } #else file_list = realloc(file_list, (num_files + 1) * sizeof(char *)); file_list[num_files++] = strdup(argv[ifile + 1]); #endif } if (G.use_stdin) { char linebuf[1024]; char *p; while (fgets(linebuf, sizeof(linebuf), stdin) != NULL) { /* Strip off newline at end of string. */ for (p = linebuf; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; } } if (strlen(linebuf) != 0) { file_list = realloc(file_list, (num_files + 1) * sizeof(char *)); file_list[num_files++] = strdup(linebuf); } } } file_info_list = malloc(num_files * sizeof(*file_info_list)); CHKMEM(file_info_list); /* figure out what kind of files we have - * supported types are: * * IMA (Siemens .ima format - Numaris 3.5) * N4DCM (Siemens DICOM - Numaris 4) * * if not all same type, return an error * * we start by assuming N4DCM with no offset - we find that the * file is IMA or has an offset (the 128 byte + DICM offset seen * on Syngo CD's and exports) then the appropriate flag will be * set. */ printf("Checking file types...\n"); if (check_file_type_consistency(num_files, file_list) < 0) { exit(EXIT_FAILURE); } /* Now loop over all files, getting basic info on each */ num_files_ok = 0; for (ifile = 0; ifile < num_files; ifile++) { const char *cur_fname_ptr = file_list[ifile]; if (!G.Debug) { sprintf(message, "Parsing %d files", num_files); progress(ifile, num_files, message); } if (G.file_type == IMA) { group_list = siemens_to_dicom(cur_fname_ptr, ACR_IMAGE_GID - 1); } else { /* read up to but not including pixel data */ group_list = read_numa4_dicom(cur_fname_ptr, ACR_IMAGE_GID - 1); } if (group_list == NULL) { /* This file appears to be invalid - it is probably a dicomdir * file or some other stray junk in the directory. */ printf("Skipping file %s, which is not in the expected format.\n", cur_fname_ptr); free((void *) cur_fname_ptr); } else { /* Copy it back to the (possibly earlier) position in the real * file list. */ file_list[num_files_ok] = cur_fname_ptr; /* allocate space for the current entry to file_info_list */ file_info_list[num_files_ok] = malloc(sizeof(*file_info_list[0])); CHKMEM(file_info_list[num_files_ok]); file_info_list[num_files_ok]->file_index = num_files_ok; parse_dicom_groups(group_list, file_info_list[num_files_ok]); /* put the file name into the info list */ file_info_list[num_files_ok]->file_name = strdup(file_list[num_files_ok]); /* Delete the group list now that we're done with it */ acr_delete_group_list(group_list); num_files_ok++; } } /* end of loop over files to get basic info */ if (G.Debug) { printf("Using %d files\n", num_files_ok); } num_files = num_files_ok; printf("Sorting %d files... ", num_files); /* sort the files into series based on acquisition number */ qsort(file_info_list, num_files, sizeof(file_info_list[0]), dcm_sort_function); /* If DEBUG, print a list of all files. */ if (G.Debug) { printf("\n"); for (ifile = 0; ifile < num_files; ifile++) { Data_Object_Info *info = file_info_list[ifile]; char *fname; if ((ifile % 16) == 0) { printf("%-4s %-32.32s %-14s %-8s %-8s %-4s %-4s %-4s %-4s %-4s %-4s %-4s %-4s %-4s %-5s %-16s\n", "num", "filename", "studyid", "serialno", "acq", "nec", "iec", "ndy", "idy", "nsl", "isl", "acol", "rcol", "mrow", "img#", "seq"); } /* Print out info about file. Truncate the name if necessary. */ fname = info->file_name; if (strlen(fname) > 32) { fname += strlen(fname) - 32; } printf("%4d %-32.32s %14.6f %8d %8d %4d %4d %4d %4d %4d %4d %4d %4d %4d %5d %-16s\n", ifile, fname, info->study_id, info->scanner_serialno, info->acq_id, info->num_echoes, info->echo_number, info->num_dyn_scans, info->dyn_scan_number, info->num_slices_nominal, info->slice_number, info->acq_cols, info->rec_cols, info->num_mosaic_rows, info->global_image_number, info->sequence_name); } } printf("Done sorting files.\n"); /* Loop over files, processing by acquisition */ if (G.List) { printf("Listing files by series...\n"); } else { printf("Processing files, one series at a time...\n"); } use_the_files(num_files, file_info_list, out_dir); if (G.List) { printf("Done listing files.\n"); } else { printf("Done processing files.\n"); } free_list(num_files, file_list, file_info_list); free(file_list); free(file_info_list); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_list @INPUT : num_files - number of files in list file_list - array of file names @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Frees up things pointed to in pointer arrays. Does not free the arrays themselves. @METHOD : @GLOBALS : @CALLS : @CREATED : November 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void free_list(int num_files, const char **file_list, Data_Object_Info **file_info_list) { int i; for (i = 0; i < num_files; i++) { if (file_list[i] != NULL) { free((void *) file_list[i]); } if (file_info_list[i] != NULL) { free(file_info_list[i]->file_name); free(file_info_list[i]); } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : dcm_sort_function @INPUT : entry1 entry2 @OUTPUT : (none) @RETURNS : -1, 0, 1 for lt, eq, gt @DESCRIPTION: Function to compare two dcm series numbers @METHOD : @GLOBALS : @CALLS : @CREATED : June 2001 (Rick Hoge) @MODIFIED : ---------------------------------------------------------------------------- */ static int dcm_sort_function(const void *entry1, const void *entry2) { Data_Object_Info **file_info_list1 = (Data_Object_Info **) entry1; Data_Object_Info **file_info_list2 = (Data_Object_Info **) entry2; // make a sort-able session ID number: date.time double session1 = (*file_info_list1)->study_date + (*file_info_list1)->study_time / 1e6; double session2 = (*file_info_list2)->study_date + (*file_info_list2)->study_time / 1e6; // series index int series1 = (*file_info_list1)->acq_id; int series2 = (*file_info_list2)->acq_id; // frame index int frame1 = (*file_info_list1)->dyn_scan_number; int frame2 = (*file_info_list2)->dyn_scan_number; // image index int image1 = (*file_info_list1)->global_image_number; int image2 = (*file_info_list2)->global_image_number; int slice1 = (*file_info_list1)->slice_number; int slice2 = (*file_info_list2)->slice_number; if (session1 < session2) return -1; else if (session1 > session2) return 1; else if (series1 < series2) return -1; else if (series1 > series2) return 1; else if (frame1 < frame2) return -1; else if (frame1 > frame2) return 1; else if (image1 < image2) return -1; else if (image1 > image2) return 1; else if (slice1 < slice2) return -1; else if (slice1 > slice2) return 1; /* Last chance - if all else is equal, sort by the file names. */ else return strcmp((*file_info_list1)->file_name, (*file_info_list2)->file_name); } static void usage(void) { fprintf(stderr, "\nUsage: %s [options] file1 file2 file3 ... destdir\n", G.pname); fprintf(stderr, "\n"); fprintf(stderr,"Files are named according to the following convention:\n\n"); fprintf(stderr," Directory: lastname_firstname_yyyymmdd_hhmmss/\n"); fprintf(stderr," Files: lastname_firstname_yyyymmdd_hhmmss_series_modality.mnc\n\n"); exit(EXIT_FAILURE); } static void use_the_files(int num_files, Data_Object_Info *di_ptr[], const char *out_dir) { int ifile; int acq_num_files; const char **acq_file_list; int *used_file; int *acq_file_index; double cur_study_id; int cur_acq_id; int cur_rec_num; int cur_image_type; int cur_echo_number; int cur_dyn_scan_number; string_t cur_patient_name; string_t cur_patient_id; string_t cur_sequence_name; int exit_status; char *output_file_name; string_t file_prefix; string_t string; FILE *fp; int trust_location; int trust_coord; int user_opts; /* Options as set by user. We may override.. */ if (out_dir != NULL) { /* if an output directory name has been * provided on the command line */ if (G.Debug) { printf("Using directory '%s'\n", out_dir); } strcpy(file_prefix, out_dir); } else { file_prefix[0] = '\0'; } if (G.Debug) { /* debugging */ printf("file_prefix: [%s]\n", file_prefix); } /* Allocate space for acquisition file list. */ acq_file_list = malloc(num_files * sizeof(*acq_file_list)); CHKMEM(acq_file_list); acq_file_index = malloc(num_files * sizeof(*acq_file_index)); CHKMEM(acq_file_index); used_file = malloc(num_files * sizeof(*used_file)); CHKMEM(used_file); for (ifile = 0; ifile < num_files; ifile++) { used_file[ifile] = FALSE; } for (;;) { /* Loop through files, looking for an acquisition * * file groups should already have been sorted into acquisitions * in calling program * * this code is in a `forever' loop because we loop over multiple * acquisitions until all of the files are used up. */ acq_num_files = 0; for (ifile = 0; ifile < num_files; ifile++) { /* If already marked used (can this happen???), we've already * written the file to an output somewhere. */ if (used_file[ifile]) { continue; } if (acq_num_files == 0) { /* found first file: set all current attributes like * study id, acq id, rec num(?), image type, echo * number, dyn scan number, flag for multiple echoes, * flag for multiple time points the flag input file * as `used' */ cur_study_id = di_ptr[ifile]->study_id; cur_acq_id = di_ptr[ifile]->acq_id; cur_rec_num = di_ptr[ifile]->rec_num; cur_image_type = di_ptr[ifile]->image_type; cur_echo_number = di_ptr[ifile]->echo_number; cur_dyn_scan_number = di_ptr[ifile]->dyn_scan_number; strcpy(cur_patient_name, di_ptr[ifile]->patient_name); strcpy(cur_patient_id, di_ptr[ifile]->patient_id); strcpy(cur_sequence_name, di_ptr[ifile]->sequence_name); used_file[ifile] = TRUE; } /* otherwise check if attributes of the new input file match those * of the current output context and flag input file as `used' */ else if ((di_ptr[ifile]->study_id == cur_study_id) && (di_ptr[ifile]->acq_id == cur_acq_id) && (di_ptr[ifile]->rec_num == cur_rec_num) && (di_ptr[ifile]->image_type == cur_image_type) && (di_ptr[ifile]->echo_number == cur_echo_number || !G.splitEcho) && (di_ptr[ifile]->dyn_scan_number == cur_dyn_scan_number || !G.splitDynScan) && !strcmp(cur_patient_name, di_ptr[ifile]->patient_name) && !strcmp(cur_patient_id, di_ptr[ifile]->patient_id) && !strcmp(cur_sequence_name, di_ptr[ifile]->sequence_name)) { used_file[ifile] = TRUE; } if (used_file[ifile]) { /* if input file is flagged as `used', then add its index to the list of files for this acquisition (and increment counter) */ acq_file_list[acq_num_files] = di_ptr[ifile]->file_name; acq_file_index[acq_num_files] = ifile; acq_num_files++; } } /* If no files were added to this acquisition, it implies that * all files have been processed. */ if (acq_num_files == 0) { break; /* All done!!! */ } /* Use the files for this acquisition */ /* Print out the file names if we are debugging. */ if (G.Debug || G.List) { printf("\nSeries %4d %20s %20s (%4d files):\n", cur_acq_id, cur_patient_name, di_ptr[acq_file_index[0]]->protocol_name, acq_num_files); for (ifile = 0; ifile < acq_num_files; ifile++) { printf(" %s\n", di_ptr[acq_file_index[ifile]]->file_name); } if (G.List) { continue; } } /* Do some sanity checks on the acquisition. In particular, we * verify that the coordinate and/or slice location information * looks reliable. */ trust_location = 1; trust_coord = 1; for (ifile = 0; ifile < acq_num_files; ifile++) { int jfile; int ix = acq_file_index[ifile]; if (!di_ptr[ix]->coord_found) { trust_coord = 0; } for (jfile = ifile + 1; jfile < acq_num_files; jfile++) { int jx = acq_file_index[jfile]; if (NEARLY_EQUAL(di_ptr[ix]->slice_location, di_ptr[jx]->slice_location)) { trust_location = 0; } } } user_opts = G.opts; if (!trust_coord) { printf("WARNING: Image coordinates absent or incomplete.\n"); if (!trust_location) { printf("WARNING: Slice location is untrustworthy.\n"); G.opts |= OPTS_NO_LOCATION; } } /* Create minc file */ exit_status = dicom_to_minc(acq_num_files, acq_file_list, NULL, G.clobber, file_prefix, &output_file_name); G.opts = user_opts; if (exit_status != EXIT_SUCCESS) continue; /* Print log message */ if (G.Debug) { printf("Created minc file %s.\n", output_file_name); } #if HAVE_POPEN /* Invoke a command on the file (if requested) and get the * returned file name */ if (G.command_line != NULL && *G.command_line != '\0') { sprintf(string, "%s %s", G.command_line, output_file_name); printf("-Applying command '%s' to output file... ", G.command_line); fflush(stdout); if ((fp = popen(string, "r")) != NULL) { fscanf(fp, "%s", output_file_name); if (pclose(fp) != EXIT_SUCCESS) { fprintf(stderr, "Error executing command\n \"%s\"\n", string); } else if (G.Debug) { printf("Executed command \"%s\",\nproducing file %s.\n", string, output_file_name); } } else { fprintf(stderr, "Error executing command \"%s\"\n", string); } printf("Done.\n"); } #endif /* HAVE_POPEN */ } /* Free acquisition file list */ free(acq_file_list); free(acq_file_index); free(used_file); } static int is_cdexport_file(const char *fullname) { FILE *fp; char tst_str[DICM_MAGIC_SIZE+1]; int result = 0; if ((fp = fopen(fullname, "rb")) == NULL) { fprintf(stderr, "Error opening file %s!\n", fullname); } else { fseek(fp, DICM_MAGIC_OFFS, SEEK_SET); fread(tst_str, 1, DICM_MAGIC_SIZE, fp); tst_str[DICM_MAGIC_SIZE] = '\0'; if (!strcmp(tst_str, DICM_MAGIC_STR)) { result = 1; } fclose(fp); } return (result); } static int is_ima_file(const char *fullname) { FILE *fp; char mfg_str[IMA_MAGIC_SIZE+1]; int result = 0; if ((fp = fopen(fullname, "rb")) == NULL) { fprintf(stderr, "Error opening file %s!\n", fullname); } else { fseek(fp, IMA_MAGIC_OFFS, SEEK_SET); fread(mfg_str, 1, IMA_MAGIC_SIZE, fp); /* We only deal with Siemens IMA files - not sure any other kinds * exist, frankly. */ if (!memcmp(mfg_str, IMA_MAGIC_STR, IMA_MAGIC_SIZE)) { result = 1; } fclose(fp); } return (result); } /* _very_ limited test for "binary-ness" of a file. This is just to keep * text files and other junk present in a directory from screwing up our * file type detection. */ static int is_binary_file(const char *fullname) { FILE *fp; int result = 0; int i; if ((fp = fopen(fullname, "rb")) == NULL) { fprintf(stderr, "Error opening file %s!\n", fullname); } else { /* This is an extremely trivial test for binary-ness. Basically, we * look at the first 512 bytes, and if there aren't lots of unprintable * characters, we assume it is not a binary file. */ for (i = 0; i < 128; i++) { int cc = getc(fp); if (cc == -1) { result = 0; /* too short!! */ break; } if (!isprint(cc) && cc != '\n' && cc != '\r') { result++; } } fclose(fp); } return (result > 3); /* Binary if more than 3 unprintables */ } static int check_file_type_consistency(int num_files, const char *file_list[]) { int i; const char *fn_ptr; int n4_offset = 0; for (i = 0; i < num_files; i++) { fn_ptr = file_list[i]; /* Numaris 4 DICOM CD/Export file? if so, bytes 128-131 will * contain the string `DICM' with no null termination. */ if (is_cdexport_file(fn_ptr)) { if (G.file_type == UNDEF) { G.file_type = N4DCM; n4_offset = 1; printf("File %s appears to be DICOM (CD/Export).\n", fn_ptr); } else if (G.file_type != N4DCM || n4_offset != 1) { printf("MISMATCH: File %s appears to be DICOM (CD/Export).\n", fn_ptr); return (-1); } } else if (is_ima_file(fn_ptr)) { if (G.file_type == UNDEF) { G.file_type = IMA; printf("File %s appears to be Siemens IMA.\n", fn_ptr); } else if (G.file_type != IMA) { printf("MISMATCH: File %s appears to be Siemens IMA.\n", fn_ptr); return (-1); } } else if (is_binary_file(fn_ptr)) { if (G.file_type == UNDEF) { G.file_type = N4DCM; n4_offset = 0; printf("File %s appears to be standard DICOM.\n", fn_ptr); } else if (G.file_type != N4DCM || n4_offset != 0) { printf("MISMATCH: File %s appears to be standard DICOM.\n", fn_ptr); return (-1); } } } return (0); } /* compare two floating-point numbers */ int fcmp(double x, double y, double delta) { return ((fabs(x - y) / ((x == 0.0) ? 1.0 : fabs(x))) < delta); } minc-2.2.00/conversion/dcm2mnc/dicom_to_minc.c0000644000265600003100000033055512030075003016117 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_to_minc.c @DESCRIPTION: Code to convert a list of DICOM files to minc format. @METHOD : @GLOBALS : @CALLS : @CREATED : January 28, 1997 (Peter Neelin) @MODIFIED : * $Log: dicom_to_minc.c,v $ * Revision 1.30 2010-11-23 23:30:50 claude * dcm2mnc: fixed seg fault bug (Claude) and added b-matrix (Ilana) * * Revision 1.29 2010-06-23 13:21:05 rotor * * changed H5Acreate2 calls back to the H5Acreate macro * * Revision 1.28 2008/08/12 05:00:23 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 1.27 2008/01/17 06:20:54 stever * * conversion/dcm2mnc/dicom_to_minc.c (copy_element_properties): * Change return type from int to void; no callers require a return value. * * * conversion/micropet/upet2mnc.c (main): Return 0 at end of function. * * Revision 1.26 2008/01/17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 1.25 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 1.24 2008/01/11 07:17:07 stever * Remove unused variables. * * Revision 1.23 2007/11/23 20:28:23 ilana * condition on picking between DICOM slice spacing and coordinate spacing was wrong (extra ! in if statement) * * Revision 1.22 2007/08/13 16:34:52 ilana * mods to handle naming scheme of more diffusion sequences * * Revision 1.21 2007/06/08 20:28:57 ilana * added several fields to mincheader (dicom elements and found in ASCONV header) * * Revision 1.20 2007/05/30 15:17:34 ilana * fix so that diffusion images all written into 1 4d volume, gradient directions and bvalues are written to mincheader, some fixes for TIM diffusion images * * Revision 1.19 2006/05/11 14:45:14 bert * Fix endian-ness issues when parsing Siemens proprietary fields * * Revision 1.18 2006/04/09 15:39:04 bert * Improve support for DTI * * Revision 1.17 2006/02/09 20:54:29 bert * More changes to dcm2mnc * * Revision 1.16 2005/12/13 17:31:13 bert * Ignore DICOM protocol errors. This change was necessitated by images from a Philips Intera scanner version 'NT 10.4.1\\PIIM V2.1.4.1 MIMIT MCS' that appears to set the DICOM length field incorrectly. * * Revision 1.15 2005/08/26 21:25:54 bert * Latest changes ported from 1.0 branch * * Revision 1.13.2.5 2005/08/18 18:18:35 bert * Implement the -usecoordinates option, also some minor cleanup and fixes for some warning messages. * * Revision 1.13.2.4 2005/08/18 16:38:44 bert * Minor updates for dealing w/older numaris data * * Revision 1.13.2.3 2005/07/14 16:47:55 bert * Handle additional classes of Numa3 mosaics by using the Siemens 'base raw matrix size' element * * Revision 1.13.2.2 2005/06/20 22:01:15 bert * Add basic support for multiframe DICOM images * * Revision 1.13.2.1 2005/05/12 21:16:47 bert * Initial checkin * * Revision 1.13 2005/05/09 15:33:20 bert * Fix handing of descending mosaic sequences; don't print GEMS field missing warnings by default * * Revision 1.12 2005/04/28 17:38:06 bert * Insert and retrieve width information when sorting a dimension * * Revision 1.11 2005/04/21 22:31:29 bert * Copy SPI_Magnetic_field_strength to standard field in copy_spi_to_acr(); Relax some tests to avoid spurious warnings * * Revision 1.10 2005/04/20 23:25:50 bert * Add copy_spi_to_acr() function, minor name and comment changes * * Revision 1.9 2005/04/20 17:48:16 bert * Copy SPI_Number_of_slices_nominal to ACR_Image_in_acquisition for Siemens * * Revision 1.8 2005/04/18 21:04:25 bert * Get rid of old is_reversed behavior, always use most natural sort of the image. Also tried to fix listing function somewhat. * * Revision 1.7 2005/04/05 21:55:33 bert * Update handling of Siemens ASCCONV to reflect value of uc2DInterpolation field for mosaic images. Additional cleanup of mosaic code and minor tweak to suppress GEMS warning message for PET data. * * Revision 1.6 2005/03/29 20:20:42 bert * Add checks for GE Medical Systems proprietary files * * Revision 1.5 2005/03/14 22:26:40 bert * Dump the entire coordinate array for each MRI dimension after sorting. Also detect GE scans. * * Revision 1.4 2005/03/13 19:35:11 bert * Lots of changes for dealing with some proprietary Philips stuff * * Revision 1.3 2005/03/03 18:59:15 bert * Fix handling of image position so that we work with the older field (0020, 0030) as well as the new (0020, 0032) * * Revision 1.2 2005/03/02 20:16:24 bert * Latest changes and cleanup * * Revision 1.1 2005/02/17 16:38:10 bert * Initial checkin, revised DICOM to MINC converter * * Revision 1.1.1.1 2003/08/15 19:52:55 leili * Leili's dicom server for sonata * * Revision 1.18 2002/09/26 15:24:33 rhoge * Before was only skipping time sort for multi-slice N4 mosaics. Turns out * this was also causing failure on single-slice scans. * Changed slices>1 to slices>0 so that now N4 dicom scans never get sorted * on their (apparently nonsensical) time value. The if statement should * really be reworked, and should keep an eye on this. Seems like EPI * time series sequences never sort properly on 'time'. * * Revision 1.17 2002/09/25 17:25:43 rhoge * changed public void's to public int's * * Revision 1.16 2002/05/08 19:32:40 rhoge * fixed handling of diffusion scans with separate series for each average * * Revision 1.15 2002/05/01 21:29:34 rhoge * removed MrProt from minc header - encountered files with large strings, * causing seg faults * * Revision 1.14 2002/04/30 12:36:35 rhoge * fixes to handle current (and hopefully final) diffusion sequence * * Revision 1.13 2002/04/26 03:27:03 rhoge * fixed MrProt problem - replaced fixed lenght char array with malloc * * Revision 1.12 2002/04/08 03:40:56 rhoge * fixed mosaic extraction for non-square scans and 3D scans. * added some new dicom elements * * Revision 1.11 2002/03/27 19:38:08 rhoge * small comment change * * Revision 1.10 2002/03/27 18:57:50 rhoge * added diffusion b value * * Revision 1.9 2002/03/23 13:17:53 rhoge * added support for Bourget network pushed dicom files, cleaned up * file check and read_numa4_dicom vr check/assignment * * Revision 1.8 2002/03/22 19:19:36 rhoge * Numerous fixes - * - handle Numaris 4 Dicom patient name * - option to cleanup input files * - command option * - list-only option * - debug mode * - user supplied name, idstr * - anonymization * * Revision 1.7 2002/03/21 13:31:56 rhoge * updated comments * * Revision 1.6 2002/03/19 22:10:16 rhoge * removed time sorting for N4DCM mosaics - time is random for mosaics * * Revision 1.5 2002/03/19 13:13:56 rhoge * initial working mosaic support - I think time is scrambled though. * * Revision 1.4 2001/12/31 18:27:21 rhoge * modifications for dicomreader processing of Numaris 4 dicom files - at * this point code compiles without warning, but does not deal with * mosaiced files. Also will probably not work at this time for Numaris * 3 .ima files. dicomserver may also not be functional... * * Revision 1.3 2000/12/14 21:37:11 rhoge * log message cleanup * * Revision 1.2 2000/12/14 21:36:22 rhoge * changes to restore measurement loop support that was broken by changes * to provide acquisition loop support * * Revision 1.1.1.1 2000/11/30 02:13:15 rhoge * imported sources to CVS repository on amoeba * -now support Siemens acquisition loop scans with and without correction * on sending side * * Revision 6.1 1999/10/29 17:51:59 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:27 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:26 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:20 neelin * Release of minc version 0.4 * * Revision 1.1 1997/03/04 20:56:47 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "dcm2mnc.h" const char *World_Names[WORLD_NDIMS] = { "X", "Y", "Z" }; const char *Volume_Names[VOL_NDIMS] = { "Slice", "Row", "Column" }; const char *Mri_Names[MRI_NDIMS] = {"Slice", "Echo", "Time", "Phase", "ChmSh"}; /* Private structure definitions. */ /* multi-image (mosaic) info */ typedef struct { int packed; mosaic_seq_t mosaic_seq; int size[2]; int big[2]; int grid[2]; int pixel_size; Acr_Element big_image; Acr_Element small_image; int sub_images; int slice_count; double normal[WORLD_NDIMS]; double step[WORLD_NDIMS]; double position[WORLD_NDIMS]; } Mosaic_Info; /* DICOM Multiframe information. NOTE: This represents at best a very * partial implementation of the DICOM multiframe specification, barely * adequate for conversion of basic 3D files. More work is needed to * support dynamic scans and other more complex objects. */ typedef struct { int frame_count; int frame_size; Acr_Element big_image; Acr_Element sub_image; double normal[WORLD_NDIMS]; double step[WORLD_NDIMS]; double position[WORLD_NDIMS]; } Multiframe_Info; /* For dicom_to_minc(), these codes specify whether we are dealing * with a "normal" DICOM sequence, a Siemens mosaic sequence, or a * DICOM multiframe sequence. */ #define SUBIMAGE_TYPE_NONE 0 #define SUBIMAGE_TYPE_MOSAIC 1 #define SUBIMAGE_TYPE_MULTIFRAME 2 /* Structure for sorting dimensions */ typedef struct { int identifier; int original_index; double value; double width; } Sort_Element; /* Private function definitions */ static int mosaic_init(Acr_Group, Mosaic_Info *, int); static void mosaic_cleanup(Mosaic_Info *); static int mosaic_insert_subframe(Acr_Group, Mosaic_Info *, int, int); /* DICOM Multiframe conversion functions (see NOTE: above) */ static void multiframe_init(Acr_Group, Multiframe_Info *, int); static void multiframe_cleanup(Multiframe_Info *); static void multiframe_insert_subframe(Acr_Group, Multiframe_Info *, int, int); static void free_info(General_Info *gi_ptr, File_Info *fi_ptr, int num_files); static int dimension_sort_function(const void *v1, const void *v2); static void sort_dimensions(General_Info *gi_ptr); static int prot_find_string(Acr_Element Protocol, const char *name, char *value); static char *dump_protocol_text(Acr_Element Protocol); /* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_to_minc @INPUT : num_files - number of image files file_list - list of file names minc_file - name of minc file to create, or NULL to make one up. clobber - if TRUE, then open the output with NC_CLOBBER file_prefix - string providing any directory or prefix for internally generated filename (if it is a directory, then it must contain the last "/") @OUTPUT : output_file_name - returns a pointer to an internal area containing the file name of the created file if minc_file is NULL, or simply a pointer to minc_file. If NULL, then nothing is returned. @RETURNS : EXIT_SUCCESS if no error, EXIT_FAILURE on error. @DESCRIPTION: Routine to convert a list of Siemens dicom files to minc format. @METHOD : @GLOBALS : @CALLS : @CREATED : November 25, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int dicom_to_minc(int num_files, const char *file_list[], const char *minc_file, int clobber, const char *file_prefix, char **output_file_name) { Acr_Group group_list; /* List of ACR/NEMA groups & elements */ File_Info *fi_ptr; /* Array of per-file information */ General_Info gi; /* General (common) DICOM file information */ int max_group; /* Maximum group number to read */ Image_Data image; /* Actual image data */ int icvid; /* MINC Image Conversion Variable */ int ifile; /* File index */ Mri_Index imri; /* MRI axis index */ char *out_file_name; /* Output MINC filename */ int isep; /* Loop counter */ const Loop_Type loop_type = NONE; /* MINC loop type always none for now */ int subimage; /* Loop counter for MOSAIC images per file */ int iimage; /* Loop counter for all files/images */ int num_images; /* Total number of slices (>= # files) */ Mosaic_Info mi; /* Mosaic (multi-image) information */ Multiframe_Info mfi; /* Multiframe information */ int n_slices_in_file; /* Number of slices in file */ int subimage_type; /* Subimage type */ subimage_type = SUBIMAGE_TYPE_NONE; /* Allocate space for the file information */ fi_ptr = malloc(num_files * sizeof(*fi_ptr)); CHKMEM(fi_ptr); num_images = num_files; /* Last group needed for first pass */ max_group = ACR_IMAGE_GID - 1; /* Add all control characters as numeric array separators to handle * odd behaviour with Siemens dicom files */ for (isep = 0; isep < 31; isep++) { acr_element_numeric_array_separator(isep); } /* Initialize some values for general info */ gi.initialized = FALSE; gi.group_list = NULL; for (imri = 0; imri < MRI_NDIMS; imri++) { gi.cur_size[imri] = -1; gi.indices[imri] = NULL; gi.coordinates[imri] = NULL; gi.widths[imri] = NULL; } /* Loop through file list getting information * (note that we have to duplicate the handling * of multiple images per file in this loop * to accumulate dimension sizes correctly) * need separate counter for images, since some files may * contain more than one image! */ iimage = 0; for (ifile = 0; ifile < num_files; ifile++) { if (G.Debug >= HI_LOGGING) { printf("\nFile %s\n", file_list[ifile]); } if (!G.Debug) { progress(ifile, num_files, "-Parsing series info"); } /* Read the file */ if (G.file_type == N4DCM) { group_list = read_numa4_dicom(file_list[ifile], max_group); } else if (G.file_type == IMA) { group_list = siemens_to_dicom(file_list[ifile], max_group); } if (group_list == NULL) { fprintf(stderr, "Error parsing file '%s' on 1st pass.\n", file_list[ifile]); exit(-1); } if (G.opts & OPTS_NO_MOSAIC) { n_slices_in_file = 1; } else { n_slices_in_file = acr_find_int(group_list, EXT_Slices_in_file, 1); } /* initialize big and small images, if mosaic */ if (n_slices_in_file > 1) { subimage_type = SUBIMAGE_TYPE_MOSAIC; mosaic_init(group_list, &mi, FALSE); num_images += n_slices_in_file - 1; fi_ptr = realloc(fi_ptr, num_images * sizeof(*fi_ptr)); CHKMEM(fi_ptr); } else { /* See if we have an DICOM multiframe image, or at least a * reasonable facsimile of one such as the files produced * by the Shimadzu PET scanner. * * It is probably not correct to rely on the presence of the * "Number of Frames" (0x0028, 0x0008) field, but the Shimadzu * multiframe implementation is far from complete and does not * seem to implement any of the other components of the * specification. */ n_slices_in_file = acr_find_int(group_list, ACR_Number_of_frames, 1); if (n_slices_in_file > 1) { subimage_type = SUBIMAGE_TYPE_MULTIFRAME; multiframe_init(group_list, &mfi, FALSE); num_images += n_slices_in_file - 1; fi_ptr = realloc(fi_ptr, num_images * sizeof(*fi_ptr)); CHKMEM(fi_ptr); } } /* loop over subimages in mosaic */ for (subimage = 0; subimage < n_slices_in_file; subimage++) { /* Modify the group list for this image if mosaic or multiframe */ switch (subimage_type) { case SUBIMAGE_TYPE_MOSAIC: mosaic_insert_subframe(group_list, &mi, subimage, FALSE); break; case SUBIMAGE_TYPE_MULTIFRAME: multiframe_insert_subframe(group_list, &mfi, subimage, FALSE); break; default: break; } /* Get file-specific information */ get_file_info(group_list, &fi_ptr[iimage], &gi); //ilana debug /*int acq=acr_find_int(group_list, ACR_Acquisition, 1); printf("****WE HAVE ACQUISITION# %i",acq);*/ /* increment iimage here */ iimage++; } /* Delete the group list */ acr_delete_group_list(group_list); /* cleanup mosaic struct if used */ switch (subimage_type) { case SUBIMAGE_TYPE_MOSAIC: mosaic_cleanup(&mi); break; case SUBIMAGE_TYPE_MULTIFRAME: multiframe_cleanup(&mfi); break; default: break; } } /* Sort the dimensions */ sort_dimensions(&gi); /* Create the output file */ if (gi.initialized) { icvid = create_minc_file(minc_file, clobber, &gi, file_prefix, &out_file_name, loop_type); } if (output_file_name != NULL) { *output_file_name = out_file_name; } /* Check that we found the general info and that the minc file was * created okay */ if ((!gi.initialized) || (icvid == MI_ERROR)) { if (gi.initialized) { fprintf(stderr, "Error creating MINC file %s.\n", out_file_name); } free_info(&gi, fi_ptr, num_files); free(fi_ptr); return EXIT_FAILURE; } if (G.Debug) { printf("Writing %d images to MINC file\n", num_files); } /* Last group needed for second pass * we now have to read up to and including the image, * since image pointers are needed in mosaic_init */ max_group = ACR_IMAGE_GID; /* Loop through the files again and put images into the minc file */ iimage = 0; for (ifile = 0; ifile < num_files; ifile++) { if (!G.Debug) { progress(ifile, num_files, "-Creating minc file"); } /* Check that we have a valid file */ if (!fi_ptr[ifile].valid) { printf("WARNING: file %s was marked invalid\n", file_list[ifile]); continue; } /* Read the file */ if (G.file_type == N4DCM) { group_list = read_numa4_dicom(file_list[ifile], max_group); } else if (G.file_type == IMA) { group_list = siemens_to_dicom(file_list[ifile], max_group); } if (group_list == NULL) { fprintf(stderr, "Error parsing file '%s' during 2nd pass.\n", file_list[ifile]); exit(-1); } /* initialize big and small images, if mosaic */ switch (subimage_type) { case SUBIMAGE_TYPE_MOSAIC: mosaic_init(group_list, &mi, TRUE); break; case SUBIMAGE_TYPE_MULTIFRAME: multiframe_init(group_list, &mfi, TRUE); break; default: break; } /* loop over subimages in mosaic */ for (subimage = 0; subimage < n_slices_in_file; subimage++) { /* Modify the group list for this image if mosaic */ switch (subimage_type) { case SUBIMAGE_TYPE_MOSAIC: mosaic_insert_subframe(group_list, &mi, subimage, TRUE); break; case SUBIMAGE_TYPE_MULTIFRAME: multiframe_insert_subframe(group_list, &mfi, subimage, TRUE); break; default: break; } /* Get image */ get_dicom_image_data(group_list, &image); /* Save the image and any other information */ save_minc_image(icvid, &gi, &fi_ptr[iimage], &image); /* Free the image data */ if (image.data != NULL) { free(image.data); image.data = NULL; } /* increment image counter */ iimage++; } /* Delete the group list */ acr_delete_group_list(group_list); /* cleanup mosaic struct if used */ switch (subimage_type) { case SUBIMAGE_TYPE_MOSAIC: mosaic_cleanup(&mi); break; case SUBIMAGE_TYPE_MULTIFRAME: multiframe_cleanup(&mfi); break; default: break; } } /* Close the output file */ close_minc_file(icvid); /* Free the gi and fi_ptr stuff */ free_info(&gi, fi_ptr, num_files); free(fi_ptr); return EXIT_SUCCESS; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_std_dicom @INPUT : filename - name of siemens Numaris 4 `dicom' file to read max_group - maximum group number to read @OUTPUT : (none) @RETURNS : group list read in from file @DESCRIPTION: Routine to read in a group list from a file. @METHOD : @GLOBALS : @CALLS : @CREATED : December 18, 2001 (Rick Hoge) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group read_std_dicom(const char *filename, int max_group) { FILE *fp; Acr_File *afp; Acr_Group group_list; int status; /* Open the file */ fp = fopen(filename, "rb"); if (fp == NULL) { return NULL; } /* Connect to input stream */ afp = acr_file_initialize(fp, 0, acr_stdio_read); if (afp == NULL) { return NULL; } acr_set_ignore_errors(afp, 1); /* ignore protocol errors */ if (acr_test_dicom_file(afp) != ACR_OK) { return NULL; } // Read in group list status = acr_input_group_list(afp, &group_list, max_group); if (status != ACR_END_OF_INPUT && status != ACR_OK) { return NULL; } // Close the file acr_file_free(afp); fclose(fp); return (group_list); } /* Return non-zero if this image looks like it is a mosaic image. */ int is_siemens_mosaic(Acr_Group group_list) { Acr_String str_ptr; str_ptr = acr_find_string(group_list, ACR_Image_type, ""); if (strstr(str_ptr, "MOSAIC") != NULL) return 1; /* slam dunk, this is mosaic data */ /* For some reason, some Localizer scans look like MOSAICs in that * they appear to be upsampled in such a way that their * rows/columns are larger than the acquisition matrix. The * details of this are probably buried in the Siemens ASCCONV dump * and therefore I have not been able to figure out how to tweak * the MOSAIC stuff to get this right. Instead I am taking the * cheesy way out and declaring that anything that is NOT * explictly marked MOSAIC, and IS marked a localizer, should not * be treated as a mosaic. */ str_ptr = acr_find_string(group_list, ACR_Series_description, ""); if (strstr(str_ptr, "localizer") || strstr(str_ptr, "LOCALIZER")) { return 0; } /* OK, we did not find the word "mosaic" in the image type. But this * could still be a mosaic image. Let's look for some other clues. */ /*the SPI_Number_of_slices_nominal and SPI_Number_of_raw_partitions_nomimal are not always good fields with which to determine whether it's Mosaic or not, these fields often get set whether we have a mosaic image or not*/ /*if (acr_find_int(group_list, SPI_Number_of_slices_nominal, 0) > 1) return 1; */ /* probably mosaic. */ /*if (acr_find_int(group_list, SPI_Number_of_3D_raw_partitions_nominal, 0) > 1) return 1; */ /* probably mosaic */ return 0; /* probably not mosaic */ } #define MAXVM 32 Acr_Group parse_siemens_proto2(Acr_Group group_list, Acr_Element element) { int byte_cnt; int byte_pos; unsigned char *byte_ptr; Acr_Long n_items; Acr_Long n_values; Acr_Long vm; char vr[4]; Acr_Long syngodt; int i; char name[64]; char *value[MAXVM]; Acr_Long len; byte_cnt = element->data_length; byte_ptr = element->data_pointer; byte_pos = 0; /* See if the magic 8-byte header is present. If not, we start * right off with the number of elements. */ if (byte_ptr[0] == 'S' && byte_ptr[1] == 'V' && byte_ptr[2] == '1' && byte_ptr[3] == '0') { byte_pos += 8; /* Skip header */ } acr_get_long(ACR_LITTLE_ENDIAN, 1, byte_ptr + byte_pos, &n_items); byte_pos += 8; /* Skip # items and 4 bytes of unknown junk */ while (n_items-- > 0) { strncpy(name, (byte_ptr + byte_pos), 64); byte_pos += 64; acr_get_long(ACR_LITTLE_ENDIAN, 1, byte_ptr + byte_pos, &vm); byte_pos += 4; strncpy(vr, (byte_ptr + byte_pos), 4); byte_pos += 4; acr_get_long(ACR_LITTLE_ENDIAN, 1, byte_ptr + byte_pos, &syngodt); byte_pos += 4; acr_get_long(ACR_LITTLE_ENDIAN, 1, byte_ptr + byte_pos, &n_values); byte_pos += 4; byte_pos += 4; /* skip dummy */ if (n_values > 0) { for (i = 0; i < (int)n_values; i++) { byte_pos += 4; /* skip */ acr_get_long(ACR_LITTLE_ENDIAN, 1, byte_ptr + byte_pos, &len); byte_pos += 4; byte_pos += 8; if (i < vm && i < MAXVM) { value[i] = (byte_ptr + byte_pos); } byte_pos += ((len + 3) / 4) * 4; } } if (!strcmp(name, "DiffusionDirectionality")) { acr_insert_string(&group_list, ACR_Diffusion_directionality, value[0]); } else if (!strcmp(name, "B_value")) { /*double tmp = atof(value[0]); this atof makes the value null! ilana*/ Acr_Double tmp = atoi(value[0]); /*need a hack for ICBM scan, see below ilana*/ acr_insert_double(&group_list, ACR_Diffusion_b_value, 1, &tmp); } else if (!strcmp(name, "DiffusionGradientDirection")) { Acr_Double tmp[3]; if (vm == 3 && n_values >= vm) { /*For the ICBM WIP scan, the b0 images do not have B_value=0 or DiffusionGradientDirection=0 0 0, they actually have DiffusionGradientDirection=-1.00010000 -1.00010000 -1.00010000 Use this to detect the b=0 images and hopefully this doesn't ever correspond to a real gradient direction (have to change bvalues correspondingly)! ilana*/ if(!strcmp(value[0],"-1.00010000") && !strcmp(value[1],"-1.00010000") && !strcmp(value[2],"-1.00010000")){ value[0] = value[1] = value[2] = "0"; /*grad directions should be 0*/ Acr_Double tmp2 = atoi("0"); acr_insert_double(&group_list, ACR_Diffusion_b_value, 1, &tmp2); /*also have to modify B values ilana*/ } tmp[0] = atof(value[0]); tmp[1] = atof(value[1]); tmp[2] = -1*atof(value[2]); /*dicom z = -minc z ilana*/ acr_insert_double(&group_list, ACR_Diffusion_gradient_orientation, 3, tmp); } } #if 0 if (G.Debug >= HI_LOGGING) { printf("%s VM=%d VR=%s %d ", name, vm, vr, n_values); if (n_values != 0) { for (i = 0; i < vm && i < MAXVM; i++) { printf("%s ", value[i]); } } printf("\n"); } #endif } return (group_list); } static Acr_Group add_siemens_info(Acr_Group group_list) { /* needed for group repair - some essential info * only available in ascii dump of MrProt structure */ Acr_Element protocol; Acr_Element element; int num_slices, num_partitions; string_t str_buf; char *str_ptr=NULL; char *str_ptr2=NULL; int interpolation_flag; int enc_ix, num_encodings, num_b0; int EXT=0; /*special handling when an external diffusion vector file is used*/ element = acr_find_group_element(group_list, SPI_Protocol2); if (element != NULL) { group_list = parse_siemens_proto2(group_list, element); } /* now fix the group list to provide essential info * via standard dicom elements * (this lets the rest of the code be more reusable) * Note that these parameters are mostly dimension lengths, * and are not usually supplied in standard DICOM implementations. * We could do without them, except that the use of mosaics for * multi-slice data makes at least the number of slices necessary. * For such elements, we will spoof our own `private' entries * using Numaris 3.5 coordinates. These should not be used elsewhere * in the code unless there's no other way! Basically things * should be done as follows: * 1) use actual element in public dicom group, if possible * 2) if not, then get info from MrProt and insert as * correct public dicom element * 3) if no public element exists, use an SPI element (careful!) * 4) if no SPI element exists, use and EXT element (careful!) */ /* read in Protocol group */ protocol = acr_find_group_element(group_list, SPI_Protocol); if (protocol != NULL) { /* parse_siemens_junk(protocol); */ if (G.Debug >= HI_LOGGING) { printf("Incorporating Siemens protocol structure...\n"); } /* Add number of dynamic scans: */ prot_find_string(protocol, "lRepetitions", str_buf); if(atoi(str_buf)==0){ /*lRepetitions not found in ASCONV header*/ int frames = acr_find_int(group_list, ACR_Cardiac_number_of_images,0); /* this seems to give number of dynamic scans when lRepetitions not there*/ acr_insert_numeric(&group_list, ACR_Acquisitions_in_series, frames); } else { acr_insert_numeric(&group_list, ACR_Acquisitions_in_series, atoi(str_buf) + 1); } /* add number of echoes: */ prot_find_string(protocol, "lContrasts", str_buf); acr_insert_numeric(&group_list, SPI_Number_of_echoes, (double)atoi(str_buf)); /* Add receiving coil (for some reason this isn't in generic groups) */ prot_find_string(protocol, "sCOIL_SELECT_MEAS.asList[0].sCoilElementID.tCoilID", str_buf); /*Adjust for change in naming convention (VB15 VA30)*/ if(atoi(str_buf)==0){ prot_find_string(protocol, "sCoilSelectMeas[0].asList[0].sCoilElementID.tCoilID", str_buf); } acr_insert_string(&group_list, ACR_Receive_coil_name, str_buf); /* add MrProt dump */ str_ptr = dump_protocol_text(protocol); acr_insert_string(&group_list, EXT_MrProt_dump, (Acr_String)str_ptr); free(str_ptr); /* add number of slices: (called `Partitions' for 3D) */ prot_find_string(protocol, "sSliceArray.lSize", str_buf); num_slices = atoi(str_buf); prot_find_string(protocol, "sKSpace.lPartitions", str_buf); num_partitions = atoi(str_buf); /* This is a hack based upon the observation that for at least some * conversions, this value seems to give the true number of slices * rather than the sKSpace.lPartitions value (bert) */ prot_find_string(protocol, "sKSpace.lImagesPerSlab", str_buf); if (str_buf[0] != '\0') { int num_images_per_slab = atoi(str_buf); if (num_images_per_slab > num_partitions) { num_partitions = num_images_per_slab; } } /* NOTE: for some reason, lPartitions > 1 even for 2D scans * (e.g. EPI, scouts) */ if (!strncmp(acr_find_string(group_list, ACR_MR_acquisition_type,""), "3D", 2)) { /* Use partitions if 3D. * (note that this gets more complicated if the 3D scan * is mosaiced - see below) */ acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal, (double)1); acr_insert_numeric(&group_list, SPI_Number_of_3D_raw_partitions_nominal, (double)num_partitions); } else { /* use slices for 2D */ acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal, (double)num_slices); acr_insert_numeric(&group_list, SPI_Number_of_3D_raw_partitions_nominal, (double)1); } /* See if the field of view is set, if not, see if we can find * it in the ASCCONV dump and copy it into the proprietary * fields. */ if (acr_find_group_element(group_list, SPI_Field_of_view) == NULL) { /* TODO: This assumes a symmetric field of view. We need to * figure out what to do if this is not true!! */ prot_find_string(protocol, "sSliceArray.asSlice[0].sReadoutFOV", str_buf); if (str_buf[0] != '\0') { int fov = atoi(str_buf); sprintf(str_buf, "%d\\%d", fov, fov); acr_insert_string(&group_list, SPI_Field_of_view, str_buf); } } prot_find_string(protocol, "sKSpace.uc2DInterpolation", str_buf); interpolation_flag = strtol(str_buf, NULL, 0); /* find Delay time in TR in ASCONV header ilana */ prot_find_string(protocol, "lDelayTimeInTR", str_buf); acr_insert_numeric(&group_list, EXT_Delay_in_TR, (double)atol(str_buf)); /* Find slice acquisition mode in ASCONV header, can't seem to find is in a standard dicom field sSliceArray.ucMode takes on 3 values: 0x1 means ASCENDING 0x2 means DESCENDING 0x4 means INTERLEAVED */ prot_find_string(protocol, "sSliceArray.ucMode", str_buf); acr_insert_string(&group_list,EXT_Slice_order,str_buf); /*Modified by ilana to handle the common types of diffusion scans (ref: siemens_dicom_to_minc for dicomserver) /* correct dynamic scan info if *MGH* diffusion scan: * * assumptions: * * - diffusion protocol indicated by sDiffusion.ulMode = 0x100 * - bvalue is in sDiffusionalBValue[1] * - there are 10 b=0 scans and a user defined number of diffusion directions * - b=0 scans have sequence name "ep_b0#0, ep_b0#1... etc" * - encoded scans have seq names "ep_b1000#1, ep_b1000#2, ...,ep_b1300#1, ep_b1300#2, ..." etc. * * actions: * * - change number of dynamic scans to sDiffusion.lDiffDirections + num b0 images * - use sWiPMemBlock.alFree[8] for number of b=0 scans * - modify dynamic scan index to encoding index */ /* correct dynamic scan info if standard *ep2d_diff* diffusion scan * * assumptions: * * - diffusion protocol indicated by sDiffusion.ulMode = 0x100 * - bvalue is in sDiffusion.alBValue[0] * - there is 1 b=0 scans and 12 diffusion directions * - b=0 scan havs sequence name "ep_b0" * - encoded scans have seq names "ep_b1000#1, ep_b1000#2, ..." etc. * * actions: * * - change number of dynamic scans to sDiffusion.lDiffDirections + num b0 images * - modify dynamic scan index to encoding index */ /* correct dynamic scan info if standard *ICBM_WIP* diffusion scan * * assumptions: * * - diffusion protocol indicated by sDiffusion.ulMode = 0x80 * - bvalue is in sDiffusion.alBValue[1] * - there is 1 b=0 scans and user defined number of diffusion directions * - b=0 scan has sequence name "ep_b0" * - encoded scans have seq names "ep_b1000#1, ep_b1000#2, ..." etc. * * actions: * * - change number of dynamic scans to sDiffusion.lDiffDirections + num b0 images * - modify dynamic scan index to encoding index */ prot_find_string(protocol, "sDiffusion.ulMode", str_buf); if (!strcmp(str_buf, "0x100") | !strcmp(str_buf, "0x80")) { /*we have a diffusion scan; flag it*/ acr_insert_string(&group_list, ACR_Acquisition_contrast, "DIFFUSION"); /*----MGH-----*/ prot_find_string(protocol,"sWiPMemBlock.alFree[8]", str_buf); if ((atoi ((char*)str_buf))!= 0 ) { /*num b0 images for MGH sequence*/ /* get number of b=0 images*/ num_b0 = atoi ((char*)str_buf); /* try to get b value */ prot_find_string(protocol, "sDiffusion.alBValue[1]", str_buf); acr_insert_numeric(&group_list, EXT_Diffusion_b_value, (double)atoi(str_buf)); } else { prot_find_string(protocol, "sDiffusion.ulMode", str_buf); /*-----ep2d_diff-----OR----- ep2d_diff_WIP_ICBM with "Diffusion mode"=MDDW & DiffusionWeightings=2-----------*/ if (!strcmp(str_buf, "0x100")) { /* try to get b value */ prot_find_string(protocol, "sDiffusion.alBValue[1]", str_buf); acr_insert_numeric(&group_list, EXT_Diffusion_b_value, (double)atoi(str_buf)); num_b0=1; } /*-----ICBM_WIP with "Diffusion mode"=Free (5 b=0 scans) or any time an external vectors file is used-----*/ else if(!strcmp(str_buf, "0x80")) { EXT=1; /* try to get b value */ prot_find_string(protocol, "sDiffusion.alBValue[0]", str_buf); acr_insert_numeric(&group_list, EXT_Diffusion_b_value, (double)atoi(str_buf)); num_b0=0; /*For ICBM there are 5 b=0 scans but they are not identified any differently than the diffusion weighted images, sDiffusion.lDiffDirections includes the b=0 images. An external DiffusionVectors file can include other b=0 and this messes up the image count*/ } } /* if all averages in one series: */ prot_find_string(protocol,"ucDixon",str_buf); if (!strcmp(str_buf,"0x1")) { prot_find_string(protocol, "sDiffusion.lDiffDirections", str_buf); num_encodings = atoi ((char*)str_buf) + num_b0; /* number of 'time points' */ acr_insert_numeric(&group_list, ACR_Acquisitions_in_series, num_encodings * acr_find_double(group_list, ACR_Nr_of_averages, 1)); /* time index of current scan: */ /* For multi-series scans, we DO USE THIS BECAUSE global * image number may be broken!! */ /*Have to also take care of numbered b=0 images (ep_b0#0, etc...) ilana*/ /*the Siemems-based sequences, in MDDW mode with 2 diff weightings have b=0 images called ep_b0*/ str_ptr = strstr(acr_find_string(group_list, ACR_Sequence_name, ""), "b"); str_ptr2 = strstr(acr_find_string(group_list, ACR_Sequence_name, ""), "#"); if (str_ptr == NULL || str_ptr2 == NULL) { enc_ix = 0; } else if(atoi(str_ptr +1) == 0){ /*a 0 after the b means b=0 image*/ enc_ix = atoi(str_ptr2 + 1); } else{ enc_ix = atoi(str_ptr2 + 1) + num_b0; /*should be in diffusion weighted images now*/ } /* however with the current sequence, we get usable * time indices from floor(global_image_num/num_slices)*/ /*i'm not sure that works here*/ acr_insert_numeric(&group_list, ACR_Acquisition, (double)enc_ix); /*acr_insert_numeric(&group_list, ACR_Acquisition, (acr_find_int(group_list, ACR_Image, 1)-1) / num_slices);*/ } else { /* averages in different series - no special handling needed? */ prot_find_string(protocol, "sDiffusion.lDiffDirections", str_buf); num_encodings = atoi((char*)str_buf) + num_b0; //num_encodings = 7; /* for now assume 7 shots in diffusion scan */ /* number of 'time points' */ acr_insert_numeric(&group_list, ACR_Acquisitions_in_series, (double)num_encodings); /* For multi-series scans, we DO USE THIS BECAUSE global * image number may be broken!! */ /*Have to also take care of numbered b=0 images (ep_b0#0, etc...) ilana*/ str_ptr = strstr(acr_find_string(group_list, ACR_Sequence_name, ""), "b"); str_ptr2 = strstr(acr_find_string(group_list, ACR_Sequence_name, ""), "#"); if (str_ptr == NULL || str_ptr2 == NULL){ enc_ix = 0; } else if(atoi(str_ptr +1) == 0){ /*a 0 after the b means b=0 image*/ enc_ix = atoi(str_ptr2 + 1); } else{ enc_ix = atoi(str_ptr2 + 1) + num_b0; /*should be in diffusion weighted images now*/ } acr_insert_numeric(&group_list, ACR_Acquisition, (double)enc_ix); } if (EXT==1) { /*if an external DiffusionVectors was used, the encoding index can be wrong because it does not take into account b=0 images within the acquisition. Have to rely on ACR_Image 0020x0013 (but this field won't work for MGH sequence)*/ acr_insert_numeric(&group_list, ACR_Acquisition,acr_find_int(group_list, ACR_Image, 1) ); } /* BUG! TODO! FIXME! In dcm2mnc.c the sequence name is * used as one of the criteria for starting a new * file. For a DTI sequence, we don't want this to * happen. For now I replace the sequence name with a * bogus value in order to keep the DTI scan from being * split into pieces. This isn't right. We should deal * with this in a more graceful way. */ acr_insert_string(&group_list, ACR_Sequence_name, "DTI"); /* Reset acquisition time to series time plus the series * index. Otherwise each slice may get its own * time. This is also probably wrong and in the ideal * world we should deal with this gracefully. But we have * no good way of storing per-slice timing information * right now. */ acr_insert_numeric(&group_list, ACR_Acquisition_time, acr_find_double(group_list, ACR_Series_time, 0) + enc_ix); /* end of diffusion scan handling */ /* There is another whole class of (probably newer) diffusion * weighted images that use a very different arrangement and * need better handling. */ } } else { /* If no protocol dump was found we have to assume no * interpolation since at the momemnt I have no idea where it * would live... */ interpolation_flag = 0; num_partitions = acr_find_int(group_list, SPI_Number_of_3D_raw_partitions_nominal, 0); num_slices = acr_find_int(group_list, SPI_Number_of_slices_nominal, 0); } /* Handle mosaic images if necessary. */ if (is_siemens_mosaic(group_list)) { int mosaic_rows, mosaic_cols; Acr_Short subimage_size[4]; int subimage_rows, subimage_cols; /* Now figure out mosaic rows and columns, and put in EXT * shadow group. Check for interpolation - will require 2x * scaling of rows and columns. */ /* Assign defaults in case something goes wrong below... */ subimage_rows = subimage_cols = acr_find_int(group_list, SPI_Base_raw_matrix_size, 0); /* If we don't have an "SPI_Base_raw_matrix_size" field, try using * the acquisition matrix. */ if (subimage_rows == 0) { /* Compute mosaic rows and columns * Here is a hack to handle non-square mosaiced images * * WARNING: as far as I can tell, the phase-encoding dir (row/col) * is reversed for mosaic EPI scans (don't know if this is a * mosaic thing, an EPI thing, or whatever). * (Something is wrong here, it seems that it's not reversed, but * not sure obviously doesn't show up when the acquisition matrix is * square) * Get the array of sizes: freq row/freq col/phase row/phase col */ element = acr_find_group_element(group_list, ACR_Acquisition_matrix); if (element == NULL) { printf("WARNING: Can't find acquisition matrix\n"); } else if (acr_get_element_short_array(element, 4, subimage_size) != 4) { printf("WARNING: Can't read acquisition matrix\n"); } else { if (G.Debug >= HI_LOGGING) { printf(" * Acquisition matrix %d %d %d %d\n", subimage_size[0], subimage_size[1], subimage_size[2], subimage_size[3]); } /* Get subimage dimensions, assuming the OPPOSITE of the * reported phase-encode direction!! */ str_ptr = (char *)acr_find_string(group_list, ACR_Phase_encoding_direction, ""); if (!strncmp(str_ptr, "COL", 3)) { /*TODO test that this is right for non-square acquisition matrices*/ subimage_rows = subimage_size[3]; subimage_cols = subimage_size[0]; } else if (!strncmp(str_ptr, "ROW", 3)) { /*not sure the subimage dimensions should be opposite of * the phase encoding direction, running into some problems, * so changed it to be the same but I also might be breaking * for other cases!*/ /*subimage_rows = subimage_size[2]; subimage_cols = subimage_size[1];*/ subimage_rows = subimage_size[1]; subimage_cols = subimage_size[2]; } else { printf("WARNING: Unknown phase encoding direction '%s'\n", str_ptr); } /* If interpolation, multiply rows and columns by 2 */ if (interpolation_flag) { subimage_rows *= 2; subimage_cols *= 2; } } } /* If these are not set or still zero, assume this is NOT a mosaic * format file. */ if (subimage_rows == 0 || subimage_cols == 0) { subimage_rows = acr_find_int(group_list, ACR_Rows, 1); subimage_cols = acr_find_int(group_list, ACR_Columns, 1); mosaic_rows = 1; mosaic_cols = 1; } else { if (G.Debug >= HI_LOGGING) { printf("Assuming %dx%d mosaic\n", subimage_rows, subimage_cols); } mosaic_rows = acr_find_int(group_list, ACR_Rows, 1) / subimage_rows; mosaic_cols = acr_find_int(group_list, ACR_Columns, 1) / subimage_cols; } acr_insert_numeric(&group_list, EXT_Mosaic_rows, (double)mosaic_rows); acr_insert_numeric(&group_list, EXT_Mosaic_columns, (double)mosaic_cols); if (mosaic_rows * mosaic_cols > 1) { str_ptr = (char *)acr_find_string(group_list, ACR_MR_acquisition_type, ""); /* assume any mosaiced file contains all slices * (we now support mosaics for 2D and 3D acquisitions, * so we may need to use partitions instead of slices) */ if (!strncmp(str_ptr, "2D", 2)) { acr_insert_numeric(&group_list, EXT_Slices_in_file, (double)num_slices); acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal, (double)num_slices); } /* if 3D mosaiced scan, write number of partitions to number of * slices in dicom group */ else if (!strncmp(str_ptr, "3D", 2)) { acr_insert_numeric(&group_list, EXT_Slices_in_file, (double)num_partitions); acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal, (double)num_partitions); /* also have to provide slice spacing - in case of 3D it's same * as slice thickness (and not provided in dicom header!) */ acr_insert_numeric(&group_list, ACR_Spacing_between_slices, acr_find_double(group_list, ACR_Slice_thickness, 1.0)); } } else { acr_insert_numeric(&group_list, EXT_Slices_in_file, (double)1); } /* Correct the rows and columns values - * These will reflect those of the subimages in the mosaics * NOT the total image dimensions */ acr_insert_short(&group_list, EXT_Sub_image_columns, subimage_cols); acr_insert_short(&group_list, EXT_Sub_image_rows, subimage_rows); /* TODO: should also correct the image position here? */ } /* Hacks for specific numaris3 sequences. */ if (is_numaris3(group_list)) { int tmp; str_ptr = (char *)acr_find_string(group_list, ACR_Sequence_name, ""); /* This first hack is for Sebastian's Numaris-3 DTI scans. */ if (!strcmp(str_ptr, "ep_d33a ")) { /* Numaris-3 DTI scan. Individual scans are identified by * echo number. We need to change echos to time. */ tmp = acr_find_int(group_list, SPI_Number_of_echoes, 1); acr_insert_numeric(&group_list, SPI_Number_of_echoes, (double)1); element = acr_find_group_element(group_list, ACR_Acquisitions_in_series); if (element != NULL) { int grp_id = acr_get_element_group(element); int elm_id = acr_get_element_element(element); acr_group_remove_element(acr_find_group(group_list, grp_id), elm_id); } acr_insert_short(&group_list, ACR_Number_of_time_slices, tmp); tmp = acr_find_int(group_list, ACR_Echo_number, 0); acr_insert_numeric(&group_list, ACR_Echo_number, (double)1); acr_insert_numeric(&group_list, ACR_Frame_reference_time, (double)(tmp * 1000)); /* Just use defaults for these values. */ acr_insert_numeric(&group_list, ACR_Actual_frame_duration, (double)1000); } /* An additional hack required for Sebastian's Numaris-3 FMRI scans. */ if (!strcmp(str_ptr, "ep_fid")) { /* Numaris-3 FMRI scan. Each time slice uses a different * series number!! */ tmp = acr_find_int(group_list, ACR_Series_time, 0); acr_insert_numeric(&group_list, ACR_Series, (double)tmp); tmp = acr_find_int(group_list, ACR_Acquisitions_in_series, 0); acr_insert_short(&group_list, ACR_Number_of_time_slices, tmp); element = acr_find_group_element(group_list, ACR_Acquisitions_in_series); if (element != NULL) { int grp_id = acr_get_element_group(element); int elm_id = acr_get_element_element(element); acr_group_remove_element(acr_find_group(group_list, grp_id), elm_id); } } } return (group_list); } #define PMS_SET_CREATOR(el, cr) \ (el)->element_id = ((el)->element_id & 0xff) + ((cr)->element_id << 8) static Acr_Group add_philips_info(Acr_Group group_list) { struct Acr_Element_Id creator_id; Acr_Group pms_group; Acr_Element pms_element; Acr_Element pms_element_list; char *str_ptr; int slice_count; int slice_index; char str_buf[128]; /* To use the Philips proprietary group, we have to figure out the * DICOM private creator ID in use. The group ID is always 0x2001, * but the upper eight bits of the element ID are somewhat variable. * To tell what they are, we have to search through the element ID's * from 0x0001-0x00ff and find one that contains the text * "PHILIPS IMAGING DD 001" or "Philips Imaging DD 001". The value * of this element is then used for the upper eight bits of all * subsequent Philips private element ID's. */ pms_group = acr_find_group(group_list, PMS_PRIVATE_GROUP_ID); if (pms_group != NULL) { pms_element_list = acr_get_group_element_list(pms_group); creator_id.group_id = PMS_PRIVATE_GROUP_ID; creator_id.vr_code = ACR_VR_LO; for (creator_id.element_id = 0x0001; creator_id.element_id <= 0x00ff; creator_id.element_id++) { pms_element = acr_find_element_id(pms_element_list, &creator_id); if (pms_element != NULL) { str_ptr = (char *)acr_get_element_string(pms_element); if (str_ptr != NULL && (!strcmp(str_ptr, "Philips Imaging DD 001") || !strcmp(str_ptr, "PHILIPS IMAGING DD 001"))) { /* Found it!!! */ break; } } } } else { creator_id.element_id = 0; } if (creator_id.element_id > 0xff || creator_id.element_id < 0x01) { printf("WARNING: Can't find Philips private creator ID.\n"); /* OK, this may be an old Philips file with the SPI stuff in it. */ str_ptr = (char *)acr_find_string(group_list, SPI_PMS_grp19_tag, ""); if (!strncmp(str_ptr, "PHILIPS MR", 10)) { if (G.Debug >= HI_LOGGING) { printf("Found Philips SPI information\n"); } str_ptr = (char *)acr_find_string(group_list, ACR_Image_position_patient, ""); if (*str_ptr == '\0') { double x, y, z; x = (double)acr_find_double(group_list, SPI_PMS_lr_position2, 0); y = (double)acr_find_double(group_list, SPI_PMS_ap_position2, 0); z = (double)acr_find_double(group_list, SPI_PMS_cc_position2, 0); sprintf(str_buf, "%.15g\\%.15g\\%.15g", x, y, z); printf("New position: %s\n", str_buf); acr_insert_string(&group_list, ACR_Image_position_patient, (Acr_String)str_buf); } str_ptr = (char *)acr_find_string(group_list, ACR_Number_of_slices, ""); if (*str_ptr == '\0') { Acr_Short n; n = acr_find_short(group_list, SPI_PMS_slice_count, 0); acr_insert_short(&group_list, ACR_Number_of_slices, n); } str_ptr = (char*)acr_find_string(group_list, ACR_Image_orientation_patient, ""); if (strchr(str_ptr, '\\') == NULL) { int orientation = acr_find_int(group_list, SPI_PMS_slice_orientation, 1); switch (orientation) { case 1: /* transverse, slice=Z */ strcpy(str_buf, "1\\0\\0\\0\\1\\0"); break; case 2: /* sagittal, slice=X */ strcpy(str_buf, "0\\1\\0\\0\\0\\1"); break; case 3: /* coronal, slice=Y */ strcpy(str_buf, "1\\0\\0\\0\\0\\1"); break; } acr_insert_string(&group_list, ACR_Image_orientation_patient, str_buf); } #if 0 /* not clear that this is needed */ str_ptr = (char *)acr_find_string(group_list, ACR_Pixel_size, ""); if (*str_ptr == '\0') { pms_element = acr_find_group_element(group_list, SPI_PMS_field_of_view); if (pms_element != NULL) { double fov[2]; acr_get_element_numeric_array(pms_element, 2, fov); if (fov[0] != 0.0 && fov[1] != 0.0) { double derived_spacing[2]; int rows = acr_find_int(group_list, ACR_Rows, 1); int cols = acr_find_int(group_list, ACR_Columns, 1); derived_spacing[0] = fov[0] / cols; derived_spacing[1] = fov[1] / rows; sprintf(str_buf, "%.15g\\%.15g", derived_spacing[0], derived_spacing[1]); printf("PHILIPS: New pixel size %s\n", str_buf); acr_insert_string(&group_list, ACR_Pixel_size, str_buf); } } } #endif } } else { if (G.Debug >= HI_LOGGING) { printf("Found Philips private creator ID at %#x\n", creator_id.element_id); } PMS_SET_CREATOR(PMS_Number_of_Slices_MR, &creator_id); slice_count = acr_find_int(group_list, PMS_Number_of_Slices_MR, -1); if (slice_count < 0) { printf("WARNING: Can't find Philips slice count\n"); } else { acr_insert_short(&group_list, ACR_Images_in_acquisition, slice_count); } PMS_SET_CREATOR(PMS_Slice_Number_MR, &creator_id); slice_index = acr_find_int(group_list, PMS_Slice_Number_MR, -1); if (slice_index < 0) { printf("WARNING: Can't find Philips slice index\n"); } else { /* TODO: It is really quite gross that we have to resort to * using a Siemens-proprietary field to tell the rest of the * code which slice we are on. But such is life, for now... */ acr_insert_numeric(&group_list, SPI_Current_slice_number, (double) slice_index); } } return (group_list); } Acr_Group add_gems_info(Acr_Group group_list) { Acr_String tmp_str; int image_count; int image_index; double tr; int ok; ok = 1; tmp_str = acr_find_string(group_list, GEMS_Acqu_private_creator_id, ""); if (strcmp(tmp_str, "GEMS_ACQU_01")) { ok = 0; } tmp_str = acr_find_string(group_list, GEMS_Sers_private_creator_id, ""); if (strcmp(tmp_str, "GEMS_SERS_01")) { ok = 0; } if (!ok) { /* Warn only for non-PET things. We know the PET scanner doesn't * rely on this proprietary nonsense. */ tmp_str = acr_find_string(group_list, ACR_Modality, ""); if (strcmp(tmp_str, "PT") && G.Debug) { printf("WARNING: GEMS data not found\n"); } } tmp_str = acr_find_string(group_list, ACR_Image_type, ""); image_index = acr_find_int(group_list, ACR_Image, -1); image_count = acr_find_int(group_list, GEMS_Images_in_series, -1); tr = (double)acr_find_double(group_list, ACR_Repetition_time, 0.0); /* If we found a valid image count in the proprietary field, copy it * into the standard field if the standard field is not already set. */ if (image_count > 0 && acr_find_int(group_list, ACR_Images_in_acquisition, -1) < 0) { acr_insert_long(&group_list, ACR_Images_in_acquisition, image_count); } /* Do this only for EPI images for now */ if (strstr(tmp_str, "\\EPI") != NULL && image_index >= 0 && image_count > 0 && tr != 0.0) { int frame_count = acr_find_int(group_list, GEMS_Fast_phases, -1); if (frame_count > 0) { if (acr_find_int(group_list, ACR_Acquisitions_in_series, -1) < 0) { acr_insert_long(&group_list, ACR_Acquisitions_in_series, (Acr_Long)frame_count); } } if (acr_find_double(group_list, ACR_Frame_reference_time, -1.0) < 0) { acr_insert_numeric(&group_list, ACR_Frame_reference_time, (double)(((image_index - 1) / image_count) * tr) ); } if (acr_find_double(group_list, ACR_Actual_frame_duration, -1.0) < 0) { acr_insert_numeric(&group_list, ACR_Actual_frame_duration, tr); } if (G.Debug >= HI_LOGGING) { printf("EPI slice %d timing information: %f, %f\n", image_index, ((image_index - 1) / image_count) * tr, tr); } } return (group_list); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_spi_to_acr() @INPUT : group_list - read a standard DICOM file @OUTPUT : (none) @RETURNS : modified group list @DESCRIPTION: Routine to copy Siemens-specific (SPI) fields to generic ACR/NEMA fields. @METHOD : @GLOBALS : @CALLS : @CREATED : 2005 (Bert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group copy_spi_to_acr(Acr_Group group_list) { int itemp; double dtemp; itemp = acr_find_int(group_list, SPI_Number_of_slices_nominal, 0); if (itemp != 0) { acr_insert_numeric(&group_list, ACR_Images_in_acquisition, (double)itemp); } itemp = acr_find_int(group_list, SPI_Number_of_echoes, 0); if (itemp != 0) { acr_insert_numeric(&group_list, ACR_Echo_train_length, (double)itemp); } dtemp = (double)acr_find_double(group_list, SPI_Magnetic_field_strength, 0); if (dtemp != 0.0) { acr_insert_numeric(&group_list, ACR_Magnetic_field_strength, dtemp); } return (group_list); } Acr_Group add_shimadzu_info(Acr_Group group_list) { Acr_String str_ptr; /* TODO: Figure out what can be done here... */ str_ptr = acr_find_string(group_list, ACR_Series_instance_UID, ""); if (*str_ptr != '\0') { } return (group_list); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_numa4_dicom @INPUT : filename - read a standard DICOM file max_group - maximum group number to read @OUTPUT : (none) @RETURNS : group list read in from file @DESCRIPTION: Routine to read in a group list from a file. @METHOD : @GLOBALS : @CALLS : @CREATED : December 18, 2001 (Rick Hoge) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group read_numa4_dicom(const char *filename, int max_group) { Acr_Group group_list; Acr_String str_ptr; group_list = read_std_dicom(filename, max_group); if (group_list == NULL) { return NULL; } /* Check the manufacturer. If it is one we know, try to interpret * the private/proprietary data if present. This is converted to * standard DICOM fields whereever it makes sense to do so. */ str_ptr = acr_find_string(group_list, ACR_Manufacturer, ""); if (strstr(str_ptr, "SIEMENS") != NULL || strstr(str_ptr, "Siemens") != NULL) { group_list = add_siemens_info(group_list); /* Now copy proprietary fields into the correct places in the * standard groups. */ group_list = copy_spi_to_acr(group_list); } else if (strstr(str_ptr, "Philips") != NULL) { group_list = add_philips_info(group_list); } else if (strstr(str_ptr, "GEMS") != NULL || strstr(str_ptr, "GE MEDICAL") != NULL) { group_list = add_gems_info(group_list); } else if (strstr(str_ptr, "shimadzu") != NULL) { group_list = add_shimadzu_info(group_list); } return (group_list); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_info @INPUT : gi_ptr fi_ptr num_files @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to free contents of general and file info structures. @METHOD : @GLOBALS : @CALLS : @CREATED : November 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void free_info(General_Info *gi_ptr, File_Info *fi_ptr, int num_files) { Mri_Index imri; /* Free the general info pointers */ for (imri = 0; imri < MRI_NDIMS; imri++) { if (gi_ptr->indices[imri] != NULL) { free(gi_ptr->indices[imri]); } if (gi_ptr->coordinates[imri] != NULL) { free(gi_ptr->coordinates[imri]); } if (gi_ptr->widths[imri] != NULL) { free(gi_ptr->widths[imri]); } } /* Free the group list */ if (gi_ptr->group_list != NULL) { acr_delete_group_list(gi_ptr->group_list); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : search_list @INPUT : value list_ptr list_length start_index - point from which search should start @OUTPUT : (none) @RETURNS : Index in list where value is found, or -1 is value not found. @DESCRIPTION: Routine to search a list for a value, returning the index into the list. If the value is not found, then -1 is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int search_list(int value, const int *list_ptr, int list_length, int start_index) { int index; /* If nothing on list, just return. */ if (list_length <= 0) { return (-1); } /* If starting point is invalid, start at zero. */ if ((start_index >= list_length) || (start_index < 0)) { start_index = 0; } /* Loop over indices, wrapping at the end of the list */ index = start_index; do { if (list_ptr[index] == value) { return index; /* Found it. */ } index++; if (index >= list_length) { index = 0; } } while (index != start_index); return -1; /* Search failed. */ } /* ----------------------------- MNI Header ----------------------------------- @NAME : sort_dimensions @INPUT : gi_ptr @OUTPUT : gi_ptr @RETURNS : (nothing) @DESCRIPTION: Routine to sort the MRI dimensions according to their coordinates. It also fills in the step and start values for the SLICE dimension. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void sort_dimensions(General_Info *gi_ptr) { Mri_Index imri; Sort_Element *sort_array; int nvalues; int i,j; int reverse_array; /* Sort the dimensions, if needed. */ for (imri = 0; imri < MRI_NDIMS; imri++) { /* Sort each dimension iff the size is greater than 1 and it is not * a time dimension in an N4 mosaic. */ if (gi_ptr->cur_size[imri] <= 1 || /* Don't sort on time for N4 mosaics (TODO: Why not??) */ ((G.file_type == N4DCM) && (imri == TIME) && (gi_ptr->num_slices_in_file > 1))) { if (G.Debug >= HI_LOGGING) { printf("Not sorting %s dimension\n", Mri_Names[imri]); } continue; } if (G.Debug >= HI_LOGGING) { printf("Sorting %s dimension\n", Mri_Names[imri]); printf(" slice order is:%s\n",gi_ptr->acq.slice_order ); } /* Set up the array for sorting. */ nvalues = gi_ptr->cur_size[imri]; sort_array = malloc(nvalues * sizeof(*sort_array)); CHKMEM(sort_array); for (i = 0; i < nvalues; i++) { sort_array[i].identifier = gi_ptr->indices[imri][i]; sort_array[i].original_index = i; sort_array[i].value = gi_ptr->coordinates[imri][i]; sort_array[i].width = gi_ptr->widths[imri][i]; } /* Sort the array. */ qsort((void *) sort_array, (size_t) nvalues, sizeof(*sort_array), dimension_sort_function); /* Added this from dicomserver conversion, it was probably removed. * Although it should not matter whether we start negative and * step positive or the other way around, we should try and stay * consistent with previous versions and with the dicom header. * It is especially important for slice times */ /* Figure out if we should reverse the array to keep something * similar to the original ordering. * Also need to check for slice ordering, MOSAIC images are * always sorted from bottom to top whether the sequence was * ascending or descending */ reverse_array = (sort_array[0].original_index > sort_array[nvalues-1].original_index) || (!strcmp(gi_ptr->acq.slice_order,"descending")&& !strcmp(Mri_Names[imri], "Slice")); /* Copy the information back into the appropriate arrays */ for (i=0; i < nvalues; i++) { j = (reverse_array ? nvalues - i - 1 : i); gi_ptr->indices[imri][i] = sort_array[j].identifier; gi_ptr->coordinates[imri][i] = sort_array[j].value; gi_ptr->widths[imri][i] = sort_array[j].width; } if (G.Debug >= HI_LOGGING) { /* Print out all of the information about this dimension. */ if(reverse_array){ printf(" nvalues %d min %f max %f\n", nvalues, gi_ptr->coordinates[imri][nvalues - 1], gi_ptr->coordinates[imri][0]); }else{ printf(" nvalues %d min %f max %f\n", nvalues, gi_ptr->coordinates[imri][0], gi_ptr->coordinates[imri][nvalues - 1]); } for (i = 0; i < nvalues; i++) { printf("%3d %6d %8.3f\n", i, gi_ptr->indices[imri][i], gi_ptr->coordinates[imri][i]); } } /* Free the temporary array we used to sort the coordinate axis. */ free(sort_array); /* Now verify that the slice coordinate array looks sane. We * don't complain about things like missing time slices, since * many PET scanners produce irregular timings. */ if (nvalues >= 2 && imri == SLICE) { /* Calculate the spacing between the first and second slice. */ double delta = (gi_ptr->coordinates[imri][1] - gi_ptr->coordinates[imri][0]); for (i = 1; i < nvalues; i++) { /* Check that each successive slice has roughly the same * spacing, to within 2 percent of the initial delta. */ /* Check against absolute value of epsilon, could be positive * or negative, because of reversal (fcmp does not handle this) */ if (!fcmp(delta, (gi_ptr->coordinates[imri][i] - gi_ptr->coordinates[imri][i - 1]), fabs(2.0 * (delta / 100.0)))) { /* TODO: Perhaps this message could be improved?? */ printf("WARNING: Missing %s data at index %d, %g %g\n", Mri_Names[imri], i, delta, (gi_ptr->coordinates[imri][i] - gi_ptr->coordinates[imri][i - 1])); } } } /* Update slice step and start. */ if (imri == SLICE) { if (gi_ptr->coordinates[imri][0] != gi_ptr->coordinates[imri][nvalues-1]) { double dbl_tmp1; double dbl_tmp2; dbl_tmp1 = gi_ptr->step[gi_ptr->slice_world]; dbl_tmp2 = (gi_ptr->coordinates[imri][nvalues - 1] - gi_ptr->coordinates[imri][0]) / ((double) gi_ptr->cur_size[imri] - 1.0); /* OK, so now we have to figure out who wins the great * battle to become the slice step value. If the value * we have been assuming up until now is the same as the * calculated value with only a sign change, or if the * assumed value is the default (1.0), we adopt the * calculated value. */ /* Check against absolute value of epsilon, could be positive * or negative, because of reversal (fcmp does not handle this) */ if (!fcmp(dbl_tmp1, dbl_tmp2, fabs((dbl_tmp1 / 1000.0)))) { printf("WARNING: Coordinate spacing (%g) differs from DICOM slice spacing (%g)\n", dbl_tmp2, dbl_tmp1); if (!G.prefer_coords) { printf(" (perhaps you should consider the -usecoordinates option)\n"); } if (dbl_tmp1 == 1.0 || G.prefer_coords || fcmp(dbl_tmp1, -dbl_tmp2, fabs(dbl_tmp1 / 1000.0))) { /*Although in the comment above it says that we should use the calculated value if the assumed and calculated value only differ by a sign change, this was not included in this if statement, added by ilana because default was wrong (i.e. w/o using -usecoordinates option)*/ gi_ptr->step[gi_ptr->slice_world] = dbl_tmp2; } printf(" Using %g for the slice spacing value.\n", gi_ptr->step[gi_ptr->slice_world]); } } gi_ptr->start[gi_ptr->slice_world] = gi_ptr->coordinates[imri][0]; if (G.Debug >= HI_LOGGING) { printf("Set slice %d step to %f, start to %f\n", gi_ptr->slice_world, gi_ptr->step[gi_ptr->slice_world], gi_ptr->start[gi_ptr->slice_world]); } } /* If slice dimension */ } /* for all mri dimensions */ } /* ----------------------------- MNI Header ----------------------------------- @NAME : dimension_sort_function @INPUT : v1, v2 - values to compare @OUTPUT : (none) @RETURNS : -1, 0 or 1 if v1 < v2, v1 == v2 or v1 > v2 @DESCRIPTION: Function to compare to array elements for sorting. Elements are compared first on value, then on their original array index (this tries to preserve the original sequence). @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int dimension_sort_function(const void *v1, const void *v2) { Sort_Element *value1, *value2; value1 = (Sort_Element *) v1; value2 = (Sort_Element *) v2; if (value1->value < value2->value) return -1; else if (value1->value > value2->value) return 1; else if (value1->original_index < value2->original_index) return -1; else if (value1->original_index > value2->original_index) return 1; else return 0; } int prot_find_string(Acr_Element elem_ptr, const char *name_str, char *value) { static const char prot_head[] = "### ASCCONV BEGIN ###"; long cur_offset,tmp_offset; long max_offset; char *field_ptr; int ix1, ix2; max_offset = elem_ptr->data_length - sizeof(prot_head); tmp_offset = max_offset; // Scan through the element containing the protocol, to find the // ASCII dump of the MrProt structure. // /*For some reason, some dicom files have 2 "ASCCONV BEGIN" tags, this screws up the search. Keep the second one we find for now, don't know if this will always work for these dual-ASCCONV files. IRL*/ for (cur_offset = 0; cur_offset < max_offset; cur_offset++) { if (!memcmp(elem_ptr->data_pointer + cur_offset, prot_head, sizeof(prot_head) - 1)) { tmp_offset = cur_offset; } } cur_offset = tmp_offset; /*set it to the last occurence of "ASCCONV BEGIN"*/ /* bail if we didn't find the protocol */ if (cur_offset == max_offset) { return (0); } field_ptr = strstr(elem_ptr->data_pointer + cur_offset, name_str); if (field_ptr != NULL) { sscanf(field_ptr, "%*s %*s %s", value); ix1 = 0; for (ix2 = 0; value[ix2] != '\0'; ix2++) { if (value[ix2] != '"') { value[ix1++] = value[ix2]; } } } else { strcpy(value, "0"); } return (1); } static char * dump_protocol_text(Acr_Element elem_ptr) { const char prot_head[] = "### ASCCONV BEGIN ###"; const char prot_tail[] = "### ASCCONV END ###"; char *output = malloc(elem_ptr->data_length); int prot_found = FALSE; long cur_offset, tmp_offset; long max_offset; CHKMEM(output); // scan throught the group containing the protocol, to find the // ascii dump of the MrProt structure max_offset = elem_ptr->data_length - sizeof (prot_head); /*For some reason, some dicom files have 2 "ASCCONV BEGIN" tags, this screws up the search. Keep the second one we find for now, don't know if this will always work for these dual-ASCCONV files. IRL*/ for (cur_offset = 0; cur_offset < max_offset; cur_offset++) { if (!memcmp(elem_ptr->data_pointer + cur_offset, prot_head, sizeof(prot_head) - 1)) { prot_found = TRUE; tmp_offset = cur_offset; } } cur_offset = tmp_offset; /*set it to the last occurence of "ASCCONV BEGIN"*/ if (prot_found) { int ix1 = 0; char *tmp_ptr = elem_ptr->data_pointer + cur_offset; for ( ; cur_offset < max_offset; cur_offset++) { if (!memcmp(tmp_ptr, prot_tail, sizeof(prot_tail) - 1)) { break; } if (*tmp_ptr != '"') { output[ix1++] = *tmp_ptr; } tmp_ptr++; } output[ix1] = '\0'; } return (output); } static void copy_element_properties(Acr_Element new_element, Acr_Element old_element) { acr_set_element_byte_order(new_element, acr_get_element_byte_order(old_element)); acr_set_element_vr_encoding(new_element, acr_get_element_vr_encoding(old_element)); } static int mosaic_init(Acr_Group group_list, Mosaic_Info *mi_ptr, int load_image) { int group_id, element_id; int grid_size; long new_image_size; void *data; Acr_Element element; int i; double pixel_spacing[2]; Acr_Double separation; double RowColVec[6]; double dircos[VOL_NDIMS][WORLD_NDIMS]; Acr_String str_tmp,str_tmp2; int old = 1; if (G.Debug >= HI_LOGGING) { printf("mosaic_init(%lx, %lx, %d)\n", (unsigned long) group_list, (unsigned long) mi_ptr, load_image); } str_tmp = acr_find_string(group_list, SPI_Order_of_slices, ""); /* Seems like this field is often not found, * the sSliceArray.ucMode field found in the ASCONV header * seems trustworthy. */ /* 0x1 means ASCENDING * 0x2 means DESCENDING * 0x4 means INTERLEAVED*/ str_tmp2 = acr_find_string(group_list, EXT_Slice_order, ""); if (!strncmp(str_tmp, "INTERLEAVED", 11) || !strncmp(str_tmp2, "0x4", 3)) { mi_ptr->mosaic_seq = MOSAIC_SEQ_INTERLEAVED; str_tmp="interleaved"; } else if (!strncmp(str_tmp, "ASCENDING", 9)|| !strncmp(str_tmp2, "0x1", 3)) { mi_ptr->mosaic_seq = MOSAIC_SEQ_ASCENDING; str_tmp="ascending"; } else if (!strncmp(str_tmp, "DESCENDING", 10)|| !strncmp(str_tmp2, "0x2", 3)) { mi_ptr->mosaic_seq = MOSAIC_SEQ_DESCENDING; str_tmp="descending"; } else { mi_ptr->mosaic_seq = G.mosaic_seq; str_tmp="default ascending"; } if (G.Debug >= HI_LOGGING) { printf(" ordering is %s\n", str_tmp); } /* Get some basic image information. * big[0/1] is number of columns/rows in whole mosaic. */ mi_ptr->big[0] = acr_find_int(group_list, ACR_Columns, 1); mi_ptr->big[1] = acr_find_int(group_list, ACR_Rows, 1); mi_ptr->pixel_size = (acr_find_int(group_list, ACR_Bits_allocated, 16) - 1) / 8 + 1; /* Get the image size * (size[0/1] is number of columns/rows in a single slice) */ mi_ptr->size[0] = (int)acr_find_short(group_list, EXT_Sub_image_columns, 1); mi_ptr->size[1] = (int)acr_find_short(group_list, EXT_Sub_image_rows, 1); // Get the grid shape, checking that it is not too big if specified mi_ptr->grid[0] = mi_ptr->big[0] / mi_ptr->size[0]; mi_ptr->grid[1] = mi_ptr->big[1] / mi_ptr->size[1]; if ((mi_ptr->grid[0] < 1) || (mi_ptr->grid[0] < 1)) { fprintf(stderr, "Grid too small: %d x %d, size %d x %d, big %d x %d\n", mi_ptr->grid[0], mi_ptr->grid[1], mi_ptr->size[0], mi_ptr->size[1], mi_ptr->big[0], mi_ptr->big[1]); exit(EXIT_FAILURE); } // Check whether we need to do anything (1x1 grid may be the whole image) mi_ptr->big_image = NULL; mi_ptr->small_image = NULL; mi_ptr->packed = FALSE; grid_size = mi_ptr->grid[0] * mi_ptr->grid[1]; if ((grid_size == 1) && (mi_ptr->size[0] == mi_ptr->big[0]) && (mi_ptr->size[1] == mi_ptr->big[1])) { /* had to remove this as now ANY images acquired with the mosaic sequence need special treatment */ mi_ptr->packed = FALSE; return 1; } /* Update the number of image rows and columns */ acr_insert_short(&group_list, ACR_Rows, mi_ptr->size[1]); acr_insert_short(&group_list, ACR_Columns, mi_ptr->size[0]); /* Get image image index info (number of slices in file) */ mi_ptr->slice_count = acr_find_int(group_list, EXT_Slices_in_file, 1); /* sub_images is now just the number of mosaic elements, even if * they don't all contain slices */ mi_ptr->sub_images = mi_ptr->grid[0] * mi_ptr->grid[1]; /* Get the pixel size. */ dicom_read_pixel_size(group_list, pixel_spacing); /* Get step between slices */ separation = acr_find_double(group_list, ACR_Slice_thickness, 0.0); if (separation == 0.0) { separation = acr_find_double(group_list, ACR_Spacing_between_slices, 1.0); } /* get image normal vector * (need to compute based on dicom field, which gives * unit vectors for row and column direction) * TODO: This code (and other code in this function) could probably * be broken out and made redundant with other code in the converter. */ if (dicom_read_orientation(group_list, RowColVec)) { memcpy(dircos[VCOLUMN], RowColVec, sizeof(*RowColVec) * WORLD_NDIMS); memcpy(dircos[VROW], &RowColVec[3], sizeof(*RowColVec) * WORLD_NDIMS); /* compute slice normal as cross product of row/column unit vectors * (should check for unit length?) */ mi_ptr->normal[XCOORD] = dircos[VCOLUMN][YCOORD] * dircos[VROW][ZCOORD] - dircos[VCOLUMN][ZCOORD] * dircos[VROW][YCOORD]; mi_ptr->normal[YCOORD] = dircos[VCOLUMN][ZCOORD] * dircos[VROW][XCOORD] - dircos[VCOLUMN][XCOORD] * dircos[VROW][ZCOORD]; mi_ptr->normal[ZCOORD] = dircos[VCOLUMN][XCOORD] * dircos[VROW][YCOORD] - dircos[VCOLUMN][YCOORD] * dircos[VROW][XCOORD]; } /* compute slice-to-slice step vector */ for (i = 0; i < WORLD_NDIMS; i++) { mi_ptr->step[i] = separation * mi_ptr->normal[i]; } /* Get position and correct to first slice */ if (!dicom_read_position(group_list, 0, mi_ptr->position)) { if (G.Debug) { printf("WARNING: No image position found\n"); } mi_ptr->position[XCOORD] = mi_ptr->position[YCOORD] = mi_ptr->position[ZCOORD] = 0.0; } if (G.Debug >= HI_LOGGING) { printf(" step %.3f %.3f %.3f pos %.3f %.3f %.3f normal %.3f,%.3f,%.3f\n", mi_ptr->step[0], mi_ptr->step[1], mi_ptr->step[2], mi_ptr->position[0], mi_ptr->position[1], mi_ptr->position[2], mi_ptr->normal[0], mi_ptr->normal[1], mi_ptr->normal[2] ); } /* Treat slice ordering differently depending on software version - for newer software versions(>VA25 or >VB), the mosaic images seem to always be ordered ascending, regardless of acquisition order.*/ str_tmp=strstr(acr_find_string(group_list, ACR_Software_versions, ""), "syngo MR A"); str_tmp2=strstr(acr_find_string(group_list, ACR_Software_versions, ""), "syngo MR B"); if(str_tmp !=NULL){ if(atoi(str_tmp + 10) >= 25) old=0; /*software version >= VA25*/ } else if(str_tmp2 !=NULL){ if(atoi(str_tmp2 + 10) >= 11) old=0; /*software version >= VB11*/ } if(old==1){ /*old behavior*/ if (mi_ptr->mosaic_seq != MOSAIC_SEQ_INTERLEAVED) { if (is_numaris3(group_list)) { for (i = 0; i < WORLD_NDIMS; i++) { mi_ptr->position[i] -= (double) (mi_ptr->sub_images-1) * mi_ptr->step[i]; } } else { /* Numaris 4 mosaic correction: * - position given is edge of huge slice constructed as if * real slice was at center of mosaic * - mi_ptr->big[0,1] are number of columns and rows of mosaic * - mi_ptr->size[0,1] are number of columns and rows of sub-image */ for (i = 0; i < WORLD_NDIMS; i++) { /* Correct offset from mosaic Center */ mi_ptr->position[i] += (double) ((dircos[VCOLUMN][i] * mi_ptr->big[0] * pixel_spacing[0]/2.0) + (dircos[VROW][i] * mi_ptr->big[1] * pixel_spacing[1]/2)); /* Move from center to corner of slice */ mi_ptr->position[i] -= ((dircos[VCOLUMN][i] * mi_ptr->size[0] * pixel_spacing[0]/2.0) + (dircos[VROW][i] * mi_ptr->size[1] * pixel_spacing[1]/2.0)); } } } } else{ /*new behavior*/ for (i = 0; i < WORLD_NDIMS; i++) { /* Correct offset from mosaic Center */ mi_ptr->position[i] += (double) ((dircos[VCOLUMN][i] * mi_ptr->big[0] * pixel_spacing[0]/2.0) + (dircos[VROW][i] * mi_ptr->big[1] * pixel_spacing[1]/2)); /* Move from center to corner of slice */ mi_ptr->position[i] -= ((dircos[VCOLUMN][i] * mi_ptr->size[0] * pixel_spacing[0]/2.0) + (dircos[VROW][i] * mi_ptr->size[1] * pixel_spacing[1]/2.0)); } } if (G.Debug >= HI_LOGGING) { printf(" corrected position %.3f %.3f %.3f\n", mi_ptr->position[0], mi_ptr->position[1], mi_ptr->position[2]); } /* Now that we've corrected the _position_, we still might need to correct * the pixel spacing. For some gadawful reason, some (but not all) Siemens * mosaic files store the pixel spacing such that it is scaled by the ratio * between the mosaic image size and the subimage size. The best way I can * think of to detect this is by comparing the field of view to the product * of the pixel spacing and the actual subimage size, and if they are * wildly different, assume that we need to perform the scaling... */ element = acr_find_group_element(group_list, SPI_Field_of_view); if (element != NULL) { double fov[2]; /* field of view (row/column) */ acr_get_element_numeric_array(element, 2, fov); if (fov[0] != 0.0 && fov[1] != 0.0) { double derived_spacing[2]; int ratio[2]; char str_buf[128]; /* Calculate the actual spacing required to cover the field of view. */ derived_spacing[0] = fov[0] / mi_ptr->size[0]; derived_spacing[1] = fov[1] / mi_ptr->size[1]; ratio[0] = (int) rint(derived_spacing[0] / pixel_spacing[0]); ratio[1] = (int) rint(derived_spacing[1] / pixel_spacing[1]); /* If the ratio of the derived spacing to the pixel spacing is * the same as the ratio between the edge length of the large * and small images, adopt the derived spacing as the correct * value. */ if (ratio[0] == (mi_ptr->big[0] / mi_ptr->size[0]) || ratio[1] == (mi_ptr->big[1] / mi_ptr->size[1])) { if (G.Debug) { printf("Updating mosaic pixel spacing from %f,%f to %f,%f\n", pixel_spacing[0],pixel_spacing[1], derived_spacing[0],derived_spacing[1]); } /* Store the updated pixel spacing in the group list. */ sprintf(str_buf, "%.15g\\%.15g", derived_spacing[0], derived_spacing[1]); acr_insert_string(&group_list, ACR_Pixel_size, str_buf); } } } if (!load_image) { mi_ptr->big_image = NULL; mi_ptr->small_image = NULL; } else { /* Steal the image element from the group list */ mi_ptr->packed = TRUE; mi_ptr->big_image = acr_find_group_element(group_list, ACR_Pixel_data); if (mi_ptr->big_image == NULL) { fprintf(stderr, "Couldn't find an image\n"); exit(EXIT_FAILURE); } group_id = acr_get_element_group(mi_ptr->big_image); element_id = acr_get_element_element(mi_ptr->big_image); acr_group_steal_element(acr_find_group(group_list, group_id), mi_ptr->big_image); /* Add a small image */ new_image_size = mi_ptr->size[0] * mi_ptr->size[1] * mi_ptr->pixel_size; data = malloc(new_image_size); CHKMEM(data); mi_ptr->small_image = acr_create_element(group_id, element_id, acr_get_element_vr(mi_ptr->big_image), new_image_size, data); acr_set_element_vr(mi_ptr->small_image, acr_get_element_vr(mi_ptr->big_image)); copy_element_properties(mi_ptr->small_image, mi_ptr->big_image); acr_insert_element_into_group_list(&group_list, mi_ptr->small_image); } /* Return number of sub-images in this image */ return mi_ptr->sub_images; } static int mosaic_insert_subframe(Acr_Group group_list, Mosaic_Info *mi_ptr, int iimage, int load_image) { int irow; int idim; int nbyte; int isub; int jsub; char *new; char *old; long old_offset; long new_offset; double position[WORLD_NDIMS]; string_t string; int islice; char *str_tmp, *str_tmp2; int oldb=1; if (G.Debug >= HI_LOGGING) { printf("mosaic_insert_subframe(%lx, %lx, %d, %d)\n", (unsigned long)group_list, (unsigned long)mi_ptr, iimage, load_image); } /* Figure out what to do based upon the mosaic sequencing. */ /* Since at least software version VA25 (and thus VA30, VB15), * the mosaic sequencing in the file is the same, regardless * of the acquisition (always ascending). * Also, the following code is based on a field that is * deprecated (0x0021 0x123f)... still keep old behavior in case * its an older image type*/ str_tmp=strstr(acr_find_string(group_list, ACR_Software_versions, ""), "syngo MR A"); str_tmp2=strstr(acr_find_string(group_list, ACR_Software_versions, ""), "syngo MR B"); if(str_tmp !=NULL){ if(atoi(str_tmp + 10) >= 25) oldb=0; /*software version >= VA25*/ } else if(str_tmp2 !=NULL){ if(atoi(str_tmp2 + 10) >= 11) oldb=0; /*software version >= VB11*/ } if(mi_ptr->mosaic_seq == MOSAIC_SEQ_INTERLEAVED && oldb==1){ //old behavior /*case MOSAIC_SEQ_INTERLEAVED:*/ /* For interleaved sequences, we have to map the odd slices to * the range slice_count/2..slice_count-1 and the even slices * from zero to slice_count/2-1 */ if (iimage & 1) { /* Odd?? */ islice = (mi_ptr->slice_count / 2) + (iimage / 2); } else { islice = iimage / 2; } //break; } else{ /*default:*/ /* Otherwise, just use the image number without modification for * ascending or unknown slice ordering. */ islice = iimage; } #if 0 if (is_numaris3(group_list)) { islice = mi_ptr->slice_count - islice - 1; } #endif /* Check the image number */ if ((iimage < 0) || (iimage > mi_ptr->sub_images)) { fprintf(stderr, "Invalid image number to send: %d of %d\n", iimage, mi_ptr->sub_images); exit(EXIT_FAILURE); } /* Update the index */ acr_insert_numeric(&group_list, SPI_Current_slice_number, (double) iimage); /* Update the position */ for (idim = 0; idim < WORLD_NDIMS; idim++) { position[idim] = mi_ptr->position[idim] + (double) iimage * mi_ptr->step[idim]; } /* If the sequence is descending, invert the slice coordinate. * This involves subtracting the step * index from the mosaic * slice position. */ /*This should already have been taken care of in sort_dimensions above*/ /*if (mi_ptr->mosaic_seq == MOSAIC_SEQ_DESCENDING) { position[ZCOORD] = mi_ptr->position[ZCOORD] - (double) islice * mi_ptr->step[ZCOORD]; }*/ sprintf(string, "%.15g\\%.15g\\%.15g", position[XCOORD], position[YCOORD], position[ZCOORD]); acr_insert_string(&group_list, ACR_Image_position_patient, string); acr_insert_string(&group_list, SPI_Image_position, string); /* HMM - is this necessary?? */ if (is_numaris3(group_list)) { update_coordinate_info(group_list); } if (G.Debug >= HI_LOGGING) { printf(" position %s\n", string); } if (load_image) { /* Figure out the sub-image indices */ isub = islice % mi_ptr->grid[0]; jsub = islice / mi_ptr->grid[0]; /* Get pointers */ old = acr_get_element_data(mi_ptr->big_image); new = acr_get_element_data(mi_ptr->small_image); /* Copy the image */ nbyte = mi_ptr->size[0] * mi_ptr->pixel_size; for (irow = 0; irow < mi_ptr->size[1]; irow++) { old_offset = isub * mi_ptr->size[0] + (jsub * mi_ptr->size[1] + irow) * mi_ptr->big[0]; old_offset *= mi_ptr->pixel_size; new_offset = (irow * mi_ptr->size[0]) * mi_ptr->pixel_size; memcpy(&new[new_offset], &old[old_offset], nbyte); } /* Reset the byte order and VR encoding. This will be modified on each * send according to what the connection needs. */ copy_element_properties(mi_ptr->small_image, mi_ptr->big_image); } return 1; } static void mosaic_cleanup(Mosaic_Info *mi_ptr) { if (mi_ptr) { if (mi_ptr->packed && mi_ptr->big_image != NULL) { acr_delete_element(mi_ptr->big_image); mi_ptr->packed = FALSE; mi_ptr->big_image = NULL; } } } /************************************************************************ * Multiframe functions, which mimic the behavior of the older mosaic * functions. This is not yet a complete or correct implementation of * multiframe DICOM - see the NOTE: above! */ /* ----------------------------- MNI Header ----------------------------------- @NAME : multiframe_init() @INPUT : group_list - the list of DICOM groups/elements that make up this file. int load_image - a boolean value, non-zero if the function should actually load the data into memory. @OUTPUT : mfi_ptr - a pointer to a Multiframe_Info structure that will contain information used to expand this multiframe file into a series of slices. @RETURNS : void @DESCRIPTION: Initialize a multiframe conversion process. @METHOD : @GLOBALS : @CALLS : @CREATED : June 3, 2005 Bert Vincent @MODIFIED : ---------------------------------------------------------------------------- */ static void multiframe_init(Acr_Group group_list, Multiframe_Info *mfi_ptr, int load_image) { int grp_id; int elm_id; void *data_ptr; Acr_Element element; int i; Acr_Double spacing; double RowColVec[6]; double dircos[VOL_NDIMS][WORLD_NDIMS]; int rows; int cols; int pixel_size; if (G.Debug >= HI_LOGGING) { printf("multiframe_init(%lx, %lx, %d)\n", (unsigned long) group_list, (unsigned long) mfi_ptr, load_image); } cols = acr_find_int(group_list, ACR_Columns, 1); rows = acr_find_int(group_list, ACR_Rows, 1); pixel_size = (acr_find_int(group_list, ACR_Bits_allocated, 16) - 1) / 8 + 1; /* Get image image index info (number of slices in file) */ mfi_ptr->frame_count = acr_find_int(group_list, ACR_Number_of_frames, 1); /* Get spacing between slices */ spacing = acr_find_double(group_list, ACR_Slice_thickness, 0.0); if (spacing == 0.0) { spacing = acr_find_double(group_list, ACR_Spacing_between_slices, 1.0); } /* get image normal vector * (need to compute based on dicom field, which gives * unit vectors for row and column direction) * TODO: This code (and other code in this function) could probably * be broken out and made redundant with other code in the converter. */ if (dicom_read_orientation(group_list, RowColVec)) { memcpy(dircos[VCOLUMN], RowColVec, sizeof(*RowColVec) * WORLD_NDIMS); memcpy(dircos[VROW], &RowColVec[3], sizeof(*RowColVec) * WORLD_NDIMS); convert_dicom_coordinate(dircos[VROW]); convert_dicom_coordinate(dircos[VCOLUMN]); /* compute slice normal as cross product of row/column unit vectors * (should check for unit length?) */ mfi_ptr->normal[XCOORD] = dircos[VCOLUMN][YCOORD] * dircos[VROW][ZCOORD] - dircos[VCOLUMN][ZCOORD] * dircos[VROW][YCOORD]; mfi_ptr->normal[YCOORD] = dircos[VCOLUMN][ZCOORD] * dircos[VROW][XCOORD] - dircos[VCOLUMN][XCOORD] * dircos[VROW][ZCOORD]; mfi_ptr->normal[ZCOORD] = dircos[VCOLUMN][XCOORD] * dircos[VROW][YCOORD] - dircos[VCOLUMN][YCOORD] * dircos[VROW][XCOORD]; } /* If the normal is unreliable, use a default value. */ if (mfi_ptr->normal[XCOORD] == mfi_ptr->normal[YCOORD] && mfi_ptr->normal[XCOORD] == mfi_ptr->normal[ZCOORD]) { mfi_ptr->normal[ZCOORD] = -1.0; mfi_ptr->normal[YCOORD] = 0.0; mfi_ptr->normal[XCOORD] = 0.0; } /* Compute slice-to-slice step vector */ for (i = 0; i < WORLD_NDIMS; i++) { mfi_ptr->step[i] = spacing * mfi_ptr->normal[i]; } /* Get position and correct to first slice */ if (!dicom_read_position(group_list, 0, mfi_ptr->position)) { if (G.Debug) { printf("WARNING: No image position found\n"); } mfi_ptr->position[XCOORD] = mfi_ptr->position[YCOORD] = mfi_ptr->position[ZCOORD] = 0.0; } convert_dicom_coordinate(mfi_ptr->position); if (G.Debug >= HI_LOGGING) { printf(" step %.3f %.3f %.3f position %.3f %.3f %.3f\n", mfi_ptr->step[0], mfi_ptr->step[1], mfi_ptr->step[2], mfi_ptr->position[0], mfi_ptr->position[1], mfi_ptr->position[2]); } if (!load_image) { mfi_ptr->big_image = NULL; mfi_ptr->sub_image = NULL; } else { /* We need to load the image (we're probably on the second pass). */ /* Steal the image element from the group list */ element = acr_find_group_element(group_list, ACR_Pixel_data); if (element == NULL) { fprintf(stderr, "Couldn't find an image\n"); exit(EXIT_FAILURE); } mfi_ptr->big_image = element; /* Save pointer to pixel data element. */ grp_id = acr_get_element_group(element); elm_id = acr_get_element_element(element); acr_group_steal_element(acr_find_group(group_list, grp_id), element); /* Add a small image */ mfi_ptr->frame_size = rows * cols * pixel_size; data_ptr = malloc(mfi_ptr->frame_size); CHKMEM(data_ptr); mfi_ptr->sub_image = acr_create_element(grp_id, elm_id, acr_get_element_vr(element), mfi_ptr->frame_size, data_ptr); copy_element_properties(mfi_ptr->sub_image, mfi_ptr->big_image); acr_insert_element_into_group_list(&group_list, mfi_ptr->sub_image); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : multiframe_insert_subframe() @INPUT : group_list - the list of DICOM groups/elements that make up this file. mfi_ptr - a pointer to a Multiframe_Info structure that will contain information used to expand this multiframe file into a series of slices. int iimage - the index of the subimage to parse and possibly to load. int load_image - a boolean value, non-zero if the function should actually load the data into memory. @OUTPUT : mfi_ptr - may be modified by the function. @RETURNS : void @DESCRIPTION: This function decomposes a multiframe DICOM image into a series of single-frame images. Modifies the group_list to include updated image and position information. @METHOD : @GLOBALS : @CALLS : @CREATED : June 3, 2005 Bert Vincent @MODIFIED : ---------------------------------------------------------------------------- */ static void multiframe_insert_subframe(Acr_Group group_list, Multiframe_Info *mfi_ptr, int iframe, int load_image) { int idim; char *new_ptr; char *old_ptr; double position[WORLD_NDIMS]; string_t string; int result; if (G.Debug >= HI_LOGGING) { printf("multiframe_insert_subframe(%lx, %lx, %d, %d)\n", (unsigned long)group_list, (unsigned long)mfi_ptr, iframe, load_image); } /* Check the frame number */ if ((iframe < 0) || (iframe > mfi_ptr->frame_count)) { fprintf(stderr, "Invalid image number to send: %d of %d\n", iframe, mfi_ptr->frame_count); exit(EXIT_FAILURE); } /* Update the index in the file's group list. */ acr_insert_numeric(&group_list, SPI_Current_slice_number, (double) iframe); result = dicom_read_position(group_list, iframe, position); convert_dicom_coordinate(position); if (result != DICOM_POSITION_LOCAL) { /* If either no position was found for this frame number, or if * only a global position was found, we need to update the * position for this particular frame number. * * If a local position is found, as in some multiframe files, * this step is unnecessary and possibly wrong. */ for (idim = 0; idim < WORLD_NDIMS; idim++) { position[idim] = mfi_ptr->position[idim] + (double) iframe * mfi_ptr->step[idim]; } } sprintf(string, "%.15g\\%.15g\\%.15g", position[XCOORD], position[YCOORD], position[ZCOORD]); acr_insert_string(&group_list, ACR_Image_position_patient, string); if (G.Debug >= HI_LOGGING) { printf(" position %s\n", string); } if (load_image) { /* Get pointers */ old_ptr = acr_get_element_data(mfi_ptr->big_image); new_ptr = acr_get_element_data(mfi_ptr->sub_image); /* Copy the image */ memcpy(new_ptr, /* destination */ old_ptr + (iframe * mfi_ptr->frame_size), /* source */ mfi_ptr->frame_size); /* length */ /* Reset the byte order and VR encoding. This will be modified * on each send according to what the connection needs. */ copy_element_properties(mfi_ptr->sub_image, mfi_ptr->big_image); } } static void multiframe_cleanup(Multiframe_Info *mfi_ptr) { if (mfi_ptr) { if (mfi_ptr->big_image != NULL) { acr_delete_element(mfi_ptr->big_image); mfi_ptr->big_image = NULL; } } } minc-2.2.00/conversion/dcm2mnc/siemens_to_dicom.c0000644000265600003100000007377512027132660016655 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : siemens_to_dicom.c @DESCRIPTION: File containing routines to read in a Siemens vision internal file (.IMA extension) and convert it to a DICOM representation. @METHOD : @GLOBALS : @CREATED : July 8, 1997 (Peter Neelin) @MODIFIED : $Log: siemens_to_dicom.c,v $ @MODIFIED : Revision 1.11 2009-01-20 11:58:13 rotor @MODIFIED : * CMakeLists.txt: updated version @MODIFIED : * Updated Changelog to include releases @MODIFIED : * Warning cleanups below @MODIFIED : * conversion/dcm2mnc/minc_file.c: fixed printf type @MODIFIED : * conversion/dcm2mnc/siemens_to_dicom.c: fixed printf type @MODIFIED : * conversion/ecattominc/machine_indep.c: added string.h and fixed @MODIFIED : 2 fprintf missing format args @MODIFIED : * conversion/micropet/upet2mnc.c: fixed two fprintf format args @MODIFIED : * conversion/minctoecat/ecat_write.c: added string.h @MODIFIED : * conversion/minctoecat/minctoecat.c: added missing argument to fprintf @MODIFIED : * conversion/nifti1/mnc2nii.c: fixed incorrect printf type @MODIFIED : * progs/mincview/invert_raw_image.c: added fwrite checking @MODIFIED : @MODIFIED : Revision 1.10 2008/08/12 05:00:23 rotor @MODIFIED : * large number of changes from Claude (64 bit and updates) @MODIFIED : @MODIFIED : Revision 1.9 2008/01/17 02:33:01 rotor @MODIFIED : * removed all rcsids @MODIFIED : * removed a bunch of ^L's that somehow crept in @MODIFIED : * removed old (and outdated) BUGS file @MODIFIED : @MODIFIED : Revision 1.8 2008/01/12 19:08:14 stever @MODIFIED : Add __attribute__ ((unused)) to all rcsid variables. @MODIFIED : @MODIFIED : Revision 1.7 2006/02/09 20:54:29 bert @MODIFIED : More changes to dcm2mnc @MODIFIED : @MODIFIED : Revision 1.6 2005/04/21 22:32:15 bert @MODIFIED : Continue Siemens IMA code cleanup @MODIFIED : @MODIFIED : Revision 1.5 2005/04/18 16:21:16 bert @MODIFIED : Fix definition of siemens_to_dicom @MODIFIED : @MODIFIED : Revision 1.4 2005/04/05 21:56:47 bert @MODIFIED : Add some conversion functions, remove some more proprietary junk, and improve range-checking on some functions @MODIFIED : @MODIFIED : Revision 1.3 2005/03/03 18:59:16 bert @MODIFIED : Fix handling of image position so that we work with the older field (0020, 0030) as well as the new (0020, 0032) @MODIFIED : @MODIFIED : Revision 1.2 2005/03/02 20:06:23 bert @MODIFIED : Update conversions to reflect simplified header structures and types @MODIFIED : @MODIFIED : Revision 1.1 2005/02/17 16:38:11 bert @MODIFIED : Initial checkin, revised DICOM to MINC converter @MODIFIED : @MODIFIED : Revision 1.1.1.1 2003/08/15 19:52:55 leili @MODIFIED : Leili's dicom server for sonata @MODIFIED : @MODIFIED : Revision 1.1 2001/12/31 17:28:34 rhoge @MODIFIED : adding file to repos - now needed for reading .ima files in directly @MODIFIED : @MODIFIED : Revision 1.2 2000/12/17 01:05:24 rhoge @MODIFIED : temporary activation of offset table printing macro @MODIFIED : @MODIFIED : Revision 1.1.1.1 2000/11/30 02:05:54 rhoge @MODIFIED : imported sources to CVS repository on amoeba @MODIFIED : * Revision 1.4 1998/11/16 19:54:15 neelin * Added definitions for SunOS. * * Revision 1.3 1998/11/13 16:02:09 neelin * Modifications to support packed images and asynchronous transfer. * * Revision 1.2 1997/11/04 14:31:30 neelin * *** empty log message *** * * Revision 1.1 1997/08/11 12:50:53 neelin * Initial revision * ---------------------------------------------------------------------------- */ #include #include #include #include #include "dcm2mnc.h" #include "siemens_header_defs.h" /* Constants */ #define SIEMENS_IMAGE_OFFSET 6144 /* From dclunie.com */ #define IMAGE_NDIMS 2 /* Types */ #define ELEMENT_FUNC_ARGS \ (int grp_id, int elm_id, void *data, int length) #define DEFINE_ELEMENT_FUNC(name) \ static Acr_Element name ELEMENT_FUNC_ARGS #define DECLARE_ELEMENT_FUNC(name) \ static Acr_Element name ELEMENT_FUNC_ARGS typedef Acr_Element (*Create_Element_Function) ELEMENT_FUNC_ARGS; typedef struct { int grp_id; int elm_id; void *data; Create_Element_Function function; int length; } Siemens_hdr_entry; /* Functions */ static Acr_Element_Id get_elid(int grp_id, int elm_id, Acr_VR_Type vr_code); DECLARE_ELEMENT_FUNC(create_char_element); DECLARE_ELEMENT_FUNC(create_long_element); DECLARE_ELEMENT_FUNC(create_short_element); DECLARE_ELEMENT_FUNC(create_double_element); DECLARE_ELEMENT_FUNC(create_ima_date_t_element); DECLARE_ELEMENT_FUNC(create_ima_time_t_element); DECLARE_ELEMENT_FUNC(create_modality_element); DECLARE_ELEMENT_FUNC(create_sex_element); DECLARE_ELEMENT_FUNC(create_age_element); DECLARE_ELEMENT_FUNC(create_slice_order_element); DECLARE_ELEMENT_FUNC(create_pixel_spacing_t_element); DECLARE_ELEMENT_FUNC(create_window_t_element); DECLARE_ELEMENT_FUNC(create_ima_vector_t_element); DECLARE_ELEMENT_FUNC(create_laterality_element); DECLARE_ELEMENT_FUNC(create_ima_position_t_element); DECLARE_ELEMENT_FUNC(create_rest_direction_t_element); DECLARE_ELEMENT_FUNC(create_view_direction_t_element); DECLARE_ELEMENT_FUNC(create_ima_orientation_t_element); DECLARE_ELEMENT_FUNC(create_field_of_view_t_element); /* Define the table of header values */ ima_header_t IMA_hdr; /* Must define this first */ #include "siemens_header_table.h" /* Now include the table */ /* flag to print offset table, useful in debugging byte pad issues with Linux/sun porting */ /* #define PRINT_OFFSET_TABLE 1 */ /* ----------------------------- MNI Header ----------------------------------- @NAME : siemens_to_dicom @INPUT : filename - name of Siemens internal file read_image - if TRUE, then the image is added to the group list, otherwise it is not read in. @OUTPUT : (none) @RETURNS : Acr-nema group list containing contents of Siemens file @DESCRIPTION: Function to read in a siemens internal format file (.IMA) and store it in an ACR-NEMA group list. @METHOD : @GLOBALS : @CALLS : @CREATED : July 8, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Group siemens_to_dicom(const char *filename, int max_group) { FILE *fp; Siemens_hdr_entry *entry; Acr_Group group_list; Acr_Element element; long image_size; long pixel_size; void *image; double flip_angle; short rows; short cols; int n_slices; #ifdef PRINT_OFFSET_TABLE void *header_ptr; /* debug junk */ void *data_ptr; /* debug junk */ long offset; /* debug junk */ #endif /* Check the structure offsets */ assert(((char *)&IMA_hdr.G08 - (char *)&IMA_hdr) == 0x0000); assert(((char *)&IMA_hdr.G10 - (char *)&IMA_hdr) == 0x0300); assert(((char *)&IMA_hdr.G18 - (char *)&IMA_hdr) == 0x0600); assert(((char *)&IMA_hdr.G19 - (char *)&IMA_hdr) == 0x0780); assert(((char *)&IMA_hdr.G20 - (char *)&IMA_hdr) == 0x0C80); assert(((char *)&IMA_hdr.G21 - (char *)&IMA_hdr) == 0x0E80); assert(((char *)&IMA_hdr.G28 - (char *)&IMA_hdr) == 0x1380); if (G.Debug >= HI_LOGGING) { printf("siemens_to_dicom(%s, %x)\n", filename, max_group); } /* Open the file */ if ((fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "Error opening file %s\n", filename); return NULL; } /* Read in the header */ if (fread(&IMA_hdr, sizeof(IMA_hdr), 1, fp) != 1) { fprintf(stderr, "Error reading header in %s\n", filename); fclose(fp); return NULL; } /* Get the image if it is needed */ if (max_group >= ACR_IMAGE_GID) { /* Figure out how much space we need for the image */ pixel_size = 2; /* Apparently this never changes?? */ /* Need to byte swap row/col values if needed */ acr_get_short(ACR_BIG_ENDIAN, 1, &IMA_hdr.G28.Rows, &rows); acr_get_short(ACR_BIG_ENDIAN, 1, &IMA_hdr.G28.Columns, &cols); image_size = rows * cols; image = malloc(pixel_size * image_size); CHKMEM(image); /* Read in the image */ if (fseek(fp, (long) SIEMENS_IMAGE_OFFSET, SEEK_SET)) { printf("ERROR: Error finding image in %s\n", filename); fclose(fp); return NULL; } if (fread(image, pixel_size, image_size, fp) != image_size) { printf("ERROR: Error reading image in %s\n", filename); fclose(fp); return NULL; } } /* If (max_group >= ACR_IMAGE_GID) */ /* Close the file */ fclose(fp); /* Loop through the header table, creating a header */ group_list = NULL; for (entry = Siemens_hdr_table; entry->data != NULL; entry++) { #ifdef PRINT_OFFSET_TABLE data_ptr = entry->data; header_ptr = &IMA_hdr; offset = (long) data_ptr - (long) header_ptr; printf("DEBUG: group = 0x%x, element = 0x%x, offset = 0x%lx, length = 0x%x\n", entry->grp_id, entry->elm_id, offset, entry->length); #endif if (entry->function == NULL) { continue; } element = entry->function(entry->grp_id, entry->elm_id, entry->data, entry->length); if (element == NULL) { continue; } acr_insert_element_into_group_list(&group_list, element); } /* Insert flip angle element */ element = acr_find_group_element(group_list, SPI_Flip_angle); if (element != NULL) { flip_angle = acr_get_element_numeric(element); if (flip_angle >= 0.0) { acr_insert_numeric(&group_list, ACR_Flip_angle, flip_angle); } } n_slices = acr_find_int(group_list, SPI_Number_of_slices_nominal, 1); if (n_slices > 1) { Acr_Short acq_cols; int n_acq; int n_avg; acq_cols = acr_find_short(group_list, SPI_Acquisition_columns, acr_find_short(group_list, ACR_Columns, 1)); rows = acr_find_int(group_list, ACR_Rows, 1); acr_insert_long(&group_list, EXT_Mosaic_rows, (Acr_Long)rows); cols = acr_find_int(group_list, ACR_Columns, 1); acr_insert_long(&group_list, EXT_Mosaic_columns, (Acr_Long)cols); /* Don't allow acq_cols greater than actual size! */ if (acq_cols > rows) { n_slices = 1; acq_cols = rows; } if (acq_cols > cols) { n_slices = 1; acq_cols = cols; } acr_insert_long(&group_list, EXT_Slices_in_file, (Acr_Long)n_slices); acr_insert_short(&group_list, EXT_Sub_image_rows, (Acr_Long)acq_cols); acr_insert_short(&group_list, EXT_Sub_image_columns, (Acr_Long)acq_cols); /* We need to set up the ACR_Acquisition (and * ACR_Acquisitions_in_series) objects to make everyone happy. * * TODO: This appears to work for SOME IMA files, but it may * not be correct for all sequences. * * BERT: My latest change here is to examine both values and * use the larger of the two. Jens Pruessner had some IMA files * that had a value for acquisitions_in_series that was correctly * giving the number of time steps, while the nr_averages was 1. * Other files apparently contradict this! */ acr_insert_long(&group_list, ACR_Acquisition, (Acr_Long)acr_find_int(group_list, ACR_Image, 1)); n_avg = acr_find_int(group_list, ACR_Nr_of_averages, 1); n_acq = acr_find_int(group_list, ACR_Acquisitions_in_series, 1); if (n_avg > n_acq) { acr_insert_long(&group_list, ACR_Acquisitions_in_series, (Acr_Long)n_avg); } } /* Insert a series number */ acr_insert_numeric(&group_list, ACR_Series, 1.0); /* Insert appropriate image position and orientation information */ update_coordinate_info(group_list); /* Add the image if it is needed */ if (max_group >= ACR_IMAGE_GID) { /* Insert the image location */ acr_insert_short(&group_list, ACR_Image_location, ACR_IMAGE_GID); /* Add the image. We don't byte-swap here since it will be done automatically when the data is written out. */ element = acr_create_element(ACR_IMAGE_GID, ACR_IMAGE_EID, ACR_VR_OW, image_size * pixel_size, image); acr_insert_element_into_group_list(&group_list, element); /* explicitly label image data as big-endian */ acr_set_element_byte_order(element, ACR_BIG_ENDIAN); } /* if (max_group >= ACR_IMAGE_GID) */ /* Return the group list */ return group_list; } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_coordinate_info @INPUT : group_list @OUTPUT : group_list @RETURNS : (nothing) @DESCRIPTION: Function to modify the DICOM coordinate information to match the Siemens info. @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1998 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void update_coordinate_info(Acr_Group group_list) { Acr_Element element; int nrows, ncolumns; int i; double coord[WORLD_NDIMS]; double row[WORLD_NDIMS]; double column[WORLD_NDIMS]; double normal[WORLD_NDIMS]; double pixel_spacing[IMAGE_NDIMS]; string_t string; int n_slices; if (G.Debug >= HI_LOGGING) { printf("update_coordinate_info(%lx)\n", (unsigned long) group_list); } /* Look for the normal vector */ element = acr_find_group_element(group_list, SPI_Image_normal); if ((element == NULL) || (acr_get_element_numeric_array(element, WORLD_NDIMS, normal) != WORLD_NDIMS)) { normal[XCOORD] = 0.0; normal[YCOORD] = 0.0; normal[ZCOORD] = 1.0; } /* Look for the row vector. */ element = acr_find_group_element(group_list, SPI_Image_row); if ((element == NULL) || (acr_get_element_numeric_array(element, WORLD_NDIMS, row) != WORLD_NDIMS)) { row[XCOORD] = 1.0; row[YCOORD] = 0.0; row[ZCOORD] = 0.0; } /* Look for the column vector */ element = acr_find_group_element(group_list, SPI_Image_column); if ((element == NULL) || (acr_get_element_numeric_array(element, WORLD_NDIMS, column) != WORLD_NDIMS)) { column[XCOORD] = 0.0; column[YCOORD] = 1.0; column[ZCOORD] = 0.0; } if (G.Debug >= HI_LOGGING) { printf("R %.3f %.3f %.3f C %.3f %.3f %.3f N %.3f %.3f %.3f\n", row[0], row[1], row[2], column[0], column[1], column[2], normal[0], normal[1], normal[2]); } /* Put in the dicom orientation (patient) field */ sprintf(string, "%.15g\\%.15g\\%.15g\\%.15g\\%.15g\\%.15g", row[XCOORD], -row[YCOORD], -row[ZCOORD], column[XCOORD], -column[YCOORD], -column[ZCOORD]); acr_insert_string(&group_list, ACR_Image_orientation_patient, string); /* Look for the position. */ element = acr_find_group_element(group_list, SPI_Image_position); if ((element == NULL) || (acr_get_element_numeric_array(element, WORLD_NDIMS, coord) != WORLD_NDIMS)) { coord[XCOORD] = 0.0; coord[YCOORD] = 0.0; coord[ZCOORD] = 0.0; } else { if (G.Debug >= HI_LOGGING) { printf(" old %.3f %.3f %.3f, ", coord[0], coord[1], coord[2]); } } /* Get the number of rows and columns. */ nrows = acr_find_int(group_list, ACR_Rows, 0); ncolumns = acr_find_int(group_list, ACR_Columns, 0); if ((nrows <= 0) || (ncolumns <= 0)) { printf("ERROR: Illegal image size in Siemens IMA file\n"); exit(1); } /* Get the pixel size */ element = acr_find_group_element(group_list, ACR_Pixel_size); if ((element == NULL) || (acr_get_element_numeric_array(element, IMAGE_NDIMS, pixel_spacing) != IMAGE_NDIMS)) { pixel_spacing[0] = pixel_spacing[1] = 1.0; } /* Calculate the position of the first pixel. This coordinate * is still in the Siemens space, not dicom space and will * need to be flipped. Note that ncolumns is used with row, * since they are the size and unit vector of the same * dimension. */ for (i = 0; i < WORLD_NDIMS; i++) { coord[i] -= pixel_spacing[0] * ((double) ncolumns - 1.0) / 2.0 * row[i] + pixel_spacing[1] * ((double) nrows - 1.0) / 2.0 * column[i]; } sprintf(string, "%.15g\\%.15g\\%.15g", coord[0], -coord[1], -coord[2]); acr_insert_string(&group_list, ACR_Image_position_patient, string); if (G.Debug >= HI_LOGGING) { printf(" new %.3f %.3f %.3f\n", coord[0], -coord[1], -coord[2]); } /* Copy non-standard fields to standard fields. */ group_list = copy_spi_to_acr(group_list); /* If this is a Mosaic image, we need to adjust the pixel spacing * to reflect the ratio between the number of mosaic columns * divided the number of image columns. */ n_slices = acr_find_int(group_list, EXT_Slices_in_file, 1); if (n_slices != 1) { int acq_cols = (int)acr_find_short(group_list, SPI_Acquisition_columns, (Acr_Short)ncolumns); if (G.Debug >= HI_LOGGING) { printf("Hmmm... This appears to be a mosaic image %d %d %d\n", acq_cols, ncolumns, n_slices); } /* Mosaic images in IMA format appear to need to have their * pixel spacing scaled up. I don't fully understand why this * should be necessary, but there it is... */ pixel_spacing[0] *= (double) nrows / (double) acq_cols; pixel_spacing[1] *= (double) ncolumns / (double) acq_cols; sprintf(string, "%.15g\\%.15g", pixel_spacing[0], pixel_spacing[1]); acr_insert_string(&group_list, ACR_Pixel_size, string); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : create__element @INPUT : grp_id elm_id data - pointer to data in Siemens header length - number of values in array (if appropriate) @OUTPUT : (none) @RETURNS : New element containing data @DESCRIPTION: Series of functions to convert Siemens vision header types to ACR-NEMA elements @METHOD : @GLOBALS : @CALLS : @CREATED : July 8, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static Acr_Element_Id get_elid(int grp_id, int elm_id, Acr_VR_Type vr_code) { static struct Acr_Element_Id elid_struct = {0, 0, ACR_VR_UNKNOWN}; elid_struct.group_id = grp_id; elid_struct.element_id = elm_id; elid_struct.vr_code = vr_code; return &elid_struct; } DEFINE_ELEMENT_FUNC(create_char_element) { char *old, *new; int oldsize, newsize, i; /* Get a pointer to the old string */ old = (char *) data; /* Figure out the length of the new string up to the first NUL. Make * sure that there is a room for an additional NUL if necessary */ for (i = 0; (i < length - 1) && (old[i] != '\0'); i++) ; newsize = ((old[i] == '\0') ? i + 1 : length + 1); oldsize = newsize - 1; if ((newsize % 2) != 1) { /* Assure even length overall */ newsize++; } /* Copy the string, making sure that there is a NUL on the end */ new = malloc(newsize); CHKMEM(new); for (i = 0; i < newsize-1; i++) { if (i < oldsize) new[i] = old[i]; else new[i] = ' '; } new[newsize-1] = '\0'; /* Create the element */ return acr_create_element(grp_id, elm_id, ACR_VR_ST, (long) newsize-1, (void *) new); } DEFINE_ELEMENT_FUNC(create_long_element) { Acr_Long data_out; acr_get_long(ACR_BIG_ENDIAN, 1, data, &data_out); return acr_create_element_long(get_elid(grp_id, elm_id, ACR_VR_IS), data_out); } DEFINE_ELEMENT_FUNC(create_short_element) { Acr_Short data_out; acr_get_short(ACR_BIG_ENDIAN, 1, data, &data_out); return acr_create_element_short(get_elid(grp_id, elm_id, ACR_VR_US), data_out); } DEFINE_ELEMENT_FUNC(create_double_element) { Acr_Double data_out; acr_get_double(ACR_BIG_ENDIAN, 1, data, &data_out); return acr_create_element_numeric(get_elid(grp_id, elm_id, ACR_VR_DS), (double)data_out); } DEFINE_ELEMENT_FUNC(create_ima_date_t_element) { string_t string; ima_date_t *ptr; Acr_Long year; Acr_Long month; Acr_Long day; ptr = (ima_date_t *) data; acr_get_long(ACR_BIG_ENDIAN, 1, (long *) &ptr->year, &year); acr_get_long(ACR_BIG_ENDIAN, 1, (long *) &ptr->month, &month); acr_get_long(ACR_BIG_ENDIAN, 1, (long *) &ptr->day, &day); if ((year < 1900) || (year > 9999)) return NULL; if ((month < 1) || (month > 12)) return NULL; if ((day < 1) || (day > 31)) return NULL; sprintf(string, "%04d%02d%02d", (int) year, (int) month, (int) day); return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_DA), (Acr_String)string); } DEFINE_ELEMENT_FUNC(create_ima_time_t_element) { string_t string; ima_time_t *ptr; Acr_Long hour; Acr_Long minute; Acr_Long second; Acr_Long msec; ptr = (ima_time_t *) data; /* Convert data from big endian to native: */ acr_get_long(ACR_BIG_ENDIAN, 1, &ptr->hour, &hour); acr_get_long(ACR_BIG_ENDIAN, 1, &ptr->minute, &minute); acr_get_long(ACR_BIG_ENDIAN, 1, &ptr->second, &second); acr_get_long(ACR_BIG_ENDIAN, 1, &ptr->msec, &msec); if ((hour < 0) || (hour >= 24)) return NULL; if ((minute < 0) || (minute >= 60)) return NULL; if ((second < 0) || (second >= 60)) return NULL; if ((msec < 0) || (msec > 999)) return NULL; sprintf(string, "%02d%02d%02d.%03d", (int) hour, (int) minute, (int) second, (int) msec); return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_TM), (Acr_String)string); } DEFINE_ELEMENT_FUNC(create_modality_element) { Acr_String string; Acr_Long modality; /* Get the appropriate string */ acr_get_long(ACR_BIG_ENDIAN, 1, data, &modality); switch (modality) { case 1: string = "CT"; break; case 2: string = "MR"; break; default: return NULL; } /* Return a new element */ return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), string); } DEFINE_ELEMENT_FUNC(create_sex_element) { Acr_String string; Acr_Long sex; /* Get the appropriate string */ acr_get_long(ACR_BIG_ENDIAN, 1, data, &sex); switch (sex) { case 1: string = "F "; break; case 2: string = "M "; break; case 3: string = "O "; break; default: return NULL; } /* Return a new element */ return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), string); } DEFINE_ELEMENT_FUNC(create_age_element) { string_t string; int i; int is_ok; is_ok = 1; /* The age string has a fixed length of 4 */ memcpy(string, data, 4); string[4] = '\0'; for (i = 0; i < 3; i++) { if (string[i] < '0' || string[i] > '9') { is_ok = 0; } } if (string[3] != 'Y' && string[3] != 'M' && string[3] != 'W' && string[3] != 'D') { is_ok = 0; } if (!is_ok) { printf("WARNING: Invalid age field '%s'\n", string); return NULL; } return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_AS), (Acr_String)string); } DEFINE_ELEMENT_FUNC(create_slice_order_element) { Acr_String string; Acr_Long slice_order; /* Get the appropriate string */ acr_get_long(ACR_BIG_ENDIAN, 1, data, &slice_order); switch ((ima_slice_order_t)slice_order) { case SO_ASCENDING: string = "ASCENDING "; break; case SO_DESCENDING: string = "DESCENDING "; break; case SO_INTERLEAVED: string = "INTERLEAVED "; break; case SO_NONE: string = "NONE "; break; default: string = "UNDEFINED "; break; } /* Return a new element */ return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), string); } DEFINE_ELEMENT_FUNC(create_pixel_spacing_t_element) { pixel_spacing_t *ptr; string_t string; Acr_Double row; Acr_Double col; /* Get the pixel sizes */ ptr = (pixel_spacing_t *) data; /* Convert from big endian to native format */ acr_get_double(ACR_BIG_ENDIAN, 1, &ptr->row, &row); acr_get_double(ACR_BIG_ENDIAN, 1, &ptr->col, &col); sprintf(string, "%.15g\\%.15g", row, col); return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_DS), (Acr_String)string); } DEFINE_ELEMENT_FUNC(create_window_t_element) { window_t *ptr; string_t string; Acr_Long x; Acr_Long y; ptr = (window_t *) data; /* Get the window info */ /* Convert from big endian to native format */ acr_get_long(ACR_BIG_ENDIAN, 1, &ptr->x, &x); acr_get_long(ACR_BIG_ENDIAN, 1, &ptr->y, &y); /* Surely this isn't right? - AJ - (found while chasing warnings) */ /* sprintf(string, "%ld\\%ld", (double)x, (double)y); */ sprintf(string, "%g\\%g", (double)x, (double)y); return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_IS), (Acr_String)string); } DEFINE_ELEMENT_FUNC(create_ima_vector_t_element) { ima_vector_t *ptr; string_t string; Acr_Double x, y, z; /* Get the coordinate */ ptr = (ima_vector_t *) data; acr_get_double(ACR_BIG_ENDIAN, 1, &ptr->x, &x); acr_get_double(ACR_BIG_ENDIAN, 1, &ptr->y, &y); acr_get_double(ACR_BIG_ENDIAN, 1, &ptr->z, &z); sprintf(string, "%.15g\\%.15g\\%.15g", x, y, z); return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_DS), (Acr_String)string); } DEFINE_ELEMENT_FUNC(create_laterality_element) { Acr_Long laterality; Acr_String string; acr_get_long(ACR_BIG_ENDIAN, 1, data, &laterality); switch (laterality) { case 1: string = "L "; break; case 2: string = ""; break; case 3: string = "R "; break; default: return NULL; } return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), string); } DEFINE_ELEMENT_FUNC(create_ima_position_t_element) { Acr_Long position; Acr_String string; acr_get_long(ACR_BIG_ENDIAN, 1, data, &position); switch ((ima_position_t)position) { case PP_LEFT: string = "HFL"; break; case PP_RIGHT: string = "HFR"; break; case PP_PRONE: string = "HFP"; break; case PP_SUPINE: string = "HFS"; break; default: string = ""; break; } return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), string); } DEFINE_ELEMENT_FUNC(create_rest_direction_t_element) { Acr_Long dir; Acr_String string; acr_get_long(ACR_BIG_ENDIAN, 1, data, &dir); switch ((ima_rest_direction_t)dir) { case RD_HEAD: string = "HEAD"; break; case RD_FEET: string = "FEET"; break; default: string = ""; break; } return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), string); } DEFINE_ELEMENT_FUNC(create_view_direction_t_element) { Acr_Long dir; Acr_String string; acr_get_long(ACR_BIG_ENDIAN, 1, data, &dir); switch ((ima_view_direction_t)dir) { case VD_HEAD: string = "HEAD"; break; case VD_FEET: string = "FEET"; break; case VD_AtoP: string = "AtoP"; break; case VD_LtoR: string = "LtoR"; break; case VD_PtoA: string = "PtoA"; break; case VD_RtoL: string = "RtoL"; break; default: string = ""; break; } return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), string); } static void copy_to_space(char *dst_ptr, char *src_ptr, int max_chr) { while (*src_ptr != ' ' && *src_ptr != '\0' && max_chr > 0) { *dst_ptr++ = *src_ptr++; max_chr--; } *dst_ptr = '\0'; } DEFINE_ELEMENT_FUNC(create_ima_orientation_t_element) { ima_orientation_t *po_ptr = (ima_orientation_t *) data; char y[N_ORIENTATION + 1]; char x[N_ORIENTATION + 1]; char z[N_ORIENTATION + 1]; string_t string; copy_to_space(y, po_ptr->y, N_ORIENTATION); copy_to_space(x, po_ptr->x, N_ORIENTATION); copy_to_space(z, po_ptr->z, N_ORIENTATION); sprintf(string, "%s\\%s\\%s", y, x, z); return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_CS), (Acr_String)string); } DEFINE_ELEMENT_FUNC(create_field_of_view_t_element) { ima_field_of_view_t *ptr; string_t string; Acr_Double height; Acr_Double width; ptr = (ima_field_of_view_t *) data; acr_get_double(ACR_BIG_ENDIAN, 1, &ptr->height, &height); acr_get_double(ACR_BIG_ENDIAN, 1, &ptr->width, &width); sprintf(string, "%.15g\\%.15g", height, width); return acr_create_element_string(get_elid(grp_id, elm_id, ACR_VR_DS), (Acr_String)string); } minc-2.2.00/conversion/dcm2mnc/dicom_read.c0000644000265600003100000024125612027132660015412 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dicom_read.c @DESCRIPTION: Code to read siemens dicom files and get info from them. @METHOD : @GLOBALS : @CALLS : @CREATED : January 28, 1997 (Peter Neelin) @MODIFIED : * $Log: dicom_read.c,v $ * Revision 1.29 2010-11-23 23:30:50 claude * dcm2mnc: fixed seg fault bug (Claude) and added b-matrix (Ilana) * * Revision 1.28 2008-08-12 05:00:23 rotor * * large number of changes from Claude (64 bit and updates) * * Revision 1.27 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 1.26 2008/01/11 07:17:07 stever * Remove unused variables. * * Revision 1.25 2007/12/09 19:52:15 alex * Fixed error in echo_time extraction * * Revision 1.24 2007/06/08 20:28:57 ilana * added several fields to mincheader (dicom elements and found in ASCONV header) * * Revision 1.23 2007/05/30 15:17:34 ilana * fix so that diffusion images all written into 1 4d volume, gradient directions and bvalues are written to mincheader, some fixes for TIM diffusion images * * Revision 1.22 2006/04/09 15:38:02 bert * Add support for standard DTI fields * * Revision 1.21 2005/12/05 16:50:08 bert * Deal with weird XMedCon images * * Revision 1.20 2005/10/26 23:43:35 bert * Latest attempt at getting slice spacing consistent * * Revision 1.19 2005/09/16 22:13:33 bert * Fix slice spacing handling * * Revision 1.18 2005/08/26 21:25:54 bert * Latest changes ported from 1.0 branch * * Revision 1.16.2.5 2005/08/26 03:50:16 bert * Use ACR_Number_of_temporal_positions for number of time slices * * Revision 1.16.2.4 2005/08/18 16:38:43 bert * Minor updates for dealing w/older numaris data * * Revision 1.16.2.3 2005/06/20 22:03:01 bert * Add functions for traversing DICOM sequences and recursively hunting for needed fields. * * Revision 1.16.2.2 2005/06/02 17:04:26 bert * 1. Fix handling of signed values for pixel minimum and maximum, 2. Set found_dircos[] when we adopt the default direction cosines for files with null direction cosines * * Revision 1.16.2.1 2005/05/12 21:16:47 bert * Initial checkin * * Revision 1.16 2005/05/09 15:30:32 bert * Don't allow a rescale slope value of zero * * Revision 1.15 2005/04/28 17:17:57 bert * Set and update new width information fields in a manner analogous to the coordinate fields in the General_Info and File_Info structures * * Revision 1.14 2005/04/20 23:14:04 bert * Remove most SPI_ references * * Revision 1.13 2005/04/20 17:47:38 bert * Fairly major restructuring, added init_general_info() function * * Revision 1.12 2005/04/18 21:43:04 bert * Properly set default minimum and maximum values based on the pixel representation * * Revision 1.11 2005/04/18 21:01:51 bert * Set signed/unsigned flag correctly * * Revision 1.10 2005/04/18 20:43:25 bert * Added some additional debugging information for image position and orientation * * Revision 1.9 2005/04/18 16:22:13 bert * Don't allow non-slice MRI dimensions to grow arbitrarily * * Revision 1.8 2005/04/05 21:49:52 bert * Use rescale slope and intercept to determine the proper slice minimum and maximum * * Revision 1.7 2005/03/29 20:21:44 bert * Fix use of slice spacing; fully check for position information if possible, otherwise create a reasonable position from the slice index * * Revision 1.6 2005/03/14 23:29:35 bert * Support basic dynamic PET fields. Also allocate indices and coordinates arrays for all dimensions, even those we won't use. * * Revision 1.5 2005/03/13 19:37:42 bert * Try to use slice location for coordinate when all else fails, also added one debugging message and a check for PET modality * * Revision 1.4 2005/03/03 20:11:00 bert * Consider patient_id and patient_name when sorting into series. Fix handling of missing direction cosines * * Revision 1.3 2005/03/03 18:59:15 bert * Fix handling of image position so that we work with the older field (0020, 0030) as well as the new (0020, 0032) * * Revision 1.2 2005/03/02 20:18:09 bert * Latest fixes and tweaks * * Revision 1.1 2005/02/17 16:38:10 bert * Initial checkin, revised DICOM to MINC converter * * Revision 1.1.1.1 2003/08/15 19:52:55 leili * Leili's dicom server for sonata * * Revision 1.12 2002/05/01 21:29:34 rhoge * removed MrProt from minc header - encountered files with large strings, * causing seg faults * * Revision 1.11 2002/04/26 03:27:03 rhoge * fixed MrProt problem - replaced fixed lenght char array with malloc * * Revision 1.10 2002/04/08 17:26:34 rhoge * added additional sequence info to minc header * * Revision 1.9 2002/03/27 18:57:50 rhoge * added diffusion b value * * Revision 1.8 2002/03/19 13:13:56 rhoge * initial working mosaic support - I think time is scrambled though. * * Revision 1.7 2001/12/31 18:27:21 rhoge * modifications for dicomreader processing of Numaris 4 dicom files - at * this point code compiles without warning, but does not deal with * mosaiced files. Also will probably not work at this time for Numaris * 3 .ima files. dicomserver may also not be functional... * * Revision 1.6 2000/12/14 21:33:13 rhoge * code modifications to restore measurement loop support that was broken * by changes to support acqusition loop scanning * * Revision 1.5 2000/12/13 13:25:36 rhoge * removed dummy printf from convert_time_to_seconds - turns out that * buggy behaviour was an optimization problem * * Revision 1.4 2000/12/12 19:27:52 rhoge * changed atof(acr_find_string) back to acr_find_double after realizing * that these functions assume string representation * * Revision 1.3 2000/12/12 14:43:22 rhoge * fixed syntax error (dangling comment symbol) from removal of debug * printfs - compiles now * * Revision 1.2 2000/12/11 20:01:44 rhoge * fixed code for frame time computation - ACR vals are strings. Also * inserted dummy fprintf statement in convert_time_to_seconds as this * seems to salvage Linux problems * * Revision 1.1.1.1 2000/11/30 02:13:15 rhoge * imported sources to CVS repository on amoeba * -now always use ACR_Series for run number (seemed to be * problems with test introduced in 6.1) * -added code to detect use of acquisition loop and also to handle * `corrected' siemens acq loop scans * -changed code to use registration time instead of scan time for * session id * -got rid of extraneous acquisition id digit * -added technical information about data acquisition * * Revision 6.2 1999/10/29 17:51:58 neelin * Fixed Log keyword * * Revision 6.1 1999/08/05 20:00:34 neelin * Get acquisition id from series or study element, depending on the * version of the Siemens software. * * Revision 6.0 1997/09/12 13:24:27 neelin * Release of minc version 0.6 * * Revision 5.1 1997/09/10 19:36:13 neelin * Small fix to set default direction cosines when they are absent from the * dicom data. * * Revision 5.0 1997/08/21 13:25:26 neelin * Release of minc version 0.5 * * Revision 4.1 1997/06/13 12:51:21 neelin * Changed definition of time index and acquisition id to match change * in Siemens dicom software. * * Revision 4.0 1997/05/07 20:06:20 neelin * Release of minc version 0.4 * * Revision 1.2 1997/03/11 13:10:48 neelin * Working version of dicomserver. * * Revision 1.1 1997/03/04 20:56:47 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "dcm2mnc.h" #define IMAGE_NDIMS 2 static double convert_time_to_seconds(double dicom_time); static void get_intensity_info(Acr_Group group_list, File_Info *file_info); static void get_coordinate_info(Acr_Group group_list, File_Info *file_info, Orientation *orientation, World_Index volume_to_world[VOL_NDIMS], const int sizes[VOL_NDIMS], double dircos[VOL_NDIMS][WORLD_NDIMS], double steps[VOL_NDIMS], double starts[VOL_NDIMS], double coordinate[WORLD_NDIMS]); static void get_general_header_info(Acr_Group group_list, General_Info *general_info); //static void convert_numa3_coordinate(double coordinate[WORLD_NDIMS]); static void get_identification_info(Acr_Group group_list, double *study_id, int *acq_id, int *rec_num, int *image_type); static int irnd(double x) { if (x > 0.0) { x += 0.5; } else { x -= 0.5; } return (int) floor(x); } int is_numaris3(Acr_Group group_list) { return (strstr(acr_find_string(group_list, ACR_Manufacturer, ""), "SIEMENS") != NULL && strstr(acr_find_string(group_list, ACR_Software_versions, ""), "VB33") != NULL); } /* ----------------------------- MNI Header ----------------------------------- @NAME : init_general_info @INPUT : fi_ptr - file-specific info group_list - input data volume_to_world - correspondence of volume to world dimensions spatial_sizes - 3D voxel counts dircos - direction cosines steps - width of each voxel for each spatial dimension starts - starting position for each spatial dimension coordinate - @OUTPUT : gi_ptr - general information about files in this series @RETURNS : (nothing) @DESCRIPTION: Initializes a "General_Info" structure based upon several bits of information, including a previously initialized File_Info structure (fi_ptr) and the DICOM group_list. Broken out from the get_file_info() function to help simplify that function. @METHOD : @GLOBALS : @CALLS : @CREATED : April 19, 2005 (Bert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ static void init_general_info(General_Info *gi_ptr, /* OUT */ const File_Info *fi_ptr, /* IN */ const Acr_Group group_list, /* IN */ const World_Index volume_to_world[VOL_NDIMS], /* IN */ const int spatial_sizes[VOL_NDIMS], /* IN */ double dircos[VOL_NDIMS][WORLD_NDIMS], /* IN */ const double steps[VOL_NDIMS], /* IN */ const double starts[VOL_NDIMS], /* IN */ double study_id, /* IN */ int acq_id, /* IN */ int rec_num) /* IN */ { Acr_Element_Id mri_total_list[MRI_NDIMS]; int ivalue; /* For pixel representation value. */ World_Index iworld; /* World coordinate index (XCOORD, YCOORD...) */ World_Index jworld; /* World coordinate index */ Volume_Index ivolume; /* Voxel coordinate index (VROW, VCOLUMN...) */ Mri_Index imri; int index; // Initialize array for MRI dimension lengths // mri_total_list[SLICE] = ACR_Images_in_acquisition; mri_total_list[ECHO] = ACR_Echo_train_length; mri_total_list[TIME] = ACR_Acquisitions_in_series; mri_total_list[PHASE] = NULL; mri_total_list[CHEM_SHIFT] = NULL; // Get row and columns sizes gi_ptr->nrows = spatial_sizes[VROW]; gi_ptr->ncolumns = spatial_sizes[VCOLUMN]; // Save the study, acquisition, reconstruction and image type // identifiers gi_ptr->study_id = study_id; gi_ptr->acq_id = acq_id; gi_ptr->rec_num = rec_num; strcpy(gi_ptr->image_type_string, acr_find_string(group_list, ACR_Image_type, "")); /* Get dimension information */ for (imri = 0; imri < MRI_NDIMS; imri++) { /* Get sizes along "MRI" dimensions... */ gi_ptr->cur_size[imri] = 1; if (mri_total_list[imri] != NULL) { int def_val = 1; /* Special case for slice index - need to look at the * new standard element 0x0020:0x1002 "Images in * Acquisition". We use this as a default, but override * it with the Siemens-specific value if present. */ if (imri == SLICE) { /* Look for the standard slice count fields first. We * start with the (0054, 0081) first, and if that fails * we retry with (0020, 1002). */ def_val = acr_find_int(group_list, ACR_Number_of_slices, 0); if (def_val == 0) { def_val = acr_find_int(group_list, ACR_Images_in_acquisition, 1); } } if (imri == TIME) { /* Look for the official time slice count field first. */ def_val = acr_find_int(group_list, ACR_Number_of_temporal_positions, 0); def_val = acr_find_int(group_list, ACR_Number_of_time_slices, def_val); /*Sometimes need to look further for time count (ex:segmented FLASH)*/ def_val = acr_find_int(group_list, ACR_Cardiac_number_of_images, def_val); } gi_ptr->max_size[imri] = acr_find_int(group_list, mri_total_list[imri], def_val); } else { gi_ptr->max_size[imri] = 1; } if (gi_ptr->max_size[imri] < 1) { gi_ptr->max_size[imri] = 1; } /* Check for 3D partitions for slice dimensions */ if (imri == SLICE) { /* Get number of 3D partitions for working out number of * slices */ int number_of_3D_partitions = acr_find_int(group_list, SPI_Number_of_3D_raw_partitions_nominal, 1); if (number_of_3D_partitions < 1) { number_of_3D_partitions = 1; } gi_ptr->max_size[imri] *= number_of_3D_partitions; } gi_ptr->default_index[imri] = fi_ptr->index[imri]; gi_ptr->image_index[imri] = -1; /* Allocate space for index and coordinate arrays. * Set the first values. */ gi_ptr->indices[imri] = malloc(gi_ptr->max_size[imri] * sizeof(int)); gi_ptr->coordinates[imri] = malloc(gi_ptr->max_size[imri] * sizeof(double)); gi_ptr->widths[imri] = malloc(gi_ptr->max_size[imri] * sizeof(double)); for (index = 0; index < gi_ptr->max_size[imri]; index++) { gi_ptr->indices[imri][index] = -1; gi_ptr->coordinates[imri][index] = 0; gi_ptr->widths[imri][index] = 0; /* default */ } gi_ptr->search_start[imri] = 0; gi_ptr->indices[imri][0] = fi_ptr->index[imri]; gi_ptr->coordinates[imri][0] = fi_ptr->coordinate[imri]; gi_ptr->widths[imri][0] = fi_ptr->width[imri]; if (G.Debug) { printf("%2d. %s axis length %d\n", imri, Mri_Names[imri], gi_ptr->max_size[imri]); } } /* Loop over dimensions */ /* Get spatial coordinate information */ gi_ptr->slice_world = volume_to_world[VSLICE]; gi_ptr->row_world = volume_to_world[VROW]; gi_ptr->column_world = volume_to_world[VCOLUMN]; for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) { iworld = volume_to_world[ivolume]; gi_ptr->step[iworld] = steps[ivolume]; gi_ptr->start[iworld] = starts[ivolume]; for (jworld = 0; jworld < WORLD_NDIMS; jworld++) { gi_ptr->dircos[iworld][jworld] = dircos[ivolume][jworld]; } if (G.Debug) { printf("%2d. %s axis length %d step %.3f, start %.3f, cosines %.3f,%.3f,%.3f\n", ivolume, World_Names[iworld], spatial_sizes[ivolume], gi_ptr->step[iworld], gi_ptr->start[iworld], gi_ptr->dircos[iworld][XCOORD], gi_ptr->dircos[iworld][YCOORD], gi_ptr->dircos[iworld][ZCOORD] ); } } /* Set data type and range */ if (fi_ptr->bits_alloc <= 8) { gi_ptr->datatype = NC_BYTE; } else { gi_ptr->datatype = NC_SHORT; } /* bert- modify code to correctly read the pixel * representation if available and use that to set the * signed/unsigned flag. */ ivalue = acr_find_int(group_list, ACR_Pixel_representation, -1); if (ivalue == ACR_PIXEL_REP_UNSIGNED) { gi_ptr->is_signed = 0; } else if (ivalue == ACR_PIXEL_REP_SIGNED) { gi_ptr->is_signed = 1; } else { if (ivalue != -1) { printf("WARNING: Unknown pixel representation value %d\n", ivalue); } gi_ptr->is_signed = ((gi_ptr->datatype == NC_SHORT) && (fi_ptr->bits_stored < 16)); } gi_ptr->pixel_min = fi_ptr->pixel_min; gi_ptr->pixel_max = fi_ptr->pixel_max; /* Save display window info */ gi_ptr->window_min = fi_ptr->window_min; gi_ptr->window_max = fi_ptr->window_max; /* Get the rest of the header information */ get_general_header_info(group_list, gi_ptr); /* Copy the group list */ gi_ptr->group_list = acr_copy_group_list(group_list); // note that number of slices will be wrong here for mosaics // we add some other mosaic-relevant fields... gi_ptr->num_mosaic_rows = acr_find_int(group_list, EXT_Mosaic_rows, 1); gi_ptr->num_mosaic_cols = acr_find_int(group_list, EXT_Mosaic_columns, 1); gi_ptr->num_slices_in_file = acr_find_int(group_list, EXT_Slices_in_file, 1); gi_ptr->sub_image_rows = (int)acr_find_short(group_list, EXT_Sub_image_rows, acr_find_short(group_list, ACR_Rows, 0)); gi_ptr->sub_image_columns = (int)acr_find_short(group_list, EXT_Sub_image_columns, acr_find_short(group_list, ACR_Rows, 0)); /* Set initialized flag */ gi_ptr->initialized = TRUE; if (G.Debug) { printf("Pixel minimum %.10f maximum %.10f\n", gi_ptr->pixel_min, gi_ptr->pixel_max); printf("Window minimum %.10f maximum %.10f\n", gi_ptr->window_min, gi_ptr->window_max); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_file_info @INPUT : group_list - input data @OUTPUT : file_inf_p - file-specific info general_info - general information about files @RETURNS : (nothing) @DESCRIPTION: Routine to extract information from a group list @METHOD : @GLOBALS : @CALLS : @CREATED : November 25, 1993 (Peter Neelin) @MODIFIED : Modified Feb. 2000 by Rick Hoge to handle Acquisition loop mode : if assume_acq_loop is FALSE the other added variables don't : matter ---------------------------------------------------------------------------- */ void get_file_info(Acr_Group group_list, File_Info *fi_ptr, General_Info *gi_ptr) { Mri_Index imri; /* MRI index (SLICE, ECHO, TIME, PHASE...) */ int nrows; /* Row count in this file */ int ncolumns; /* Column count in this file */ int spatial_sizes[VOL_NDIMS]; /* Voxel coordinate extents */ double study_id; /* Study identifier */ int acq_id; /* Acquisition identifier */ int rec_num; /* ? Seems to be a dummy */ int cur_index; /* Index of slice(s) in current file */ int index; /* General index value */ Orientation orientation; /* TRANSVERSE, SAGITTAL, or CORONAL */ World_Index volume_to_world[VOL_NDIMS]; /* Maps voxel to world indices */ double coordinate[WORLD_NDIMS]; /* Slice coordinates */ double dircos[VOL_NDIMS][WORLD_NDIMS]; /* Direction cosines */ double steps[VOL_NDIMS]; /* Step (spacing) coordinates */ double starts[VOL_NDIMS]; /* Start (origin) coordinates */ Acr_Element_Id mri_index_list[MRI_NDIMS]; Acr_Element_Id mri_total_list[MRI_NDIMS]; /*added by ilana*/ Acr_Element element; // Array of elements for mri dimensions mri_index_list[SLICE] = SPI_Current_slice_number; mri_index_list[ECHO] = ACR_Echo_number; // dicom time element may be different on old systems mri_index_list[TIME] = ACR_Acquisition; mri_index_list[PHASE] = NULL; mri_index_list[CHEM_SHIFT] = NULL; mri_total_list[SLICE] = SPI_Number_of_slices_nominal; mri_total_list[ECHO] = SPI_Number_of_echoes; mri_total_list[TIME] = ACR_Acquisitions_in_series; mri_total_list[PHASE] = NULL; mri_total_list[CHEM_SHIFT] = NULL; /* Get image dimensions */ nrows = (int)acr_find_short(group_list, ACR_Rows, 0); ncolumns = (int)acr_find_short(group_list, ACR_Columns, 0); spatial_sizes[VROW] = nrows; spatial_sizes[VCOLUMN] = ncolumns; spatial_sizes[VSLICE] = acr_find_int(group_list, ACR_Images_in_acquisition, 1); /* Get intensity information */ get_intensity_info(group_list, fi_ptr); /* Check for necessary values not found */ if ((nrows <= 0) || (ncolumns <= 0) || (fi_ptr->bits_stored <= 0) || (fi_ptr->bits_alloc <= 0)) { if (G.Debug) { printf("ERROR: Needed values missing, marking invalid\n"); } fi_ptr->valid = FALSE; return; } /* Get study, acq, rec, image type id's */ get_identification_info(group_list, &study_id, &acq_id, &rec_num, NULL); /* Get indices for image in current file */ for (imri=0; imri < MRI_NDIMS; imri++) { if (mri_index_list[imri] != NULL) { fi_ptr->index[imri] = /* note that for TIME this will use ACR_Acqusition, which does not work for measurement loop scans */ acr_find_int(group_list, mri_index_list[imri], 1); } else { fi_ptr->index[imri] = 1; } } /* Get coordinate information */ get_coordinate_info(group_list, fi_ptr, &orientation, volume_to_world, spatial_sizes, dircos, steps, starts, coordinate); /* * Use the coordinate information rather than the slice or time * position derived above. This seems to be much more reliable. */ fi_ptr->index[SLICE] = irnd(fi_ptr->coordinate[SLICE] * 100.0); /* For non-IMA files, use the time coordinate to order the time. * index. IMA files do not seem to have a reliable slice time * indicator. */ /*if (G.file_type != IMA) { fi_ptr->index[TIME] = irnd(fi_ptr->coordinate[TIME] * 100.0); }*/ //ilana debug //int test = fi_ptr->coordinate[TIME]; //print ("*******Time coordinate IS: %i\n\n",test); /* Set up general info on first pass */ if (!gi_ptr->initialized) { init_general_info(gi_ptr, fi_ptr, group_list, volume_to_world, spatial_sizes, dircos, steps, starts, study_id, acq_id, rec_num); } /* Set up file info */ /* Update general info and validate file on later passes */ else { /* Check for consistent pixel minimum and maximum. */ if ((gi_ptr->pixel_max != fi_ptr->pixel_max) || (gi_ptr->pixel_min != fi_ptr->pixel_min)) { printf("WARNING: Inconsistent pixel minimum and maximum\n"); printf(" %f %f, %f %f\n", gi_ptr->pixel_min, gi_ptr->pixel_max, fi_ptr->pixel_min, fi_ptr->pixel_max); #if 0 if (gi_ptr->pixel_max < fi_ptr->pixel_max) { gi_ptr->pixel_max = fi_ptr->pixel_max; } if (gi_ptr->pixel_min > fi_ptr->pixel_min) { gi_ptr->pixel_min = fi_ptr->pixel_min; } #endif } /* Check for consistent data type */ if (((gi_ptr->datatype == NC_BYTE) && (fi_ptr->bits_alloc > 8)) || ((gi_ptr->datatype == NC_SHORT) && (fi_ptr->bits_alloc <= 8))) { printf("Inconsistent datatype, marking invalid\n"); fi_ptr->valid = FALSE; return; } /* Check row and columns sizes */ if ((nrows != gi_ptr->nrows) && (ncolumns != gi_ptr->ncolumns)) { printf("Mismatched rows/columns, marking invalid\n"); fi_ptr->valid = FALSE; return; } /* Check study and acquisition id's */ if ((gi_ptr->study_id != study_id) || (gi_ptr->acq_id != acq_id)) { printf("Mismatched acquisition/study, marking invalid\n"); fi_ptr->valid = FALSE; return; } /* Look to see if indices have changed */ for (imri = 0; imri < MRI_NDIMS; imri++) { /* If a dimension is known to have a maximum size of one * or less, we do NOT allow it to grow in any way. An * exception is made for the slice dimension, however, * since it appears that it is common for it to be * unspecified and can be guessed only by the number of * distinct locations discovered. */ if (imri != SLICE && gi_ptr->max_size[imri] <= 1) { continue; } /* Get current index */ cur_index = fi_ptr->index[imri]; //ilana debug //print ("************CURRENT INDEX IS: %i\n\n",cur_index); /* Check whether this index is in the list. */ if (gi_ptr->cur_size[imri] == 1) { index = ((cur_index == gi_ptr->default_index[imri]) ? 0 : -1); } else { /* Search list of indices for 'cur_index'. Search is started at search_start[] and has maximum length of size[imri]. */ index = search_list(cur_index, gi_ptr->indices[imri], gi_ptr->cur_size[imri], gi_ptr->search_start[imri]); } /* If it is not, then add it */ if (index < 0) { if (G.Debug >= HI_LOGGING) { printf("Need to add index %d to %s list, %d/%d\n", cur_index, Mri_Names[imri], gi_ptr->cur_size[imri], gi_ptr->max_size[imri]); } /* Check whether we can add a new index */ if (gi_ptr->cur_size[imri] >= gi_ptr->max_size[imri]) { gi_ptr->max_size[imri]++; gi_ptr->indices[imri] = realloc(gi_ptr->indices[imri], gi_ptr->max_size[imri] * sizeof(int)); gi_ptr->coordinates[imri] = realloc(gi_ptr->coordinates[imri], gi_ptr->max_size[imri] * sizeof(double)); gi_ptr->widths[imri] = realloc(gi_ptr->widths[imri], gi_ptr->max_size[imri] * sizeof(double)); } /* Add the index and coordinate to the lists */ index = gi_ptr->cur_size[imri]; gi_ptr->search_start[imri] = index; gi_ptr->indices[imri][index] = cur_index; gi_ptr->coordinates[imri][index] = fi_ptr->coordinate[imri]; gi_ptr->widths[imri][index] = fi_ptr->width[imri]; gi_ptr->cur_size[imri]++; } } /* Loop over Mri_Index */ // Update display window info if (gi_ptr->window_min > fi_ptr->window_min) gi_ptr->window_min = fi_ptr->window_min; if (gi_ptr->window_max < fi_ptr->window_max) gi_ptr->window_max = fi_ptr->window_max; } // Update general info for this file /* Get DTI information if available. */ fi_ptr->b_value = (double)acr_find_double(group_list, ACR_Diffusion_b_value, -1); element = acr_find_group_element(group_list, ACR_Diffusion_gradient_orientation); Acr_Double grad_direction[WORLD_NDIMS]; if (element == NULL || acr_get_element_double_array(element, WORLD_NDIMS, grad_direction) != WORLD_NDIMS) { grad_direction[XCOORD] = grad_direction[YCOORD] = grad_direction[ZCOORD] = 0; /*this should be 0 for the b=0 images*/ } fi_ptr->grad_direction[XCOORD] = (double)grad_direction[XCOORD]; fi_ptr->grad_direction[YCOORD] = (double)grad_direction[YCOORD]; fi_ptr->grad_direction[ZCOORD] = (double)grad_direction[ZCOORD]; /*Want to add B-matrix if it exists, the problem is that the b=0 image does not even have the field (0019x1027) while the other directions might (AND b=0 is ofen the first image!). Initialize to all 0s and decide later whether to include in header? */ if (gi_ptr->acq.dti) { element = acr_find_group_element(group_list, ACR_B_matrix); int num_bmatrix_elements=6;/*bmatrix should have 6 values*/ if (element == NULL || acr_get_element_double_array(element, num_bmatrix_elements, fi_ptr->b_matrix) != num_bmatrix_elements) { int i=0; for(i;ib_matrix[i]=0; /*bmatrix for b=0 should be 0*/ } } } // If we get to here, then we have a valid file fi_ptr->valid = TRUE; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_identification_info @INPUT : group_list - input data @OUTPUT : study_id acq_id rec_num image_type @RETURNS : (nothing) @DESCRIPTION: Routine to get image identification information. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_identification_info(Acr_Group group_list, double *study_id, int *acq_id, int *rec_num, int *image_type) { int number_of_frames; int number_of_averages; if (study_id != NULL) { // generate a study ID number from date & time: yyyymmdd.hhmmss // (should be unique enough for our application) *study_id = (((float)acr_find_int(group_list, ACR_Study_date, 0)) + ((float)acr_find_int(group_list, ACR_Study_time, 0))/1e6); } if (acq_id != NULL) { *acq_id = acr_find_int(group_list, ACR_Series, 0); number_of_frames = acr_find_int(group_list, ACR_Acquisitions_in_series, 1); number_of_averages = acr_find_int(group_list, ACR_Nr_of_averages, 1); /* Determine if measurement loop was used (rhoge) - if so, we replace the different series numbers with ACR_Study_time, which is the same for all frames in a run. This will aid in grouping the files later on. Criteria used for identification of meast loop: 1) more than one dynamic scan 2) number of dynamic scans NOT equal to nominal number of signal averages (if they're equal, we assume acquisition loop scan) WARNING: it is possible that someone might use the measurement loop do serial scans which each have multiple signal averages. If NSA = the number of measts. in this case, then the scan will not be recognized as a Meast loop scan and the different frames will be placed in different series. To fix this, we'd really need to look at the series numbers of future and past files. It's also unlikely to happen but I'm sure it will... This also means we should NOT correct the number of signal averages on the sending side */ /* if ((number_of_frames > 1) || (*acq_id == 0)) { (orig test) */ if ( (G.file_type == N3DCM) && (number_of_frames > 1) && (number_of_frames != number_of_averages)) { *acq_id = acr_find_int(group_list, ACR_Study_time, 0); } } if (rec_num != NULL) *rec_num = 0; if (image_type != NULL) *image_type = 0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_intensity_info @INPUT : group_list - input data @OUTPUT : fi_ptr - file-specific info @RETURNS : (nothing) @DESCRIPTION: Routine to get intensity information from a group list @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_intensity_info(Acr_Group group_list, File_Info *fi_ptr) { double window_centre, window_width; double rescale_intercept, rescale_slope; int ivalue; /* 0000 for unsigned, 0001 for signed */ int imin, imax; /* Default minimum and maximum values */ /* Get pixel storage information */ fi_ptr->bits_alloc = (int)acr_find_short(group_list, ACR_Bits_allocated, 0); fi_ptr->bits_stored = (int)acr_find_short(group_list, ACR_Bits_stored, 0); /* bert- properly set the minimum and maximum pixel values depending * on whether or not this file specifies signed pixel values. */ ivalue = acr_find_int(group_list, ACR_Pixel_representation, -1); if (ivalue == ACR_PIXEL_REP_SIGNED) { imin = -(1 << (fi_ptr->bits_stored - 1)); imax = (1 << (fi_ptr->bits_stored - 1)) - 1; } else { imin = 0; imax = (1 << fi_ptr->bits_stored) - 1; } if (G.useMinMax) { int pmin; int pmax; /* Get pixel value information * I think this might wrongly assume that the ACR values min/max * apply to the whole volume - it actually appears that they apply * to the current slice. */ pmin = (int)acr_find_short(group_list, ACR_Smallest_pixel_value, imin); pmax = (int)acr_find_short(group_list, ACR_Largest_pixel_value, imax); /* Hack to convert to signed representation if indicated - if * bit 15 is set, we have to "promote" to 2's complement by * sign-extending the result before converting it to a double. * Perhaps this sort of thing needs to be pushed down into the * ACR-NEMA library somehow, so that the representations of * short values are automatically converted properly? */ if (ivalue == ACR_PIXEL_REP_SIGNED) { if (pmin & 0x8000) { pmin -= 0x10000; } if (pmax & 0x8000) { pmax -= 0x10000; } } fi_ptr->pixel_min = (double) pmin; fi_ptr->pixel_max = (double) pmax; } else { /* for now, use bits_stored to determine dynamic range * DICOM info on largest pixel applies to first slice, * not whole volume - this caused problems (roundoff?) * in Siemens Numaris 4 scans */ fi_ptr->pixel_min = imin; fi_ptr->pixel_max = imax; } /* Get the rescale intercept and slope. If they are not present, * we use the default values of 0.0 for the intercept and 1.0 for * the slope. */ rescale_intercept = (double)acr_find_double(group_list, ACR_Rescale_intercept, 0); rescale_slope = (double)acr_find_double(group_list, ACR_Rescale_slope, 1); /* If the rescale slope is set to zero, force the default value of * one and issue a warning. */ if (rescale_slope == 0.0) { printf("WARNING: File contains a rescale slope value of zero.\n"); rescale_slope = 1.0; } fi_ptr->slice_min = fi_ptr->pixel_min * rescale_slope + rescale_intercept; fi_ptr->slice_max = fi_ptr->pixel_max * rescale_slope + rescale_intercept; /* Get window min and max */ window_centre = (fi_ptr->slice_max + fi_ptr->slice_min) / 2.0; window_width = fi_ptr->slice_max - fi_ptr->slice_min; window_centre = (double)acr_find_double(group_list, ACR_Window_centre, window_centre); window_width = (double)acr_find_double(group_list, ACR_Window_width, window_width); fi_ptr->window_min = window_centre - window_width / 2.0; fi_ptr->window_max = window_centre + window_width / 2.0; } /* Function to recursively search an element list for a specific * element, skipping a specified number of occurrences before * returning. This is only called by acr_recurse_for_element(). */ static Acr_Element acr_recursive_search(Acr_Element el_lst, int *nskip, Acr_Element_Id srch_id) { Acr_Element el_ret = NULL; Acr_Element el_tmp; for (el_tmp = el_lst; el_tmp != NULL; el_tmp = acr_get_element_next(el_tmp)) { /* If we find what we're looking for, return it. */ if (acr_get_element_group(el_tmp) == srch_id->group_id && acr_get_element_element(el_tmp) == srch_id->element_id) { if (*nskip <= 0) { el_ret = el_tmp; break; } else { --(*nskip); } } /* See if we need to recurse. */ if (acr_element_is_sequence(el_tmp)) { el_lst = (Acr_Element) acr_get_element_data(el_tmp); el_ret = acr_recursive_search(el_lst, nskip, srch_id); if (el_ret != NULL) { break; } } } return (el_ret); } /* acr_recurse_for_element() * * Function to search a group list for a particular element. Unlike other * functions along these lines, this function will recursively descend into * compound datatypes (DICOM sequences) to hunt for instances of a particular * element. * * The search proceeds in two stages: The first is to search for * a particular sequence object. This must be found or else the search is * called off. Once the expected sequences is found, the function will * recursively search all of the substructure of that sequence for the * requested subelement. The "nskip" parameter tells the function to ignore * the first "nskip" matches that it locates. */ Acr_Element acr_recurse_for_element(Acr_Group group_list, int nskip, Acr_Element_Id seq_id, Acr_Element_Id srch_id) { Acr_Element el_seq; /* Hunt for the necessary sequence object. */ el_seq = acr_find_group_element(group_list, seq_id); if (el_seq == NULL || !acr_element_is_sequence(el_seq)) { /* If not found, or not a sequence, abort the search. */ return (NULL); } /* Otherwise proceed to "stage 2" and hunt for the requested subelement. */ return acr_recursive_search((Acr_Element) acr_get_element_data(el_seq), &nskip, srch_id); } int dicom_read_position(Acr_Group group_list, int n, double coordinate[3]) { Acr_Element element; int result; /* Try to read a unique element from the sequences. If this * succeeds, we need to flag this fact so that the higher-level * processing can adapt accordingly. */ element = acr_recurse_for_element(group_list, n, ACR_Perframe_func_groups_seq, ACR_Image_position_patient); if (element != NULL) { result = DICOM_POSITION_LOCAL; /* Found a slice-specific position */ } else { result = DICOM_POSITION_GLOBAL; /* Found a global position */ /* bert-look for field in weird XMedCon location */ element = acr_recurse_for_element(group_list, 0, ACR_Detector_information_seq, ACR_Image_position_patient); if (element == NULL) { element = acr_find_group_element(group_list, ACR_Image_position_patient); } if (element == NULL) { element = acr_find_group_element(group_list, ACR_Image_position_patient_old); } } if (element == NULL) { printf("WARNING: Failed to find image position\n"); } else { if (acr_get_element_numeric_array(element, WORLD_NDIMS, coordinate) == WORLD_NDIMS) { return (result); } if (G.Debug) { printf("WARNING: Failed to read image position ('%s')\n", (char *)acr_get_element_string(element)); } } return DICOM_POSITION_NONE; } int dicom_read_orientation(Acr_Group group_list, double orientation[6]) { Acr_Element element; int result; /* read in row/col vectors: */ /* Look for single global header with slices all in same file. */ element = acr_recurse_for_element(group_list, 0, ACR_Shared_func_groups_seq, ACR_Image_orientation_patient); /* Look for single local header with slices all in same file, with one header per slice (Philips Intera). */ if (element == NULL) { element = acr_recurse_for_element(group_list, 0, ACR_Perframe_func_groups_seq, ACR_Image_orientation_patient); } /* bert - deal with weird XMedCon images... */ if (element == NULL) { element = acr_recurse_for_element(group_list, 0, ACR_Detector_information_seq, ACR_Image_orientation_patient); } /* Look for header with slices in separate files. */ if (element == NULL) { element = acr_find_group_element(group_list, ACR_Image_orientation_patient); } if (element == NULL) { /* If we failed to find the newer, better patient orientation * information, try to use the obsolete information if present. */ element = acr_find_group_element(group_list, ACR_Image_orientation_patient_old); } if (element == NULL) { printf("WARNING: Failed to find image orientation!\n"); return (0); } else if ((result = acr_get_element_numeric_array(element, 6, orientation)) != 6) { printf("WARNING: Failed to read image orientation! (%d, '%s')\n", result, (char *)acr_get_element_string(element)); return (0); } return (1); } /* * Read the pixel size, an array of 2 floating point numbers, from the * DICOM group list. */ int dicom_read_pixel_size(Acr_Group group_list, double pixel_size[IMAGE_NDIMS]) { Acr_Element element; int result = 0; int i; for (i = 0; i < IMAGE_NDIMS; i++) { pixel_size[i] = -DBL_MAX; } /* Look for single global header with slices all in same file. */ element = acr_recurse_for_element(group_list, 0, ACR_Shared_func_groups_seq, ACR_Pixel_size); /* Look for single local header with slices all in same file, with one header per slice (Philips Intera). */ if (element == NULL) { element = acr_recurse_for_element(group_list, 0, ACR_Perframe_func_groups_seq, ACR_Pixel_size); } /* Look for header with slices in separate files. */ if (element == NULL) { element = acr_find_group_element(group_list, ACR_Pixel_size); } if (element == NULL) { printf("WARNING: Can't find pixel size element\n"); } else { /* Extract sizes from header string if found. */ if (acr_get_element_numeric_array(element, IMAGE_NDIMS, pixel_size) != IMAGE_NDIMS) { printf("WARNING: Can't read pixel size element\n"); } else { result = 1; } } /* If the values are still uninitialized, set them to some reasonable * defaults. */ if (pixel_size[0] == -DBL_MAX) { pixel_size[0] = 1.0; /* Assume 1mm spacing */ } if (pixel_size[1] == -DBL_MAX) { pixel_size[1] = pixel_size[0]; /* Assume uniform sample grid. */ } return (result); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_coordinate_info @INPUT : group_list - input data sizes - size of each spatial dimension @OUTPUT : fi_ptr - file-specific info volume_to_world - volume index to world coordinate index mapping dircos - direction cosines for spatial dimensions steps - step sizes for spatial dimensions starts - start positions for spatial dimensions (for a slice) coordinate - coordinate of centre of slice @RETURNS : (nothing) @DESCRIPTION: Routine to get coordinate information for a slice from a group list @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_coordinate_info(Acr_Group group_list, File_Info *fi_ptr, Orientation *orientation, World_Index volume_to_world[VOL_NDIMS], const int sizes[VOL_NDIMS], double dircos[VOL_NDIMS][WORLD_NDIMS], double steps[VOL_NDIMS], double starts[VOL_NDIMS], double coordinate[WORLD_NDIMS]) { Volume_Index ivolume; World_Index iworld; int found_dircos[VOL_NDIMS]; int found_coordinate; double frame_time; double start_time; double magnitude; double largest; double psize[IMAGE_NDIMS]; double slice_thickness, slice_spacing; double RowColVec[6]; /* row/column unit vectors in public dicom element */ const Orientation orientation_list[WORLD_NDIMS] = { SAGITTAL, CORONAL, TRANSVERSE }; if (G.Debug >= HI_LOGGING) { printf("get_coordinate_info(%lx, ...)\n", (unsigned long) group_list); } /* Initialize a few things... */ for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) { found_dircos[ivolume] = FALSE; } found_coordinate = FALSE; #if 0 /* TODO: For now this appears to be necessary. In cases I don't fully * understand, the Siemens Numaris 3 DICOM image orientation does not * give the correct direction cosines, so we use the nonstandard Siemens * fields instead. Someday I should figure out the relation (if any) * between the standard fields and these fields, and try to normalize * this mess. * * We only attempt this for files that are clearly marked as SIEMENS * files, with a version string that looks like VB33 (VB33D, VB33G, etc.) * Later versions do not seem to use these fields. */ if (is_numaris3(group_list)) { Acr_Element_Id dircos_elid[VOL_NDIMS]; /* Set direction cosine element ids. Note that the reversal of * rows and columns is intentional - their idea of the meaning * of theses labels is different from ours. (Their row vector * points along the row and not along the row dimension.) */ dircos_elid[VSLICE] = SPI_Image_normal; dircos_elid[VROW] = SPI_Image_column; dircos_elid[VCOLUMN] = SPI_Image_row; /* Get direction cosines */ for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) { element = acr_find_group_element(group_list, dircos_elid[ivolume]); if (element == NULL) { continue; } if (acr_get_element_numeric_array(element, WORLD_NDIMS, dircos[ivolume]) != WORLD_NDIMS) { continue; } /* negate the X and Z coordinates */ convert_numa3_coordinate(dircos[ivolume]); found_dircos[ivolume] = TRUE; } } #endif /* If we did not find the Siemens proprietary image vectors, try * the DICOM standard image position. */ if (!found_dircos[VCOLUMN] || !found_dircos[VROW] || !found_dircos[VSLICE]) { if (dicom_read_orientation(group_list, RowColVec)) { dircos[VCOLUMN][XCOORD] = RowColVec[0]; dircos[VCOLUMN][YCOORD] = RowColVec[1]; dircos[VCOLUMN][ZCOORD] = RowColVec[2]; dircos[VROW][XCOORD] = RowColVec[3]; dircos[VROW][YCOORD] = RowColVec[4]; dircos[VROW][ZCOORD] = RowColVec[5]; found_dircos[VCOLUMN] = TRUE; found_dircos[VROW] = TRUE; convert_dicom_coordinate(dircos[VROW]); convert_dicom_coordinate(dircos[VCOLUMN]); /* slice direction unit vector is cross product of row, col vectors: */ dircos[VSLICE][XCOORD] = dircos[VCOLUMN][YCOORD] * dircos[VROW][ZCOORD] - dircos[VCOLUMN][ZCOORD] * dircos[VROW][YCOORD]; dircos[VSLICE][YCOORD] = dircos[VCOLUMN][ZCOORD] * dircos[VROW][XCOORD] - dircos[VCOLUMN][XCOORD] * dircos[VROW][ZCOORD]; dircos[VSLICE][ZCOORD] = dircos[VCOLUMN][XCOORD] * dircos[VROW][YCOORD] - dircos[VCOLUMN][YCOORD] * dircos[VROW][XCOORD]; found_dircos[VSLICE] = TRUE; } } if (G.Debug >= HI_LOGGING) { printf("dircos %f %f %f %f %f %f %f %f %f\n", dircos[VSLICE][XCOORD], dircos[VSLICE][YCOORD], dircos[VSLICE][ZCOORD], dircos[VROW][XCOORD], dircos[VROW][YCOORD], dircos[VROW][ZCOORD], dircos[VCOLUMN][XCOORD], dircos[VCOLUMN][YCOORD], dircos[VCOLUMN][ZCOORD]); } /* Normalize the direction cosines */ for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) { magnitude = 0.0; for (iworld=0; iworld < WORLD_NDIMS; iworld++) { magnitude += dircos[ivolume][iworld] * dircos[ivolume][iworld]; } if (magnitude <= 0) { found_dircos[ivolume] = FALSE; continue; } magnitude = sqrt(magnitude); for (iworld=0; iworld < WORLD_NDIMS; iworld++) { dircos[ivolume][iworld] /= magnitude; } } /* If we don't find direction cosines, then assume transverse volume */ if (!found_dircos[VSLICE] || !found_dircos[VROW] || !found_dircos[VCOLUMN]) { if (G.Debug) { printf("Using default direction cosines\n"); } for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) { for (iworld = 0; iworld < WORLD_NDIMS; iworld++) { dircos[ivolume][iworld] = ((ivolume == (WORLD_NDIMS-iworld-1)) ? -1.0 : 0.0); found_dircos[iworld] = TRUE; } } } /* Figure out volume index to world index mapping and sign of direction * cosines - the code below figures out the primary direction in x,y,z * of each volume coordinate (row,col,slice) */ for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) { largest = -1.0; for (iworld = 0; iworld < WORLD_NDIMS; iworld++) { magnitude = dircos[ivolume][iworld]; if (magnitude < 0.0) magnitude = -magnitude; if (magnitude > largest) { largest = magnitude; volume_to_world[ivolume] = iworld; } } } if (G.Debug >= HI_LOGGING) { printf(" Volume_to_world slice=%s row=%s column=%s\n", World_Names[volume_to_world[VSLICE]], World_Names[volume_to_world[VROW]], World_Names[volume_to_world[VCOLUMN]]); } /* Get orientation (depends on primary direction of slice normal) */ *orientation = orientation_list[volume_to_world[VSLICE]]; if (G.Debug >= HI_LOGGING) { printf(" Orientation is %s\n", (*orientation == SAGITTAL) ? "SAGITTAL" : (*orientation == CORONAL) ? "CORONAL" : "TRANSVERSE"); } /* Get step information */ dicom_read_pixel_size(group_list, psize); steps[VCOLUMN] = psize[0]; steps[VROW] = psize[1]; /* anisotropic resolution? */ /* Figure out the slice thickness. It could be from either one of * two possible places in the file. * * This code has changed several times, and there may be no single * correct way of deriving the true slice spacing from the official * DICOM slice thickness and slice spacing fields. My best guess is * to look for both fields, and to adopt the */ slice_thickness = (double)acr_find_double(group_list, ACR_Slice_thickness, 0); slice_spacing = (double)acr_find_double(group_list, ACR_Spacing_between_slices, 0); if (slice_thickness == 0.0) { /* No slice thickness value found. */ if (slice_spacing == 0.0) { if (G.Debug >= HI_LOGGING) { printf("Using default slice thickness of 1.0\n"); } steps[VSLICE] = 1.0; } else { if (G.Debug >= HI_LOGGING) { printf("Using (0018,0088) for slice thickness\n"); } steps[VSLICE] = slice_spacing; } } else if (slice_spacing == 0.0) { /* No slice spacing value found. */ if (G.Debug >= HI_LOGGING) { printf("Using (0018,0050) for slice thickness\n"); } steps[VSLICE] = slice_thickness; } else { /* Both fields are set. I choose the slice spacing rather * than the slice thickness in this case. However, I believe * there is some evidence that this can cause problems in rare * cases. */ if (G.Debug && !NEARLY_EQUAL(slice_thickness, slice_spacing)) { printf("WARNING: slice thickness conflict: "); printf("old = %.10f, new = %.10f\n", slice_thickness, slice_spacing); } steps[VSLICE] = slice_spacing; } /* Make sure that direction cosines point the right way (dot * product of direction cosine and axis is positive) and that step * has proper sign. */ for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) { iworld = volume_to_world[ivolume]; if (dircos[ivolume][iworld] < 0.0) { if (G.Debug >= HI_LOGGING) { printf("Swapping direction of %s %s\n", Volume_Names[ivolume], World_Names[iworld]); } steps[ivolume] *= -1.0; for (iworld = 0; iworld < WORLD_NDIMS; iworld++) { dircos[ivolume][iworld] *= -1.0; } } } /* Find 3D coordinate of slice - ACR_Image_position_patient gives * the *corner* of the slice! * * Start by assuming that we didn't find it. */ found_coordinate = FALSE; for (iworld = 0; iworld < WORLD_NDIMS; iworld++) { coordinate[iworld] = 0.0; } if (G.opts & OPTS_NO_LOCATION) { /* If the coordinates are untrustworthy, just generate something * reasonable for the slice coordinate. Ignore the rest. */ coordinate[volume_to_world[VSLICE]] = (steps[VSLICE] * fi_ptr->index[SLICE]); found_coordinate = TRUE; } else { found_coordinate = dicom_read_position(group_list, fi_ptr->index[SLICE] - 1, coordinate); if (!found_coordinate) { /* Last gasp - try to interpret the slice location as our slice * position. It might work. */ if (!found_coordinate) { coordinate[volume_to_world[VSLICE]] = (double)acr_find_double(group_list, ACR_Slice_location, 1.0); } found_coordinate = TRUE; } } convert_dicom_coordinate(coordinate); /* Work out start positions in volume coordinates */ for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) { if (found_coordinate && found_dircos[VSLICE] && found_dircos[VROW] && found_dircos[VCOLUMN]) { starts[ivolume] = coordinate[XCOORD] * dircos[ivolume][XCOORD] + coordinate[YCOORD] * dircos[ivolume][YCOORD] + coordinate[ZCOORD] * dircos[ivolume][ZCOORD]; } else { starts[ivolume] = 0.0; } } if (G.Debug >= HI_LOGGING) { printf(" coordinate %f %f %f, start %f %f %f\n", coordinate[XCOORD], coordinate[YCOORD], coordinate[ZCOORD], starts[VROW], starts[VCOLUMN], starts[VSLICE]); } /* Find position along each dimension */ fi_ptr->coordinate[SLICE] = starts[VSLICE]; fi_ptr->coordinate[ECHO] = (double)acr_find_double(group_list, ACR_Echo_time, 0.0) / MS_PER_SECOND; /* Get the dimension width for time, if available. The units are in * milliseconds in DICOM, whereas we use seconds in MINC. */ fi_ptr->width[TIME] = (double)acr_find_double(group_list, ACR_Actual_frame_duration, 0.0) / MS_PER_SECOND; /* PET scan times (bert) */ start_time = (double)acr_find_double(group_list, ACR_Frame_reference_time, -1.0); frame_time = (double)acr_find_double(group_list, ACR_Actual_frame_duration, -1.0); if (start_time > 0.0 && frame_time > 0.0) { frame_time = start_time / 1000.0; /* Convert msec to seconds. */ } else { /* time section (rhoge) * now assume that time has been fixed when file was read */ start_time = (double)acr_find_double(group_list, ACR_Series_time, 0.0); frame_time = (double)acr_find_double(group_list, ACR_Acquisition_time, 0.0); start_time = convert_time_to_seconds(start_time); frame_time = convert_time_to_seconds(frame_time) - start_time; /* check for case where scan starts right before midnight, * but frame is after midnight */ if (frame_time < 0.0) { frame_time += SECONDS_PER_DAY; } } fi_ptr->coordinate[TIME] = frame_time; /* end of time section */ fi_ptr->coordinate[PHASE] = 0.0; fi_ptr->coordinate[CHEM_SHIFT] = 0.0; } #if 0 /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_numa3_coordinate @INPUT : coordinate @OUTPUT : coordinate @RETURNS : (nothing) @DESCRIPTION: Routine to convert a coordinate to the correct orientation @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : made version specific to Numaris 3 SPI data (rhoge) ---------------------------------------------------------------------------- */ static void convert_numa3_coordinate(double coordinate[WORLD_NDIMS]) { coordinate[XCOORD] = -coordinate[XCOORD]; coordinate[ZCOORD] = -coordinate[ZCOORD]; } #endif /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_dicom_coordinate @INPUT : coordinate @OUTPUT : coordinate @RETURNS : (nothing) @DESCRIPTION: Routine to convert a coordinate to the correct orientation @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : made new dicom version (rhoge) ---------------------------------------------------------------------------- */ void convert_dicom_coordinate(double coordinate[WORLD_NDIMS]) { /* Allow the user to override this, if only for debugging purposes... */ if (G.opts & OPTS_KEEP_COORD) { return; } coordinate[XCOORD] = -coordinate[XCOORD]; coordinate[YCOORD] = -coordinate[YCOORD]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_general_header_info @INPUT : group_list - input data @OUTPUT : gi_ptr - general information about files @RETURNS : (nothing) @DESCRIPTION: Routine to extract general header information from a group list @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_string_field(char *out_str, Acr_Group group_list, Acr_Element_Id element_id) { strncpy(out_str, acr_find_string(group_list, element_id, ""), STRING_T_LEN); } void get_general_header_info(Acr_Group group_list, General_Info *gi_ptr) { int length; char *string; if (G.Debug) { printf("SOP Class UID: %s\n", acr_find_string(group_list, ACR_SOP_Class_UID, "")); printf("Images in acquisition: %d\n", acr_find_int(group_list, ACR_Images_in_acquisition, -1)); printf("Acquisitions in series: %d\n", acr_find_int(group_list, ACR_Acquisitions_in_series, -1)); printf("3D raw partitions: %d\n", acr_find_int(group_list, SPI_Number_of_3D_raw_partitions_nominal, -1)); } /* Get intensity units */ strncpy(gi_ptr->units, "", STRING_T_LEN); /* Get patient info */ get_string_field(gi_ptr->patient.name, group_list, ACR_Patient_name); get_string_field(gi_ptr->patient.identification, group_list, ACR_Patient_identification); get_string_field(gi_ptr->patient.birth_date, group_list, ACR_Patient_birth_date); get_string_field(gi_ptr->patient.age, group_list, ACR_Patient_age); string = (char*)acr_find_string(group_list, ACR_Patient_sex, ""); if (*string == 'M') strncpy(gi_ptr->patient.sex, MI_MALE, STRING_T_LEN); else if (*string == 'F') strncpy(gi_ptr->patient.sex, MI_FEMALE, STRING_T_LEN); else if (*string == 'O') strncpy(gi_ptr->patient.sex, MI_OTHER, STRING_T_LEN); else strncpy(gi_ptr->patient.sex, "", STRING_T_LEN); gi_ptr->patient.weight = (double)acr_find_double(group_list, ACR_Patient_weight, -DBL_MAX); /* added by rhoge - registration timing info */ get_string_field(gi_ptr->patient.reg_date, group_list, ACR_Study_date); get_string_field(gi_ptr->patient.reg_time, group_list, ACR_Study_time); get_string_field(gi_ptr->patient.position, /*position of patient added by ilana*/ group_list, ACR_Patient_position); /* Get study info */ /*some more timing info added by ilana*/ get_string_field(gi_ptr->acq.series_time, group_list, ACR_Series_time); get_string_field(gi_ptr->study.start_time, group_list, ACR_Study_date); length = strlen(gi_ptr->study.start_time); gi_ptr->study.start_time[length] = ' '; length++; strncpy(&gi_ptr->study.start_time[length], acr_find_string(group_list, ACR_Study_time, ""), STRING_T_LEN - length); string = (char*)acr_find_string(group_list, ACR_Modality, ""); if (strcmp(string, ACR_MODALITY_MR) == 0) strncpy(gi_ptr->study.modality, MI_MRI, STRING_T_LEN); else if (strcmp(string, ACR_MODALITY_PT) == 0) strncpy(gi_ptr->study.modality, MI_PET, STRING_T_LEN); get_string_field(gi_ptr->study.manufacturer, group_list, ACR_Manufacturer); get_string_field(gi_ptr->study.model, group_list, ACR_Manufacturer_model); gi_ptr->study.field_value = (double)acr_find_double(group_list, ACR_Magnetic_field_strength, -DBL_MAX); get_string_field(gi_ptr->study.software_version, group_list, ACR_Software_versions); get_string_field(gi_ptr->study.serial_no, group_list, ACR_Device_serial_number); get_string_field(gi_ptr->study.calibration_date, group_list, ACR_Calibration_date); get_string_field(gi_ptr->study.calibration_time, /*add time as well ilana*/ group_list, ACR_Calibration_time); get_string_field(gi_ptr->study.institution, group_list, ACR_Institution_id); get_string_field(gi_ptr->study.station_id, group_list, ACR_Station_id); get_string_field(gi_ptr->study.referring_physician, group_list, ACR_Referring_physician); get_string_field(gi_ptr->study.performing_physician, group_list, ACR_Performing_physician); get_string_field(gi_ptr->study.operator, group_list, ACR_Operators_name); get_string_field(gi_ptr->study.procedure, group_list, ACR_Procedure_description); sprintf(gi_ptr->study.study_id, "%.6f",gi_ptr->study_id); /* Acquisition id modified by rhoge to get rid of first digit that is not required for identification of run */ /* sprintf(gi_ptr->study.acquisition_id, "%d_%d", acr_find_int(group_list, ACR_Series, 0), gi_ptr->acq_id); */ sprintf(gi_ptr->study.acquisition_id, "%d", gi_ptr->acq_id); /* Get acquisition information */ get_string_field(gi_ptr->acq.acquisition_time, group_list, ACR_Acquisition_time); /*add acquisition start time ilana*/ get_string_field(gi_ptr->acq.image_time, group_list, ACR_Image_time); get_string_field(gi_ptr->acq.scan_seq, group_list, ACR_Sequence_name); get_string_field(gi_ptr->acq.protocol_name, group_list, ACR_Protocol_name); get_string_field(gi_ptr->acq.series_description, /*add series description ilana*/ group_list, ACR_Series_description); get_string_field(gi_ptr->acq.receive_coil, group_list, ACR_Receive_coil_name); get_string_field(gi_ptr->acq.transmit_coil, group_list, ACR_Transmit_coil_name); get_string_field(gi_ptr->acq.slice_order, group_list, EXT_Slice_order); /*0x1 means ASCENDING 0x2 means DESCENDING 0x4 means INTERLEAVED*/ if(!strcmp(gi_ptr->acq.slice_order,"0x1 ")) strncpy(gi_ptr->acq.slice_order, "ascending", STRING_T_LEN); else if(!strcmp(gi_ptr->acq.slice_order,"0x2 ")) strncpy(gi_ptr->acq.slice_order, "descending", STRING_T_LEN); else if(!strcmp(gi_ptr->acq.slice_order,"0x4 ")) strncpy(gi_ptr->acq.slice_order, "interleaved", STRING_T_LEN); gi_ptr->acq.rep_time = (double)acr_find_double(group_list, ACR_Repetition_time, -DBL_MAX); if (gi_ptr->acq.rep_time != -DBL_MAX) gi_ptr->acq.rep_time /= 1000.0; gi_ptr->acq.echo_time = (double)acr_find_double(group_list, ACR_Echo_time, -DBL_MAX); if (gi_ptr->acq.echo_time != -DBL_MAX) gi_ptr->acq.echo_time /= 1000.0; gi_ptr->acq.echo_train_length = (double)acr_find_double(group_list, ACR_Echo_train_length, -DBL_MAX); /*added echo train length ilana*/ gi_ptr->acq.echo_number = (double)acr_find_double(group_list, ACR_Echo_number, -DBL_MAX); gi_ptr->acq.inv_time = (double)acr_find_double(group_list, ACR_Inversion_time, -DBL_MAX); if (gi_ptr->acq.inv_time != -DBL_MAX) gi_ptr->acq.inv_time /= 1000.0; gi_ptr->acq.delay_in_TR = (double)acr_find_double(group_list, EXT_Delay_in_TR, -DBL_MAX); /*added delay in TR ilana*/ if (gi_ptr->acq.delay_in_TR != -DBL_MAX) gi_ptr->acq.delay_in_TR /= 1000000.0; /*write in seconds*/ gi_ptr->acq.b_value = (double)acr_find_double(group_list, EXT_Diffusion_b_value, -DBL_MAX); gi_ptr->acq.flip_angle = (double)acr_find_double(group_list, ACR_Flip_angle, -DBL_MAX); gi_ptr->acq.slice_thickness = (double)acr_find_double(group_list, ACR_Slice_thickness, -DBL_MAX); gi_ptr->acq.num_slices = (double)acr_find_double(group_list, ACR_Images_in_acquisition, -DBL_MAX); gi_ptr->acq.num_dyn_scans = (double)acr_find_double(group_list, ACR_Acquisitions_in_series, -DBL_MAX); gi_ptr->acq.num_avg = (double)acr_find_double(group_list, ACR_Nr_of_averages, -DBL_MAX); gi_ptr->acq.imaging_freq = (double)acr_find_double(group_list, ACR_Imaging_frequency, -DBL_MAX); if (gi_ptr->acq.imaging_freq != -DBL_MAX) gi_ptr->acq.imaging_freq *= 1e6; get_string_field(gi_ptr->acq.imaged_nucl, group_list, ACR_Imaged_nucleus); gi_ptr->acq.win_center = (double)acr_find_double(group_list, ACR_Window_centre, -DBL_MAX); gi_ptr->acq.win_width = (double)acr_find_double(group_list, ACR_Window_width, -DBL_MAX); gi_ptr->acq.num_phase_enc_steps = (double)acr_find_double(group_list, ACR_Number_of_phase_encoding_steps, -DBL_MAX); gi_ptr->acq.percent_sampling = (double)acr_find_double(group_list, ACR_Percent_sampling, -DBL_MAX); /*don't need to multiply by 100 ilana*/ gi_ptr->acq.percent_phase_fov = (double)acr_find_double(group_list, ACR_Percent_phase_field_of_view, -DBL_MAX); /*don't need to multiply by 100 ilana*/ gi_ptr->acq.pixel_bandwidth = (double)acr_find_double(group_list, ACR_Pixel_bandwidth, -DBL_MAX); gi_ptr->acq.sar = (double)acr_find_double(group_list, ACR_SAR, -DBL_MAX); get_string_field(gi_ptr->acq.mr_acq_type, group_list, ACR_MR_acquisition_type); get_string_field(gi_ptr->acq.image_type, group_list, ACR_Image_type); if (G.Debug) { if (strstr(gi_ptr->acq.image_type, "MOSAIC") != NULL) { printf("This appears to be a Mosaic image\n"); } } get_string_field(gi_ptr->acq.phase_enc_dir, group_list, ACR_Phase_encoding_direction); /*Add image comments*/ /*strncpy(gi_ptr->acq.comments, "", STRING_T_LEN);*/ get_string_field(gi_ptr->acq.comments, group_list, ACR_Image_comments); /* Siemens Numaris 4 specific! */ #if 0 gi_ptr->acq.MrProt = strdup(acr_find_string(group_list, EXT_MrProt_dump, "")); #else gi_ptr->acq.MrProt = strdup(""); #endif string = (char*)acr_find_string(group_list, ACR_Acquisition_contrast, ""); gi_ptr->acq.dti = (strstr(string, "DIFFUSION") != NULL); } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_time_to_seconds @INPUT : dicom_time @OUTPUT : (none) @RETURNS : real time in seconds from beginning of day @DESCRIPTION: Routine to convert dicom seconds (decimal hhmmss.xxxxx) to real seconds since the start of day. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static double convert_time_to_seconds(double dicom_time) { /* Constants */ #define DICOM_SECONDS_PER_HOUR 10000.0 #define DICOM_SECONDS_PER_MINUTE 100.0 /* Variables */ double hh, mm, ss; /* Get the components of the time */ hh = (int) (dicom_time / DICOM_SECONDS_PER_HOUR); dicom_time -= hh * DICOM_SECONDS_PER_HOUR; mm = (int) (dicom_time / DICOM_SECONDS_PER_MINUTE); dicom_time -= mm * DICOM_SECONDS_PER_MINUTE; ss = dicom_time; /* Work out the number of seconds */ return (hh * 3600.0) + (mm * 60.0) + ss; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dicom_image_data @INPUT : group_list - input data @OUTPUT : image - image data structure (user must free data) @RETURNS : (nothing) @DESCRIPTION: Routine to get an image from a group list @METHOD : @GLOBALS : @CALLS : @CREATED : November 25, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void get_dicom_image_data(Acr_Group group_list, Image_Data *image) { /* Variables */ Acr_Element element; int nrows, ncolumns; int bits_alloc; int image_group; void *data = NULL; long imagepix, ipix; struct Acr_Element_Id elid; nc_type datatype; /* Get the image information */ bits_alloc = (int)acr_find_short(group_list, ACR_Bits_allocated, 0); nrows = (int)acr_find_short(group_list, ACR_Rows, 0); ncolumns = (int)acr_find_short(group_list, ACR_Columns, 0); image_group = (int)acr_find_short(group_list, ACR_Image_location, ACR_IMAGE_GID); /* Figure out type */ if (bits_alloc > CHAR_BIT) datatype = NC_SHORT; else datatype = NC_BYTE; /* Set image info */ imagepix = nrows * ncolumns; image->data = (unsigned short *) malloc(imagepix * sizeof(short)); CHKMEM(image->data); /* Get image pointer */ elid.group_id = image_group; elid.element_id = ACR_IMAGE_EID; element = acr_find_group_element(group_list, &elid); if (element == NULL) { memset(image->data, 0, imagepix * sizeof(short)); return; } data = acr_get_element_data(element); /* Convert the data according to type */ /* Look for byte data */ if (datatype == NC_BYTE) { for (ipix=0; ipix < imagepix; ipix++) { image->data[ipix] = *((unsigned char *) data + ipix); } } else { /* Look for unpacked short data */ if (bits_alloc == nctypelen(datatype) * CHAR_BIT) { acr_get_short(acr_get_element_byte_order(element), nrows*ncolumns, data, image->data); } /* Fill with zeros in any other case */ else { memset(image->data, 0, imagepix * sizeof(short)); } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : parse_dicom_groups @INPUT : group_list - list of acr-nema groups that make up object @OUTPUT : data_info - information about data object @RETURNS : (nothing) @DESCRIPTION: Routine to parse dicom object @METHOD : @GLOBALS : @CALLS : @CREATED : June 2001 (Rick Hoge) @MODIFIED : ---------------------------------------------------------------------------- */ #define IDEFAULT (-1) void parse_dicom_groups(Acr_Group group_list, Data_Object_Info *di_ptr) { Acr_Element element; Acr_Short AcqMat[4]; Acr_Short freq_rows; Acr_Short freq_cols; Acr_Short phase_rows; Acr_Short phase_cols; double slice_coord[WORLD_NDIMS]; /* Get info to construct unique identifiers for study, series/acq * for file processing */ get_identification_info(group_list, &(di_ptr->study_id), &(di_ptr->acq_id), &(di_ptr->rec_num), &(di_ptr->image_type)); /* Get number of echos, echo number, number of dynamic scans and * dynamic_scan_number */ di_ptr->num_echoes = acr_find_int(group_list, ACR_Echo_train_length, IDEFAULT); di_ptr->echo_number = acr_find_int(group_list, ACR_Echo_number, IDEFAULT); di_ptr->num_dyn_scans = acr_find_int(group_list, ACR_Acquisitions_in_series, IDEFAULT); di_ptr->dyn_scan_number = acr_find_int(group_list, ACR_Acquisition, IDEFAULT); di_ptr->global_image_number = acr_find_int(group_list, ACR_Image, IDEFAULT); /* rhoge: new info added to di_ptr by rhoge: nominal number of slices; this is used in detection of a stream of files with the same acquisition ID number in which there are more files than slices. If the number of signal averages is greater than one, we will assume that this means the acquisition loop was used for dynamic scanning. WARNINGS: the same thing may need to be done with `number of partitions' for it to work with 3D scans */ di_ptr->num_slices_nominal = acr_find_int(group_list, ACR_Images_in_acquisition, IDEFAULT); di_ptr->slice_number = acr_find_int(group_list, SPI_Current_slice_number, IDEFAULT); di_ptr->slice_location = (double)acr_find_double(group_list, ACR_Slice_location, 0.0); di_ptr->coord_found = dicom_read_position(group_list, 0, slice_coord); /* identification info needed to generate unique session id * for file names */ di_ptr->study_date = acr_find_int(group_list, ACR_Study_date, IDEFAULT); di_ptr->study_time = acr_find_int(group_list, ACR_Study_time, IDEFAULT); di_ptr->scanner_serialno = acr_find_int(group_list, ACR_Device_serial_number, IDEFAULT); /* identification info needed to determine if mosaics used */ element = acr_find_group_element(group_list, ACR_Acquisition_matrix); if (element != NULL) { acr_get_element_short_array(element, 4, AcqMat); freq_rows = AcqMat[0]; freq_cols = AcqMat[1]; phase_rows = AcqMat[2]; phase_cols = AcqMat[3]; /* rows in acq matrix is larger of freq rows and freq columns: */ di_ptr->acq_rows = ( freq_rows > freq_cols ? freq_rows : freq_cols ); /* all images are square, at this time */ di_ptr->acq_cols = di_ptr->acq_rows; } else { di_ptr->acq_rows = IDEFAULT; di_ptr->acq_cols = IDEFAULT; } di_ptr->rec_rows = acr_find_int(group_list, ACR_Rows, IDEFAULT); di_ptr->rec_cols = acr_find_int(group_list, ACR_Columns, IDEFAULT); di_ptr->num_mosaic_rows = acr_find_int(group_list, EXT_Mosaic_rows, IDEFAULT); di_ptr->num_mosaic_cols = acr_find_int(group_list, EXT_Mosaic_columns, IDEFAULT); di_ptr->num_slices_in_file = acr_find_int(group_list, EXT_Slices_in_file, IDEFAULT); /* sequence, protocol names (useful for debugging): */ get_string_field(di_ptr->sequence_name, group_list, ACR_Sequence_name); get_string_field(di_ptr->protocol_name, group_list, ACR_Protocol_name); get_string_field(di_ptr->patient_name, group_list, ACR_Patient_name); get_string_field(di_ptr->patient_id, group_list, ACR_Patient_identification); } minc-2.2.00/conversion/dcm2mnc/minc_file.c0000644000265600003100000014654112027132660015252 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_file.c @DESCRIPTION: Code to do minc file handling. @METHOD : @GLOBALS : @CALLS : @CREATED : January 28, 1997 (Peter Neelin) @MODIFIED : * $Log: minc_file.c,v $ * Revision 1.19 2010-11-23 23:30:50 claude * dcm2mnc: fixed seg fault bug (Claude) and added b-matrix (Ilana) * * Revision 1.18 2009-01-20 11:58:13 rotor * * CMakeLists.txt: updated version * * Updated Changelog to include releases * * Warning cleanups below * * conversion/dcm2mnc/minc_file.c: fixed printf type * * conversion/dcm2mnc/siemens_to_dicom.c: fixed printf type * * conversion/ecattominc/machine_indep.c: added string.h and fixed * 2 fprintf missing format args * * conversion/micropet/upet2mnc.c: fixed two fprintf format args * * conversion/minctoecat/ecat_write.c: added string.h * * conversion/minctoecat/minctoecat.c: added missing argument to fprintf * * conversion/nifti1/mnc2nii.c: fixed incorrect printf type * * progs/mincview/invert_raw_image.c: added fwrite checking * * Revision 1.17 2008/01/17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 1.16 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 1.15 2008/01/11 07:17:07 stever * Remove unused variables. * * Revision 1.14 2007/12/18 15:19:48 jharlap * reverted acq.comments from its new image_comments name to maintain backwards compatibility. also restored all the dicom elements which ilana decided to remove, with the exception of 0-length elements which make HDF spit out lots of warnings * * Revision 1.13 2007/06/08 20:28:57 ilana * added several fields to mincheader (dicom elements and found in ASCONV header) * * Revision 1.12 2006/04/09 15:34:32 bert * Add ability to save DTI parameters using Jennifer Campbell's convention * * Revision 1.11 2005/11/04 22:26:16 bert * Combined cloned code into a single check_regular() function * * Revision 1.10 2005/08/26 21:25:54 bert * Latest changes ported from 1.0 branch * * Revision 1.6.2.7 2005/08/18 18:17:55 bert * Fix up one warning message * * Revision 1.6.2.6 2005/07/22 20:02:45 bert * 1) Save start value for time coordinate. 2) Don't append fractional seconds to time in filename * * Revision 1.6.2.5 2005/06/20 21:59:33 bert * Add strfminc() to allow arbitrary output file naming, implement OPTS_NO_RESCALE debug option, fix rounding * * Revision 1.6.2.4 2005/06/02 18:20:06 bert * Fix generation and scaling of files with signed data * * Revision 1.6.2.3 2005/05/16 19:55:26 bert * Fix usage of G.Name * * Revision 1.6.2.2 2005/05/13 21:40:15 bert * properly initialize variable, also use _pet instead of _mri suffix for PET modality * * Revision 1.6.2.1 2005/05/12 21:16:48 bert * Initial checkin * * Revision 1.6 2005/04/29 23:09:06 bert * Write sample-width information to file for irregular time dimensions * * Revision 1.5 2005/04/20 23:15:06 bert * Don't save attributes that are no longer set * * Revision 1.4 2005/04/18 16:21:42 bert * Add debugging information for intensity scaling * * Revision 1.3 2005/03/13 19:34:21 bert * Minor change to avoid core dump with strange files * * Revision 1.2 2005/03/03 18:59:15 bert * Fix handling of image position so that we work with the older field (0020, 0030) as well as the new (0020, 0032) * * Revision 1.1 2005/02/17 16:38:10 bert * Initial checkin, revised DICOM to MINC converter * * Revision 1.1.1.1 2003/08/15 19:52:55 leili * Leili's dicom server for sonata * * Revision 1.12 2002/04/29 15:24:53 rhoge * removed (mode_t) cast in minc_file - would not build on SGI's * * Revision 1.11 2002/04/08 17:26:34 rhoge * added additional sequence info to minc header * * Revision 1.10 2002/03/27 18:57:50 rhoge * added diffusion b value * * Revision 1.9 2002/03/22 19:19:36 rhoge * Numerous fixes - * - handle Numaris 4 Dicom patient name * - option to cleanup input files * - command option * - list-only option * - debug mode * - user supplied name, idstr * - anonymization * * Revision 1.8 2002/03/19 22:10:16 rhoge * removed time sorting for N4DCM mosaics - time is random for mosaics * * Revision 1.7 2002/03/19 13:13:56 rhoge * initial working mosaic support - I think time is scrambled though. * * Revision 1.6 2001/12/31 18:27:21 rhoge * modifications for dicomreader processing of Numaris 4 dicom files - at * this point code compiles without warning, but does not deal with * mosaiced files. Also will probably not work at this time for Numaris * 3 .ima files. dicomserver may also not be functional... * * Revision 1.5 2001/02/26 22:22:37 rhoge * added scanner serial number to minc file naming * * Revision 1.4 2001/02/26 13:38:22 rhoge * made `existing directory' warning conditional on logging * * Revision 1.3 2000/12/15 01:04:46 rhoge * make sure acquisition_id (series no) is 6 digit hhmmss string for meas loop * * Revision 1.2 2000/12/14 21:19:22 rhoge * added code to compute time spacing if measurement loop dynamic * scanning has been detected * * Revision 1.1.1.1 2000/11/30 02:13:15 rhoge * imported sources to CVS repository on amoeba * * Revision 6.1 1999/10/29 17:51:55 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:27 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:26 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:20 neelin * Release of minc version 0.4 * * Revision 1.1 1997/03/04 20:56:47 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "dcm2mnc.h" #include /* Define mri dimension names */ static char *mri_dim_names[] = { NULL, "echo_time", MItime, "phase_number", "chemical_shift", NULL}; /* * verify that a list of coordinates is "regular", that is, that the * spacing between each adjacent pair does not vary by more than a * small amount relative to an average stepsize. */ int check_regular(double step, double coordinates[], int length) { int index; double diff; if (step == 0.0) { step = 1.0; /* avoid division by zero */ } for (index = 1; index < length; index++) { /* Calculate the difference between two adjacent locations, * less the average step value. */ diff = (coordinates[index] - coordinates[index - 1]) - step; if (diff < 0.0) { diff = -diff; } diff /= step; if (diff > COORDINATE_EPSILON) { return FALSE; } } return TRUE; } int strfminc(char *str_ptr, int str_max, const char *fmt_ptr, General_Info *gi_ptr) { char *tmp_ptr; int str_len = 0; char scan_label[MRI_NDIMS][20]; Mri_Index imri; static char *scan_prefix[MRI_NDIMS] = {"sl", "e", "d", "p", "cs"}; char tmp_str[1024]; /* Get strings for echo number, etc. */ for (imri = 0; imri < MRI_NDIMS; imri++) { if ((gi_ptr->cur_size[imri] < gi_ptr->max_size[imri]) && (gi_ptr->cur_size[imri] == 1)) { sprintf(scan_label[imri], "%s%d", scan_prefix[imri], gi_ptr->default_index[imri]); } else { strcpy(scan_label[imri], ""); } } while (*fmt_ptr != '\0') { tmp_ptr = NULL; if (*fmt_ptr == '%') { fmt_ptr++; switch (*fmt_ptr) { case 'N': /* Subject name */ string_to_filename(gi_ptr->patient.name, tmp_str, sizeof(tmp_str)); if (tmp_str[0] == '\0') { tmp_ptr = "no_name"; } else { tmp_ptr = tmp_str; } break; case 'D': string_to_filename(gi_ptr->patient.reg_date, tmp_str, sizeof(tmp_str)); tmp_ptr = tmp_str; break; case 'S': string_to_filename(gi_ptr->study.study_id, tmp_str, sizeof(tmp_str)); tmp_ptr = tmp_str; break; case 'T': strcpy(tmp_str, gi_ptr->patient.reg_time); tmp_ptr = tmp_str; while (*tmp_ptr != '\0') { if (!isdigit(*tmp_ptr)) { *tmp_ptr = '\0'; break; } tmp_ptr++; } tmp_ptr = tmp_str; break; case 'A': string_to_filename(gi_ptr->study.acquisition_id, tmp_str, sizeof(tmp_str)); tmp_ptr = tmp_str; break; case 's': tmp_ptr = scan_label[SLICE]; break; case 'e': tmp_ptr = scan_label[ECHO]; break; case 't': tmp_ptr = scan_label[TIME]; break; case 'p': tmp_ptr = scan_label[PHASE]; break; case 'c': tmp_ptr = scan_label[CHEM_SHIFT]; break; case 'm': if (!strcmp(gi_ptr->study.modality, MI_MRI)) { tmp_ptr = "_mri"; } else if (!strcmp(gi_ptr->study.modality, MI_PET)) { tmp_ptr = "_pet"; } else { tmp_ptr = ""; } break; default: break; } } if (tmp_ptr == NULL) { if (str_len < str_max) { *str_ptr++ = *fmt_ptr++; str_len++; } } else { fmt_ptr++; while (str_len < str_max && *tmp_ptr != '\0') { *str_ptr++ = *tmp_ptr++; str_len++; } } } *str_ptr++ = '\0'; return (str_len); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_minc_file @INPUT : minc_file - name of file to create. If NULL, a name is generated internally. clobber - if TRUE, any existing file will be overwritten. general_info - information for creating the file. file_prefix - string providing any directory or prefix for internally generated filename (if it is a directory, then it must contain the last "/") @OUTPUT : output_file_name - returns a pointer to an internal area containing the file name of the created file if minc_file is NULL, or simply a pointer to minc_file. If NULL, then nothing is returned. @RETURNS : id of image conversion variable (MI_ERROR in case of error). @DESCRIPTION: Routine to create the minc file. @METHOD : @GLOBALS : CALLS : @CREATED : November 26, 1993 (Peter Neelin) @MODIFIED : rhoge - modified to create directory for session -------------------------------------------------------------------------- */ int create_minc_file(const char *minc_file, int clobber, General_Info *general_info, const char *file_prefix, char **output_file_name, Loop_Type loop_type) { char temp_name[1024]; char *filename; int minc_clobber; int mincid, icvid; static char full_path[1024]; /* Turn off fatal errors */ ncopts = NCOPTS_DEFAULT; /* Create the file name if needed */ if (minc_file != NULL) { filename = (char *) minc_file; } else { /* rhoge: add session directory to prefix */ strcpy(full_path, file_prefix); if (G.dirname_format == NULL) { G.dirname_format = "%N_%D_%T"; } strfminc(temp_name, sizeof(temp_name), G.dirname_format, general_info); strcat(full_path, temp_name); if (strlen(full_path) != 0) { if (mkdir(full_path, 0777) && G.Debug) { printf("Directory %s exists...\n", full_path); } strcat(full_path, "/"); } /* if measurement loop, make sure that acquisition_id is * a 6 digit (hhmmss) string with leading zero if needed */ if (loop_type == MEAS) { sprintf(general_info->study.acquisition_id, "%06d", general_info->acq_id); } /* Create file name */ if (G.filename_format == NULL) { G.filename_format = "%N_%D_%T_%A%s%e%t%p%c%m"; } strfminc(temp_name, sizeof(temp_name), G.filename_format, general_info); strcat(full_path, temp_name); strcat(full_path, ".mnc"); /* Always append the extension */ filename = full_path; if (G.Debug) { printf("MINC file name: %s\n", filename); printf("Patient name: %s\n", general_info->patient.name); printf("Study ID: %s\n", general_info->study.study_id); printf("Acquisition ID: %s\n", general_info->study.acquisition_id); printf("Registration date: %s\n", general_info->patient.reg_date); printf("Registration time: %s\n", general_info->patient.reg_time); printf("Rows %d columns %d slices %d/%d\n", general_info->nrows, general_info->ncolumns, general_info->cur_size[SLICE], general_info->max_size[SLICE]); if (general_info->max_size[TIME] != 1) { printf("Time axis length: %d/%d\n", general_info->cur_size[TIME], general_info->max_size[TIME]); } } } /* Set output file name */ if (output_file_name != NULL) { *output_file_name = filename; } /* Set the clobber value */ if (clobber) minc_clobber = NC_CLOBBER; else minc_clobber = NC_NOCLOBBER; /* Create the file */ mincid = micreate(filename, minc_clobber); if (mincid == MI_ERROR) { return MI_ERROR; } /* Set up variables */ setup_minc_variables(mincid, general_info, loop_type); /* Put the file in data mode */ ncsetfill(mincid, NC_NOFILL); if (ncendef(mincid) == MI_ERROR) { return MI_ERROR; } /* Create the icv */ icvid = miicv_create(); /* Set the type and range */ miicv_setint(icvid, MI_ICV_TYPE, NC_SHORT); if (general_info->is_signed) miicv_setstr(icvid, MI_ICV_SIGN, MI_SIGNED); else miicv_setstr(icvid, MI_ICV_SIGN, MI_UNSIGNED); miicv_setdbl(icvid, MI_ICV_VALID_MIN, general_info->pixel_min); miicv_setdbl(icvid, MI_ICV_VALID_MAX, general_info->pixel_max); /* Attach the icv */ miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); return icvid; } /* ----------------------------- MNI Header ----------------------------------- @NAME : minc_set_spacing @INPUT : mincid varid imri gi_ptr @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: This function checks the given MRI dimension (most typically the TIME dimension) to see if it has a "regular" structure. If so, the MINC file is updated accordingly. If not, the function creates a "xxxx-width" variable corresponding to the dimension which will contain the width information from this dimension. NOTE: At present only the time-width variable is defined by MINC. @METHOD : @GLOBALS : CALLS : @CREATED : April 27, 2005 (Bert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ static void minc_set_spacing(int mincid, int varid, Mri_Index imri, General_Info *gi_ptr) { double sum = 0.0; /* Sum of differences for computing average */ double avg; /* Average */ double step; /* Step size from widths */ int regular; /* TRUE if dimension is regular */ int index; /* Loop/array index */ long length; /* Length of this dimension (> 1) */ regular = TRUE; length = gi_ptr->cur_size[imri]; /* First, see if the widths were set, and if so, if they are consistent. */ for (index = 1; index < length; index++) { if (gi_ptr->widths[imri][0] != gi_ptr->widths[imri][index]) { regular = FALSE; break; } } /* OK, now set the step value according to the widths, if possible. */ if (regular) { step = gi_ptr->widths[imri][0]; /* Now calculate the average value for the coordinate spacing. */ for (index = 1; index < length; index++) { sum += gi_ptr->coordinates[imri][index] - gi_ptr->coordinates[imri][index-1]; } avg = sum / length; /* compute mean */ if (step != 0.0 && avg != step) { printf("WARNING: Sample width (%g) not equal to average delta (%g)\n", step, avg); } step = avg; /* Use the average anyway. */ /* Check for uniformity of spacing */ regular = check_regular(step, gi_ptr->coordinates[imri], length); } else { /* We have widths provided for us, so use them to calculate the * average step size. */ for (index = 0; index < length; index++) { sum += gi_ptr->widths[imri][index]; } step = sum / length; } /* * Write the step value. According to the MINC specifications, it is * always valid to store a step value even for irregular dimensions. * The step should always equal the average spacing of the dimension. */ miattputdbl(mincid, varid, MIstep, step); miattputdbl(mincid, varid, MIstart, gi_ptr->coordinates[imri][0]); if (regular) { miattputstr(mincid, varid, MIspacing, MI_REGULAR); } else { miattputstr(mincid, varid, MIspacing, MI_IRREGULAR); /* Create the -width variable. At present, this * is only a valid operation if the dimension in question is the * time dimension. MINC does not define a width variable for any of * the other, non-standard dimensions. So for now this code is * very much a special case. */ if (imri == TIME) { int dimid; dimid = ncdimid(mincid, MItime); if (dimid >= 0) { micreate_std_variable(mincid, MItime_width, NC_DOUBLE, 1, &dimid); } } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_minc_variables @INPUT : mincid general_info @OUTPUT : general_info @RETURNS : (nothing) @DESCRIPTION: Routine to setup minc variables. @METHOD : @GLOBALS : CALLS : @CREATED : November 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void setup_minc_variables(int mincid, General_Info *general_info, Loop_Type loop_type) { Mri_Index imri; Volume_Index ivol; World_Index iworld; int ndims; int dim[MAX_VAR_DIMS]; long dimsize; char *dimname; int varid, imgid, dicomvar; double valid_range[2]; char name[MAX_NC_NAME]; Acr_Group cur_group; Acr_Element cur_element; int length; char *data; nc_type datatype; int is_char; int ich; /* Define the spatial dimension names */ static char *spatial_dimnames[WORLD_NDIMS] = {MIxspace, MIyspace, MIzspace}; /* Create the dimensions from slowest to fastest */ ndims=0; /* Create the non-spatial dimensions (from slowest to fastest) */ for (imri=MRI_NDIMS-1; (int) imri > SLICE; imri--) { /* for the TIME dimension, check if we have acquisition-loop dynamic scan OR a `corrected' dynamic scan */ if ( (imri==TIME) && ((loop_type!=NONE) || (general_info->acq.num_dyn_scans>1)) ) { /* for Siemens scans using the signal averaging loop for multiple time points we use the TR as the time step */ dimsize = general_info->cur_size[TIME]; if (general_info->cur_size[TIME] > 1) { dimname = mri_dim_names[TIME]; dim[ndims] = ncdimdef(mincid, dimname, dimsize); varid = micreate_std_variable(mincid, dimname, NC_DOUBLE, 1, &dim[ndims]); miattputstr(mincid, varid, MIspacing, MI_REGULAR); miattputstr(mincid, varid, MIunits, "s"); if (loop_type == MEAS) { /* if Meas loop, time step is not equal to TR, and frames should have time values (rhoge) */ minc_set_spacing(mincid, varid, TIME, general_info); } else { /* assume ACQ loop and use TR for time step */ miattputdbl(mincid, varid, MIstep, general_info->acq.rep_time); } miattputdbl(mincid, varid, MIstart,0); general_info->image_index[TIME] = ndims; ndims++; } } else { /* NORMAL CODE */ dimsize = general_info->cur_size[imri]; if (general_info->cur_size[imri] > 1) { dimname = mri_dim_names[imri]; dim[ndims] = ncdimdef(mincid, dimname, dimsize); if (imri == TIME) { varid = micreate_std_variable(mincid, dimname, NC_DOUBLE, 1, &dim[ndims]); miattputstr(mincid, varid, MIunits, "s"); minc_set_spacing(mincid, varid, TIME, general_info); } else if (imri == ECHO) { varid = ncvardef(mincid, dimname, NC_DOUBLE, 1, &dim[ndims]); miattputstr(mincid, varid, MIvartype, MI_DIMENSION); miattputstr(mincid, varid, MIspacing, MI_IRREGULAR); miattputstr(mincid, varid, MIunits, "s"); } general_info->image_index[imri] = ndims; ndims++; } } } /* Next the spatial dimensions */ for (ivol = 0; ivol < VOL_NDIMS; ivol++) { switch (ivol) { case VSLICE: dimsize = general_info->cur_size[SLICE]; iworld = general_info->slice_world; break; case VROW: dimsize = general_info->nrows; iworld = general_info->row_world; break; case VCOLUMN: dimsize = general_info->ncolumns; iworld = general_info->column_world; break; default: fprintf(stderr, "Should not happen!!"); exit(-1); } dimname = spatial_dimnames[iworld]; dim[ndims] = ncdimdef(mincid, dimname, dimsize); if (ivol == VSLICE) { varid = micreate_std_variable(mincid, dimname, NC_DOUBLE, 1, &dim[ndims]); /* Check for regular slices */ if (check_regular(general_info->step[general_info->slice_world], general_info->coordinates[SLICE], general_info->cur_size[SLICE])) { miattputstr(mincid, varid, MIspacing, MI_REGULAR); } } else { varid = micreate_std_variable(mincid, dimname, NC_LONG, 0, NULL); } miattputdbl(mincid, varid, MIstep, general_info->step[iworld]); miattputdbl(mincid, varid, MIstart, general_info->start[iworld]); miattputstr(mincid, varid, MIspacetype, MI_NATIVE); ncattput(mincid, varid, MIdirection_cosines, NC_DOUBLE, WORLD_NDIMS, general_info->dircos[iworld]); if (ivol == VSLICE) { general_info->image_index[SLICE] = ndims; } ndims++; } /* Set up image variable */ imgid = micreate_std_variable(mincid, MIimage, general_info->datatype, ndims, dim); if (general_info->is_signed) miattputstr(mincid, imgid, MIsigntype, MI_SIGNED); else miattputstr(mincid, imgid, MIsigntype, MI_UNSIGNED); valid_range[0] = general_info->pixel_min; valid_range[1] = general_info->pixel_max; ncattput(mincid, imgid, MIvalid_range, NC_DOUBLE, 2, valid_range); miattputstr(mincid, imgid, MIcomplete, MI_FALSE); /* Create image max and min variables */ varid = micreate_std_variable(mincid, MIimagemin, NC_DOUBLE, ndims-2, dim); if (strlen(general_info->units) > 0) miattputstr(mincid, varid, MIunits, general_info->units); varid = micreate_std_variable(mincid, MIimagemax, NC_DOUBLE, ndims-2, dim); if (strlen(general_info->units) > 0) miattputstr(mincid, varid, MIunits, general_info->units); /* Create the patient variable */ varid = micreate_group_variable(mincid, MIpatient); if (strlen(general_info->patient.name) > 0) { if (G.Anon) { miattputstr(mincid, varid, MIfull_name, "anonymous"); } else { miattputstr(mincid, varid, MIfull_name, general_info->patient.name); } } if (strlen(general_info->patient.identification) > 0) miattputstr(mincid, varid, MIidentification, general_info->patient.identification); if (strlen(general_info->patient.birth_date) > 0) miattputstr(mincid, varid, MIbirthdate, general_info->patient.birth_date); if (strlen(general_info->patient.age) > 0) miattputstr(mincid, varid, MIage, general_info->patient.age); if (strlen(general_info->patient.sex) > 0) miattputstr(mincid, varid, MIsex, general_info->patient.sex); if (general_info->patient.weight != -DBL_MAX) miattputdbl(mincid, varid, MIweight, general_info->patient.weight); if (strlen(general_info->patient.position) > 0) miattputstr(mincid, varid, "position", general_info->patient.position); /* Create the study variable */ varid = micreate_group_variable(mincid, MIstudy); /* rhoge: fixed date/time to reflect study */ if (strlen(general_info->patient.reg_date) > 0) miattputstr(mincid, varid, "start_date", general_info->patient.reg_date); if (strlen(general_info->patient.reg_time) > 0) miattputstr(mincid, varid, MIstart_time, general_info->patient.reg_time); if (strlen(general_info->study.modality) > 0) miattputstr(mincid, varid, MImodality, general_info->study.modality); if (strlen(general_info->study.manufacturer) > 0) miattputstr(mincid, varid, MImanufacturer, general_info->study.manufacturer); if (strlen(general_info->study.model) > 0) miattputstr(mincid, varid, MIdevice_model, general_info->study.model); if (general_info->study.field_value != -DBL_MAX) miattputdbl(mincid, varid, "field_value", general_info->study.field_value); if (strlen(general_info->study.software_version) > 0) miattputstr(mincid, varid, "software_version", general_info->study.software_version); if (strlen(general_info->study.serial_no) > 0) miattputstr(mincid, varid, "serial_no", general_info->study.serial_no); if (strlen(general_info->study.calibration_date) > 0) miattputstr(mincid, varid, "calibration_date", general_info->study.calibration_date); if (strlen(general_info->study.calibration_time) > 0) miattputstr(mincid, varid, "calibration_time", general_info->study.calibration_time); if (strlen(general_info->study.institution) > 0) miattputstr(mincid, varid, MIinstitution, general_info->study.institution); if (strlen(general_info->study.station_id) > 0) miattputstr(mincid, varid, MIstation_id, general_info->study.station_id); if (strlen(general_info->study.referring_physician) > 0) miattputstr(mincid, varid, MIreferring_physician, general_info->study.referring_physician); if (strlen(general_info->study.performing_physician) > 0) miattputstr(mincid, varid, "performing_physician", general_info->study.referring_physician); if (strlen(general_info->study.operator) > 0) miattputstr(mincid, varid, MIoperator, general_info->study.operator); if (strlen(general_info->study.procedure) > 0) miattputstr(mincid, varid, MIprocedure, general_info->study.procedure); if (strlen(general_info->study.study_id) > 0) miattputstr(mincid, varid, MIstudy_id, general_info->study.study_id); /* Create acquisition variable */ varid = micreate_group_variable(mincid, MIacquisition); if (strlen(general_info->study.acquisition_id) > 0) miattputstr(mincid, varid, "acquisition_id", general_info->study.acquisition_id); if (strlen(general_info->study.start_time) > 0) miattputstr(mincid, varid, MIstart_time, general_info->study.start_time); /*added some more study info*/ if (strlen(general_info->acq.series_time) > 0) miattputstr(mincid, varid, "series_time", general_info->acq.series_time); if (strlen(general_info->acq.acquisition_time) > 0) /*should use this instead of the Study time*/ miattputstr(mincid, varid, "acquisition_time", general_info->acq.acquisition_time); if (strlen(general_info->acq.image_time) > 0) miattputstr(mincid, varid, "image_time", general_info->acq.image_time); if (strlen(general_info->acq.scan_seq) > 0) miattputstr(mincid, varid, MIscanning_sequence, general_info->acq.scan_seq); if (strlen(general_info->acq.series_description) > 0) /*add Series Description*/ miattputstr(mincid, varid, "series_description", general_info->acq.series_description); if (strlen(general_info->acq.protocol_name) > 0) miattputstr(mincid, varid, MIprotocol, general_info->acq.protocol_name); if (strlen(general_info->acq.receive_coil) > 0) miattputstr(mincid, varid, "receive_coil", general_info->acq.receive_coil); if (strlen(general_info->acq.transmit_coil) > 0) miattputstr(mincid, varid, "transmit_coil", general_info->acq.transmit_coil); if (general_info->acq.rep_time != -DBL_MAX) miattputdbl(mincid, varid, MIrepetition_time, general_info->acq.rep_time); if ((general_info->acq.echo_time != -DBL_MAX) && (general_info->cur_size[ECHO] <= 1)) miattputdbl(mincid, varid, MIecho_time, general_info->acq.echo_time); if (general_info->acq.echo_number != -DBL_MAX) miattputdbl(mincid, varid, "echo_number", general_info->acq.echo_number); if (general_info->acq.echo_train_length != -DBL_MAX) /*add echo train length ilana*/ miattputdbl(mincid, varid, "echo_train_length", general_info->acq.echo_train_length); if (general_info->acq.inv_time != -DBL_MAX) miattputdbl(mincid, varid, MIinversion_time, general_info->acq.inv_time); if (general_info->acq.flip_angle != -DBL_MAX) miattputdbl(mincid, varid, "flip_angle", general_info->acq.flip_angle); if (general_info->acq.slice_thickness != -DBL_MAX) miattputdbl(mincid, varid, "slice_thickness", general_info->acq.slice_thickness); if (general_info->acq.num_slices != -DBL_MAX) miattputdbl(mincid, varid, "num_slices", general_info->acq.num_slices); if (strlen(general_info->acq.slice_order) > 0) /* add slice ordering info*/ miattputstr(mincid, varid, "slice_order", general_info->acq.slice_order); if (general_info->acq.b_value != -DBL_MAX) miattputdbl(mincid, varid, "b_value", general_info->acq.b_value); if (general_info->acq.delay_in_TR != -DBL_MAX) /*add delay in TR*/ miattputdbl(mincid, varid, "delay_in_TR", general_info->acq.delay_in_TR); /* add number of dynamic scans (rhoge) */ /* this will be relevant if we are receiving siemens scans that have been `cleaned up' (and hence have the correct number of dynamic scans inserted) */ if (general_info->acq.num_dyn_scans != -DBL_MAX) miattputdbl(mincid, varid, "num_dyn_scans", general_info->acq.num_dyn_scans); if (general_info->acq.num_avg != -DBL_MAX) miattputdbl(mincid, varid, MInum_averages, general_info->acq.num_avg); if (general_info->acq.imaging_freq != -DBL_MAX) miattputdbl(mincid, varid, MIimaging_frequency, general_info->acq.imaging_freq); if (strlen(general_info->acq.imaged_nucl) > 0) miattputstr(mincid, varid, MIimaged_nucleus, general_info->acq.imaged_nucl); if (general_info->acq.win_center != -DBL_MAX) miattputdbl(mincid, varid, "window_center", general_info->acq.win_center); if (general_info->acq.win_width != -DBL_MAX) miattputdbl(mincid, varid, "window_width", general_info->acq.win_width); if (general_info->acq.num_phase_enc_steps != -DBL_MAX) miattputdbl(mincid, varid, "num_phase_enc_steps", general_info->acq.num_phase_enc_steps); if (general_info->acq.percent_sampling != -DBL_MAX) miattputdbl(mincid, varid, "percent_sampling", general_info->acq.percent_sampling); if (general_info->acq.percent_phase_fov != -DBL_MAX) miattputdbl(mincid, varid, "percent_phase_fov", general_info->acq.percent_phase_fov); if (general_info->acq.pixel_bandwidth != -DBL_MAX) miattputdbl(mincid, varid, "pixel_bandwidth", general_info->acq.pixel_bandwidth); if (strlen(general_info->acq.phase_enc_dir) > 0) miattputstr(mincid, varid, "phase_enc_dir", general_info->acq.phase_enc_dir); if (general_info->acq.sar != -DBL_MAX) miattputdbl(mincid, varid, "SAR", general_info->acq.sar); if (strlen(general_info->acq.mr_acq_type) > 0) miattputstr(mincid, varid, "mr_acq_type", general_info->acq.mr_acq_type); if (strlen(general_info->acq.image_type) > 0) miattputstr(mincid, varid, "image_type", general_info->acq.image_type); if (strlen(general_info->acq.comments) > 0) miattputstr(mincid, varid, MIcomments, general_info->acq.comments); // this is Siemens Numaris 4 specific! if (strlen(general_info->acq.MrProt) > 0) miattputstr(mincid, varid, "MrProt_dump", general_info->acq.MrProt); /* Add DTI stuff if needed */ if (general_info->acq.dti) { int length = general_info->cur_size[TIME]; double *tmp_ptr = calloc(length, sizeof(double)); ncattput(mincid, varid, "bvalues", NC_DOUBLE, length, tmp_ptr); ncattput(mincid, varid, "direction_x", NC_DOUBLE, length, tmp_ptr); ncattput(mincid, varid, "direction_y", NC_DOUBLE, length, tmp_ptr); ncattput(mincid, varid, "direction_z", NC_DOUBLE, length, tmp_ptr); free( tmp_ptr ); /*This means that ANY DTI sequence will have a b_matrix in the mincheader. For Siemens software versions before VB (and probably other vendors), the field does not exist but we still choose to set the b_matrix field in the mincheader to all 0s. We do this because b=0 files do not have the b_matrix 0019x1027 field, and we must create one. I.e. determining whether the field exists or not in a particular file is not enough to reject it for the series.*/ int num_elements=6;/*should always have 6 elements per direction (i.e. direction=TIME variable)*/ double *tmp_ptr2 = calloc(length*num_elements,sizeof(double)); ncattput(mincid, varid, "b_matrix", NC_DOUBLE, num_elements*length, tmp_ptr2); } /* Create the dicom info variable */ varid = ncvardef(mincid, "dicominfo", NC_LONG, 0, NULL); miattputstr(mincid, varid, MIvartype, MI_GROUP); miattputstr(mincid, varid, MIvarid, "MNI DICOM information variable"); miadd_child(mincid, ncvarid(mincid, MIrootvariable), varid); if (strlen(general_info->image_type_string) > 0) miattputstr(mincid, varid, "image_type", general_info->image_type_string); miattputdbl(mincid, varid, "window_min", general_info->window_min); miattputdbl(mincid, varid, "window_max", general_info->window_max); /* Put group info in header */ /* A lot of these dicom groups dump lots of junk into the mincheader, and most of the information here has already been included in the minc fields, we just should add those that are missing and might be of use. Removing the fields starting with "dicom_0x... for now ilana*/ /* contrary to ilanas view - this *is* useful info! */ cur_group = general_info->group_list; dicomvar = ncvardef(mincid, DICOM_ROOT_VAR, NC_LONG, 0, NULL); miattputstr(mincid, dicomvar, MIvartype, MI_GROUP); miattputstr(mincid, dicomvar, MIvarid, "MNI DICOM variable"); miadd_child(mincid, ncvarid(mincid, MIrootvariable), dicomvar); while (cur_group != NULL) { /* Create variable for group */ sprintf(name, "dicom_0x%04x", acr_get_group_group(cur_group)); varid = ncvardef(mincid, name, NC_LONG, 0, NULL); miattputstr(mincid, varid, MIvartype, MI_GROUP); miattputstr(mincid, varid, MIvarid, "MNI DICOM variable"); miadd_child(mincid, dicomvar, varid); /* Loop through elements of group */ cur_element = acr_get_group_element_list(cur_group); while (cur_element != NULL) { sprintf(name, "el_0x%04x", acr_get_element_element(cur_element)); is_char = TRUE; length = acr_get_element_length(cur_element); data = acr_get_element_data(cur_element); if (data == NULL) { length = 0; } for (ich=0; ich < length; ich++) { if (!isprint((int) data[ich])) { is_char = FALSE; break; } } if (is_char) datatype = NC_CHAR; else datatype = NC_BYTE; /* Do not insert 0-length elements as it makes HDF complain */ if(length > 0) ncattput(mincid, varid, name, datatype, length, data); cur_element = acr_get_element_next(cur_element); } cur_group = acr_get_group_next(cur_group); } /* Create the history attribute */ if (G.minc_history != NULL) { miattputstr(mincid, NC_GLOBAL, MIhistory, G.minc_history); } return; } /* Insert a scalar 'value' at 'position' along the given vector attribute * of preallocated 'length'. */ void put_att_dbl(int mincid, int varid, char *attname, int length, int position, double value) { double *val_ptr = malloc(sizeof(double) * length); if (val_ptr != NULL) { ncattget(mincid, varid, attname, val_ptr); val_ptr[position] = value; ncattput(mincid, varid, attname, NC_DOUBLE, length, val_ptr); free( val_ptr ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : save_minc_image @INPUT : icvid general_info file_info image @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to save the image in the minc file @METHOD : @GLOBALS : CALLS : @CREATED : November 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void save_minc_image(int icvid, General_Info *gi_ptr, File_Info *fi_ptr, Image_Data *image) { int mincid; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; int file_index, array_index; int idim; Mri_Index imri; char *dimname; int pvalue, pmax, pmin; double dvalue, maximum, minimum, scale, offset; long ipix, imagepix; /* Get the minc file id */ miicv_inqint(icvid, MI_ICV_CDFID, &mincid); /* Create start and count variables */ idim = 0; for (imri=MRI_NDIMS-1; (int) imri >= 0; imri--) { if (gi_ptr->image_index[imri] >= 0) { file_index = gi_ptr->image_index[imri]; if (gi_ptr->cur_size[imri] > 1) { array_index = search_list(fi_ptr->index[imri], gi_ptr->indices[imri], gi_ptr->cur_size[imri], gi_ptr->search_start[imri]); if (array_index < 0) array_index = 0; gi_ptr->search_start[imri] = array_index; } else { array_index = 0; } start[file_index] = array_index; count[file_index] = 1; idim++; } } start[idim] = 0; start[idim+1] = 0; count[idim] = gi_ptr->nrows; count[idim+1] = gi_ptr->ncolumns; /* Write out slice position */ switch (gi_ptr->slice_world) { case XCOORD: dimname = MIxspace; break; case YCOORD: dimname = MIyspace; break; case ZCOORD: dimname = MIzspace; break; default: dimname = MIzspace; } mivarput1(mincid, ncvarid(mincid, dimname), &start[gi_ptr->image_index[SLICE]], NC_DOUBLE, NULL, &fi_ptr->coordinate[SLICE]); /* Write out time of slice, if needed */ if (gi_ptr->cur_size[TIME] > 1) { mivarput1(mincid, ncvarid(mincid, mri_dim_names[TIME]), &start[gi_ptr->image_index[TIME]], NC_DOUBLE, NULL, &fi_ptr->coordinate[TIME]); if (gi_ptr->acq.dti) { put_att_dbl(mincid, ncvarid(mincid, MIacquisition), "bvalues", gi_ptr->cur_size[TIME], start[gi_ptr->image_index[TIME]], fi_ptr->b_value); put_att_dbl(mincid, ncvarid(mincid, MIacquisition), "direction_x", gi_ptr->cur_size[TIME], start[gi_ptr->image_index[TIME]], fi_ptr->grad_direction[XCOORD]); put_att_dbl(mincid, ncvarid(mincid, MIacquisition), "direction_y", gi_ptr->cur_size[TIME], start[gi_ptr->image_index[TIME]], fi_ptr->grad_direction[YCOORD]); put_att_dbl(mincid, ncvarid(mincid, MIacquisition), "direction_z", gi_ptr->cur_size[TIME], start[gi_ptr->image_index[TIME]], fi_ptr->grad_direction[ZCOORD]); int i=0; int num_elements=6; for(i;icur_size[TIME], start[gi_ptr->image_index[TIME]]*num_elements+i, fi_ptr->b_matrix[i]); } } /* If width information is present, save it to the appropriate * location in the time-width variable. */ if (fi_ptr->width[TIME] != 0.0) { int ncopts_prev; int varid; /* Since it is possible for width information to be present * in circumstances where we do not want to save it, the * time-width variable may not even exist when we get here. * In order to avoid a nasty and unnecessary error message * we have to disable netCDF errors here. */ ncopts_prev = ncopts; ncopts = 0; varid = ncvarid(mincid, MItime_width); /* Get the variable id */ ncopts = ncopts_prev; /* If the variable was created, update it as needed. */ if (varid >= 0) { mivarput1(mincid, varid, &start[gi_ptr->image_index[TIME]], NC_DOUBLE, NULL, &fi_ptr->width[TIME]); } } } /* Write out echo time of slice, if needed */ if (gi_ptr->cur_size[ECHO] > 1) { mivarput1(mincid, ncvarid(mincid, mri_dim_names[ECHO]), &start[gi_ptr->image_index[ECHO]], NC_DOUBLE, NULL, &fi_ptr->coordinate[ECHO]); } /* Search image for max and min. This needs to be done such * that we interpret signed data correctly, so there are separate * loops for signed and unsigned data. * * If the data is signed, we need to search for the smallest and * lowest 2's complement 16-bit values. These will range from (at * most) -32768 to 32767. For unsigned values, we know that the * range will be from 0 to 65535. Since pmin, pmax, and pvalue * are declared to be 'int', they will always be able to represent * these values on 32-bit or 64-bit architectures. * * First, calculate the total number of voxels in this image. */ imagepix = gi_ptr->nrows * gi_ptr->ncolumns; pmax = INT_MIN; /* Initialize to smallest possible int */ pmin = INT_MAX; /* Initialize to largest possible int */ if (gi_ptr->is_signed) { short *ssh_ptr = (short *) image->data; /* Cast to signed data */ for (ipix = 0; ipix < imagepix; ipix++) { pvalue = ssh_ptr[ipix]; if (pvalue > pmax) pmax = pvalue; if (pvalue < pmin) pmin = pvalue; } } else { unsigned short *ush_ptr = (unsigned short *) image->data; for (ipix = 0; ipix < imagepix; ipix++) { pvalue = ush_ptr[ipix]; if (pvalue > pmax) pmax = pvalue; if (pvalue < pmin) pmin = pvalue; } } /* Calculate the 'scale' and 'offset' (slope and intercept) we * must use to scale the data. */ if (pmax > pmin) { scale = (gi_ptr->pixel_max - gi_ptr->pixel_min) / ((double) pmax - (double) pmin); } else { scale = 0.0; } offset = gi_ptr->pixel_min - scale * (double) pmin; /* debugging info for slice intensity scaling */ if (G.Debug >= HI_LOGGING) { printf("ranges: global %.2f %.2f, file %.2f %.2f, ", gi_ptr->pixel_min, gi_ptr->pixel_max, fi_ptr->slice_min, fi_ptr->slice_max); printf("slice %d %d\n", pmin, pmax); printf("1. scale %.2f offset %.2f\n", scale, offset); } /* Re-scale the images. Again, this has to be done in a * "signedness-aware" way, so that negative values will be * dealt with properly in signed data. */ if (gi_ptr->is_signed) { short *ssh_ptr = (short *) image->data; for (ipix = 0; ipix < imagepix; ipix++) { dvalue = ssh_ptr[ipix]; ssh_ptr[ipix] = (short) rint(dvalue * scale + offset); } } else { unsigned short *ush_ptr = (unsigned short *) image->data; for (ipix = 0; ipix < imagepix; ipix++) { dvalue = ush_ptr[ipix]; ush_ptr[ipix] = (unsigned short) rint(dvalue * scale + offset); } } if (gi_ptr->pixel_max > gi_ptr->pixel_min) { scale = (fi_ptr->slice_max - fi_ptr->slice_min) / (gi_ptr->pixel_max - gi_ptr->pixel_min); } else { scale = 0.0; } offset = fi_ptr->slice_min - scale * gi_ptr->pixel_min; minimum = (double) pmin * scale + offset; maximum = (double) pmax * scale + offset; if (G.Debug >= HI_LOGGING) { printf("2. scale %.2f offset %.2f min %.2f max %.2f\n", scale, offset, minimum, maximum); printf("3. position %ld,%ld,%ld\n", start[0], start[1], start[2]); } /* Write out the max and min values */ mivarput1(mincid, ncvarid(mincid, MIimagemin), start, NC_DOUBLE, NULL, &minimum); mivarput1(mincid, ncvarid(mincid, MIimagemax), start, NC_DOUBLE, NULL, &maximum); if (G.opts & OPTS_NO_RESCALE) { mivarput(mincid, ncvarid(mincid, MIimage), start, count, NC_SHORT, (gi_ptr->is_signed) ? MI_SIGNED : MI_UNSIGNED, image->data); } else { /* Write out the image */ miicv_put(icvid, start, count, image->data); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : close_minc_file @INPUT : icvid - value returned by create_minc_file @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to close the minc file. @METHOD : @GLOBALS : CALLS : @CREATED : November 30, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void close_minc_file(int icvid) { int mincid; /* Get the minc file id */ miicv_inqint(icvid, MI_ICV_CDFID, &mincid); /* Write out the complete attribute */ miattputstr(mincid, ncvarid(mincid, MIimage), MIcomplete, MI_TRUE); /* Close the file */ miclose(mincid); miicv_free(icvid); } minc-2.2.00/conversion/dcm2mnc/progress.c0000644000265600003100000000213112027132660015153 00000000000000 // This function prints a text progress bar within a term window // Input arguments assume a for loop starting at zero: // // for (index = 0; index < end; index++) { ... #include #include #include #include "progress.h" void progress(long index, int end, const char *message) { int ix; const int width = 50; int nchars; if (index == 0) { printf("%-20.20s |<--", message); for (ix = 0; ix < width; ix++) { printf(" "); } printf("|"); for (ix = 0; ix < width+1; ix++) { printf("\b"); } } else if ((index > 0) && (index < end)) { nchars = (((float)index/(float)(end-1)) * width) - floor(((float)(index-1)/(float)(end-1)) * width); for (ix = 0; ix < nchars; ix++) { printf("\b->"); fflush(stdout); } // print terminating newline at end if we're done if (index == end-1) { printf("\n"); } } else { fprintf(stderr,"PROGRESS: bad input indices!\n"); } } minc-2.2.00/conversion/dcm2mnc/string_to_filename.c0000644000265600003100000002027612027132660017171 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : string_to_filename.c @DESCRIPTION: Code to convert a string to something that can be used in a file name. @METHOD : @GLOBALS : @CALLS : @CREATED : January 10, 1997 (Peter Neelin) @MODIFIED : * $Log: string_to_filename.c,v $ * Revision 1.4 2008-01-17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 1.3 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 1.2 2005/03/03 18:59:16 bert * Fix handling of image position so that we work with the older field (0020, 0030) as well as the new (0020, 0032) * * Revision 1.1 2005/02/17 16:38:11 bert * Initial checkin, revised DICOM to MINC converter * * Revision 1.1.1.1 2003/08/15 19:52:55 leili * Leili's dicom server for sonata * * Revision 1.2 2002/03/22 19:19:36 rhoge * Numerous fixes - * - handle Numaris 4 Dicom patient name * - option to cleanup input files * - command option * - list-only option * - debug mode * - user supplied name, idstr * - anonymization * * Revision 1.1.1.1 2000/11/30 02:13:15 rhoge * imported sources to CVS repository on amoeba * * Revision 6.1 1999/10/29 17:52:00 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:27 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:26 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:20 neelin * Release of minc version 0.4 * * Revision 1.1 1997/03/04 20:56:47 neelin * Initial revision * @COPYRIGHT : Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "dcm2mnc.h" #include #define SEPARATOR '_' /* ----------------------------- MNI Header ----------------------------------- @NAME : string_to_filename @INPUT : string - string to convert maxlen - maximum length of output string (including terminating '\0') @OUTPUT : filename - output string @RETURNS : (nothing) @DESCRIPTION: Routine to convert a string to something that can be used in a filename @METHOD : @GLOBALS : @CALLS : @CREATED : December 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void string_to_filename(const char *string, char *filename, int maxlen) { int length, isrc, idst; int ch; int found_first, need_separator; /* Get string length */ length = strlen(string); if (length > maxlen-1) length = maxlen - 1; /* Loop through characters */ idst = 0; found_first = FALSE; need_separator = FALSE; for (isrc=0; isrc < length; isrc++) { ch = string[isrc]; if (isalnum(ch)) { found_first = TRUE; if (need_separator) { filename[idst++] = SEPARATOR; need_separator = FALSE; } filename[idst++] = tolower(ch); } else if (found_first) { need_separator = TRUE; } } /* Add terminating '\0' */ filename[idst++] = '\0'; return; } void string_to_initials(char *string, char *filename, int maxlen) { /* function added by R. Hoge to convert name-like strings to initials in environment where confidentiality policy prohibits use of names in file-names */ int length, isrc, idst; int ch; int first_found, sep_found, multi_word, comma_found, comma_found2, in_word; /* Get string length */ length = strlen(string); if (length > maxlen-1) length = maxlen - 1; /* do first pass to look for multi-words, commas */ first_found = FALSE; sep_found = FALSE; multi_word = FALSE; comma_found = FALSE; for (isrc=0; isrc < length; isrc++) { ch = string[isrc]; /* if we hit a separator after finding a first alphanum, treat as multi words */ /* alphanumeric expressions (including underscores, hyphens) are treated as discrete words - note that we won't print hyphens */ /* examples of single words: test5 test-5 test_5 examples of multi words: test 5 snr_test 5 test,5 snr-test 5 */ if (sep_found && isalnum(ch)) { multi_word = TRUE; } if (first_found && !(isalnum(ch)||ch=='-'||ch=='_')) { sep_found = TRUE; } if (isalnum(ch)) { first_found = TRUE; } // Numaris 4 used caret (^) to separate names (Last^first) if (ch == ',' || ch == '^') { comma_found = TRUE; } } /* if Patient name is only a single word, then just strip out non-alphanumeric characters examples: snrtest1 -> snrtest1 snrtest-1 -> snrtest1 snr_test-2 -> snr_test2 note that hyphens are omitted, because these are used as delimiters in filename */ if (!multi_word) { idst = 0; for (isrc=0; isrc < length; isrc++) { ch = string[isrc]; if (isalnum(ch) || ch=='_') { filename[idst++] = tolower(ch); } } /* Add terminating '\0' */ filename[idst++] = '\0'; } else { /* multiple words */ if (!comma_found) { /* examples of multi-word no comma: john doe -> jd john edward doe -> jed john doe-smith -> jds my snr_test -> mst john doe 12 -> jd12 john12 smith -> j12s 12john smith -> 12js john doe test2b -> jst2b note that underscores are treated as separators here, contiguous digits are all printed, and digits are treated as printable separators */ /* Loop through characters */ idst = 0; in_word = FALSE; for (isrc=0; isrc < length; isrc++) { ch = string[isrc]; if (isalpha(ch) && !in_word) { in_word = TRUE; filename[idst++] = tolower(ch); } else if (isdigit(ch)) { in_word = FALSE; filename[idst++] = ch; } else if (!isalnum(ch)) { in_word = FALSE; } } /* Add terminating '\0' */ filename[idst++] = '\0'; } else { /* multiple words with comma separation */ /* examples of multi-word with comma: doe, john -> jd doe,john -> jd doe-smith, john -> jds note that we treat stuff before the comma as the LAST name */ /* we do two passes: all the stuff after the comma THEN all the stuff before the comma */ idst = 0; /* Loop through characters, writing those after comma*/ comma_found2 = FALSE; in_word = FALSE; for (isrc=0; isrc < length; isrc++) { ch = string[isrc]; if (isalpha(ch) && !in_word) { in_word = TRUE; if (comma_found2) filename[idst++] = tolower(ch); } else if (isdigit(ch)) { in_word = FALSE; if (comma_found2) filename[idst++] = ch; } else if (!isalnum(ch)) { in_word = FALSE; } // numaris 4 uses Last^First if (ch == ',' || ch == '^') { comma_found2 = TRUE; } } /* now write characters/initials before the comma*/ comma_found2 = FALSE; in_word = FALSE; for (isrc=0; isrc < length; isrc++) { ch = string[isrc]; if (isalpha(ch) && !in_word) { in_word = TRUE; if (!comma_found2) filename[idst++] = tolower(ch); } else if (isdigit(ch)) { in_word = FALSE; if (!comma_found2) filename[idst++] = ch; } else if (!isalnum(ch)) { in_word = FALSE; } // Numaris 4 uses Last^First if (ch == ',' || ch == '^') { comma_found2 = TRUE; } } /* Add terminating '\0' */ filename[idst++] = '\0'; } } return; } minc-2.2.00/conversion/ecattominc/0000755000265600003100000000000012030114723014023 500000000000000minc-2.2.00/conversion/ecattominc/ecat_file.h0000644000265600003100000001440212027132661016037 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_file.h @DESCRIPTION: Header file for routines that read ECAT image files @GLOBALS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : * $Log: ecat_file.h,v $ * Revision 6.2 2005-01-19 19:46:01 bert * Changes from Anthonin Reilhac * * Revision 6.1 1999/10/29 17:52:01 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:22 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:21 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:04 neelin * Release of minc version 0.4 * * Revision 1.2 1996/03/26 15:58:18 neelin * Added some more header values. * * Revision 1.1 1996/01/18 14:52:14 neelin * Initial revision * @COPYRIGHT : Copyright 1996 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #ifndef public #define public #endif #ifndef private #define private static #endif #define ECAT_MAX_STRING_LENGTH 64 /*memory allocation*/ #define MALLOC(size) ((void *) malloc_check(size)) #define FREE(ptr) free(ptr) #define REALLOC(ptr, size) ((void *) realloc_check(ptr, size)) #define CALLOC(nelem, elsize) ((void *) calloc(nelem, elsize)) public void *malloc_check(size_t size); public void *realloc_check(void *ptr, size_t size); typedef enum { ECAT_No_Field, ECAT_Magic_Number, ECAT_Original_Filename, ECAT_Sw_Version, ECAT_System_Type, ECAT_File_Type, ECAT_Serial_Number, ECAT_Scan_Start_Time, ECAT_Isotope_Name, ECAT_Isotope_Halflife, ECAT_Radiopharmaceutical, ECAT_Gantry_Tilt, ECAT_Gantry_Rotation, ECAT_Bed_Elevation, ECAT_Intrinsic_Tilt, ECAT_Wobble_Speed, ECAT_Transm_Source_Type, ECAT_Distance_Scanned, ECAT_Transaxial_Fov, ECAT_Angular_Compression, ECAT_Coin_Samp_Mode, ECAT_Axial_Samp_Mode, ECAT_Calibration_Factor, ECAT_Calibration_Units, ECAT_Calibration_Units_Label, ECAT_Compression_Code, ECAT_Study_Type, ECAT_Patient_Id, ECAT_Patient_Name, ECAT_Patient_Sex, ECAT_Patient_Dexterity, ECAT_Patient_Age, ECAT_Patient_Height, ECAT_Patient_Weight, ECAT_Patient_Birth_Date, ECAT_Physician_Name, ECAT_Operator_Name, ECAT_Study_Description, ECAT_Acquision_Type, ECAT_Patient_Orientation, ECAT_Facility_Name, ECAT_Num_Planes, ECAT_Num_Frames, ECAT_Num_Gates, ECAT_Num_Bed_Pos, ECAT_Init_Bed_Position, ECAT_Bed_Position, ECAT_Plane_Separation, ECAT_Lwr_Sctr_Thres, ECAT_Lwr_True_Thres, ECAT_Upr_True_Thres, ECAT_User_Process_Code, ECAT_Acquisition_Mode, ECAT_Bin_Size, ECAT_Branching_Fraction, ECAT_Dose_Start_Time, ECAT_Dosage, ECAT_Well_Counter_Corr_Factor, ECAT_Data_Units, ECAT_Septa_State, ECAT_Data_Type, ECAT_Num_Dimensions, ECAT_X_Dimension, ECAT_Y_Dimension, ECAT_Z_Dimension, ECAT_X_Offset, ECAT_Y_Offset, ECAT_Z_Offset, ECAT_Recon_Zoom, ECAT_Scale_Factor, ECAT_Image_Min, ECAT_Image_Max, ECAT_X_Pixel_Size, ECAT_Y_Pixel_Size, ECAT_Z_Pixel_Size, ECAT_Frame_Duration, ECAT_Frame_Start_Time, ECAT_Filter_Code, ECAT_X_Resolution, ECAT_Y_Resolution, ECAT_Z_Resolution, ECAT_X_Rotation_Angle, ECAT_Y_Rotation_Angle, ECAT_Z_Rotation_Angle, ECAT_Decay_Corr_Fctr, ECAT_Corrections_Applied, ECAT_Gate_Duration, ECAT_R_Wave_Offset, ECAT_Num_Accepted_Beats, ECAT_Filter_Cutoff_Frequency, ECAT_Filter_Dc_Component, ECAT_Filter_Ramp_Slope, ECAT_Filter_Order, ECAT_Filter_Scatter_Fraction, ECAT_Filter_Scatter_Slope, ECAT_Annotation, ECAT_Da_X_Rotation_Angle, ECAT_Da_Y_Rotation_Angle, ECAT_Da_Z_Rotation_Angle, ECAT_Da_X_Translation, ECAT_Da_Y_Translation, ECAT_Da_Z_Translation, ECAT_Da_X_Scale_Factor, ECAT_Da_Y_Scale_Factor, ECAT_Da_Z_Scale_Factor, ECAT_Rfilter_Cutoff, ECAT_Rfilter_Resolution, ECAT_Rfilter_Code, ECAT_Rfilter_Order, ECAT_Zfilter_Cutoff, ECAT_Zfilter_Resolution, ECAT_Zfilter_Code, ECAT_Zfilter_Order, ECAT_Scan_Start_Day, ECAT_Scan_Start_Month, ECAT_Scan_Start_Year, ECAT_Scan_Start_Hour, ECAT_Scan_Start_Minute, ECAT_Scan_Start_Second, ECAT_Rot_Source_Speed } Ecat_field_name; typedef struct Ecat_file Ecat_file; /* Routine declarations */ public Ecat_file *ecat_open(char *filename); public void ecat_close(Ecat_file *file); public int ecat_get_num_planes(Ecat_file *file); public int ecat_get_num_frames(Ecat_file *file); public int ecat_get_num_bed_positions(Ecat_file *file); public int ecat_get_num_gates(Ecat_file *file); public Ecat_field_name ecat_list_main(Ecat_file *file, int index); public Ecat_field_name ecat_list_subhdr(Ecat_file *file, int index); public int ecat_get_main_field_length(Ecat_file *file, Ecat_field_name field); public int ecat_get_subhdr_field_length(Ecat_file *file, Ecat_field_name field); public char *ecat_get_main_field_description(Ecat_file *file, Ecat_field_name field); public char *ecat_get_subhdr_field_description(Ecat_file *file, Ecat_field_name field); public int ecat_get_main_value(Ecat_file *file, Ecat_field_name field, int index, int *ivalue, double *fvalue, char *svalue); public int ecat_get_subhdr_value(Ecat_file *file, int volume, int slice, Ecat_field_name field, int index, int *ivalue, double *fvalue, char *svalue); public int ecat_get_image(Ecat_file *file, int volume, int slice, short *image); minc-2.2.00/conversion/ecattominc/machine_indep.h0000644000265600003100000000432612027132661016713 00000000000000#ifndef _ECAT_MACHINE_INDEP_H #define _ECAT_MACHINE_INDEP_H 1 void get_short_value(const void *from, void *to); void get_long_value(const void *from, void *to); /* from vax_conversions.h -Copyright 1993 Peter Neelin */ /* ----------------------------- MNI Header ----------------------------------- @NAME : vax_conversions.h @DESCRIPTION: Header file for vax type conversion routines @GLOBALS : @CALLS : @CREATED : January 8, 1993 @MODIFIED : * $Log: machine_indep.h,v $ * Revision 6.1 2005-01-19 19:46:28 bert * Changes from Anthonin Reilhac * * Revision 6.2 1999/10/19 15:57:19 neelin * Fixed log message containing log substitution * * Revision 6.1 1999/10/19 14:45:15 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:34:32 neelin * Release of minc version 0.2 * * Revision 1.4 94/09/28 10:34:21 neelin * Pre-release * * Revision 1.3 93/08/04 13:04:03 neelin * Added RCS Log to keep track of modifications in source * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ void get_vax_short(int nvals, void *vax_value, short *mach_value); void get_vax_long(int nvals, void *vax_value, long *mach_value); void get_vax_float(int nvals, void *vax_value, float *mach_value); #endif /*_ECAT_MACHINE_INDEP_H*/ minc-2.2.00/conversion/ecattominc/ecat_header_definition.h0000644000265600003100000003461512027132661020570 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_header_definition.h @DESCRIPTION: Header file containing header description for ECAT files @GLOBALS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : * $Log: ecat_header_definition.h,v $ * Revision 6.1 1999-10-29 17:52:01 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:22 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:21 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:04 neelin * Release of minc version 0.4 * * Revision 1.2 1996/03/26 15:58:18 neelin * Added some more header values. * * Revision 1.1 1996/01/18 14:52:14 neelin * Initial revision * @COPYRIGHT : Copyright 1996 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Macro to set up header definition tables */ #define INITIAL_HEADER_TABLE(field_list) \ {FALSE, sizeof(field_list)/sizeof(field_list[0]), field_list, NULL} /* Main header and sub header descriptions for ECAT version 7 files */ static Ecat_field_description_type version_7_main_list[] = { {ECAT_Magic_Number, 0, 14, ecat_char, "Magic_Number"}, {ECAT_Original_Filename, 14, 32, ecat_char, "Original_Filename"}, {ECAT_Sw_Version, 46, 1, ecat_short, "Sw_Version"}, {ECAT_System_Type, 48, 1, ecat_short, "System_Type"}, {ECAT_File_Type, 50, 1, ecat_short, "File_Type"}, {ECAT_Serial_Number, 52, 10, ecat_char, "Serial_Number"}, {ECAT_Scan_Start_Time, 62, 1, ecat_long, "Scan_Start_Time"}, {ECAT_Isotope_Name, 66, 8, ecat_char, "Isotope_Name"}, {ECAT_Isotope_Halflife, 74, 1, ecat_float, "Isotope_Halflife"}, {ECAT_Radiopharmaceutical, 78, 32, ecat_char, "Radiopharmaceutical"}, {ECAT_Gantry_Tilt, 110, 1, ecat_float, "Gantry_Tilt"}, {ECAT_Gantry_Rotation, 114, 1, ecat_float, "Gantry_Rotation"}, {ECAT_Bed_Elevation, 118, 1, ecat_float, "Bed_Elevation"}, {ECAT_Intrinsic_Tilt, 122, 1, ecat_float, "Intrinsic_Tilt"}, {ECAT_Wobble_Speed, 126, 1, ecat_short, "Wobble_Speed"}, {ECAT_Transm_Source_Type, 128, 1, ecat_short, "Transm_Source_Type"}, {ECAT_Distance_Scanned, 130, 1, ecat_float, "Distance_Scanned"}, {ECAT_Transaxial_Fov, 134, 1, ecat_float, "Transaxial_Fov"}, {ECAT_Angular_Compression, 138, 1, ecat_short, "Angular_Compression"}, {ECAT_Coin_Samp_Mode, 140, 1, ecat_short, "Coin_Samp_Mode"}, {ECAT_Axial_Samp_Mode, 142, 1, ecat_short, "Axial_Samp_Mode"}, {ECAT_Calibration_Factor, 144, 1, ecat_float, "Calibration_Factor"}, {ECAT_Calibration_Units, 148, 1, ecat_short, "Calibration_Units"}, {ECAT_Calibration_Units_Label, 150, 1, ecat_short, "Calibration_Units_Label"}, {ECAT_Compression_Code, 152, 1, ecat_short, "Compression_Code"}, {ECAT_Study_Type, 154, 12, ecat_char, "Study_Type"}, {ECAT_Patient_Id, 166, 16, ecat_char, "Patient_Id"}, {ECAT_Patient_Name, 182, 32, ecat_char, "Patient_Name"}, {ECAT_Patient_Sex, 214, 1, ecat_char, "Patient_Sex"}, {ECAT_Patient_Dexterity, 215, 1, ecat_char, "Patient_Dexterity"}, {ECAT_Patient_Age, 216, 1, ecat_float, "Patient_Age"}, {ECAT_Patient_Height, 220, 1, ecat_float, "Patient_Height"}, {ECAT_Patient_Weight, 224, 1, ecat_float, "Patient_Weight"}, {ECAT_Patient_Birth_Date, 228, 1, ecat_long, "Patient_Birth_Date"}, {ECAT_Physician_Name, 232, 32, ecat_char, "Physician_Name"}, {ECAT_Operator_Name, 264, 32, ecat_char, "Operator_Name"}, {ECAT_Study_Description, 296, 32, ecat_char, "Study_Description"}, {ECAT_Acquision_Type, 328, 1, ecat_short, "Acquision_Type"}, {ECAT_Patient_Orientation, 330, 1, ecat_short, "Patient_Orientation"}, {ECAT_Facility_Name, 332, 20, ecat_char, "Facility_Name"}, {ECAT_Num_Planes, 352, 1, ecat_short, "Num_Planes"}, {ECAT_Num_Frames, 354, 1, ecat_short, "Num_Frames"}, {ECAT_Num_Gates, 356, 1, ecat_short, "Num_Gates"}, {ECAT_Num_Bed_Pos, 358, 1, ecat_short, "Num_Bed_Pos"}, {ECAT_Init_Bed_Position, 360, 1, ecat_float, "Init_Bed_Position"}, {ECAT_Bed_Position, 364, 15, ecat_float, "Bed_Position"}, {ECAT_Plane_Separation, 424, 1, ecat_float, "Plane_Separation"}, {ECAT_Lwr_Sctr_Thres, 428, 1, ecat_short, "Lwr_Sctr_Thres"}, {ECAT_Lwr_True_Thres, 430, 1, ecat_short, "Lwr_True_Thres"}, {ECAT_Upr_True_Thres, 432, 1, ecat_short, "Upr_True_Thres"}, {ECAT_User_Process_Code, 434, 10, ecat_char, "User_Process_Code"}, {ECAT_Acquisition_Mode, 444, 1, ecat_short, "Acquisition_Mode"}, {ECAT_Bin_Size, 446, 1, ecat_float, "Bin_Size"}, {ECAT_Branching_Fraction, 450, 1, ecat_float, "Branching_Fraction"}, {ECAT_Dose_Start_Time, 454, 1, ecat_long, "Dose_Start_Time"}, {ECAT_Dosage, 458, 1, ecat_float, "Dosage"}, {ECAT_Well_Counter_Corr_Factor, 462, 1, ecat_float, "Well_Counter_Corr_Factor"}, {ECAT_Data_Units, 466, 32, ecat_char, "Data_Units"}, {ECAT_Septa_State, 498, 1, ecat_short, "Septa_State"} }; static Ecat_field_description_type version_7_subhdr_list[] = { {ECAT_Data_Type, 0, 1, ecat_short, "Data_Type"}, {ECAT_Num_Dimensions, 2, 1, ecat_short, "Num_Dimensions"}, {ECAT_X_Dimension, 4, 1, ecat_short, "X_Dimension"}, {ECAT_Y_Dimension, 6, 1, ecat_short, "Y_Dimension"}, {ECAT_Z_Dimension, 8, 1, ecat_short, "Z_Dimension"}, {ECAT_X_Offset, 14, 1, ecat_float, "X_Offset"}, {ECAT_Y_Offset, 18, 1, ecat_float, "Y_Offset"}, {ECAT_Z_Offset, 10, 1, ecat_float, "Z_Offset"}, {ECAT_Recon_Zoom, 22, 1, ecat_float, "Recon_Zoom"}, {ECAT_Scale_Factor, 26, 1, ecat_float, "Scale_Factor"}, {ECAT_Image_Min, 30, 1, ecat_short, "Image_Min"}, {ECAT_Image_Max, 32, 1, ecat_short, "Image_Max"}, {ECAT_X_Pixel_Size, 34, 1, ecat_float, "X_Pixel_Size"}, {ECAT_Y_Pixel_Size, 38, 1, ecat_float, "Y_Pixel_Size"}, {ECAT_Z_Pixel_Size, 42, 1, ecat_float, "Z_Pixel_Size"}, {ECAT_Frame_Duration, 46, 1, ecat_long, "Frame_Duration"}, {ECAT_Frame_Start_Time, 50, 1, ecat_long, "Frame_Start_Time"}, {ECAT_Filter_Code, 54, 1, ecat_short, "Filter_Code"}, {ECAT_X_Resolution, 56, 1, ecat_float, "X_Resolution"}, {ECAT_Y_Resolution, 60, 1, ecat_float, "Y_Resolution"}, {ECAT_Z_Resolution, 64, 1, ecat_float, "Z_Resolution"}, {ECAT_X_Rotation_Angle, 68, 1, ecat_float, "X_Rotation_Angle"}, {ECAT_Y_Rotation_Angle, 72, 1, ecat_float, "Y_Rotation_Angle"}, {ECAT_Z_Rotation_Angle, 76, 1, ecat_float, "Z_Rotation_Angle"}, {ECAT_Decay_Corr_Fctr, 80, 1, ecat_float, "Decay_Corr_Fctr"}, {ECAT_Corrections_Applied, 84, 1, ecat_long, "Corrections_Applied"}, {ECAT_Gate_Duration, 88, 1, ecat_long, "Gate_Duration"}, {ECAT_R_Wave_Offset, 92, 1, ecat_long, "R_Wave_Offset"}, {ECAT_Num_Accepted_Beats, 96, 1, ecat_long, "Num_Accepted_Beats"}, {ECAT_Filter_Cutoff_Frequency, 100, 1, ecat_float, "Filter_Cutoff_Frequency"}, {ECAT_Filter_Dc_Component, 104, 1, ecat_float, "Filter_Dc_Component"}, {ECAT_Filter_Ramp_Slope, 108, 1, ecat_float, "Filter_Ramp_Slope"}, {ECAT_Filter_Order, 112, 1, ecat_short, "Filter_Order"}, {ECAT_Filter_Scatter_Fraction, 114, 1, ecat_float, "Filter_Scatter_Fraction"}, {ECAT_Filter_Scatter_Slope, 118, 1, ecat_float, "Filter_Scatter_Slope"}, {ECAT_Annotation, 122, 40, ecat_char, "Annotation"}, {ECAT_Da_X_Rotation_Angle, 162, 1, ecat_float, "Da_X_Rotation_Angle"}, {ECAT_Da_Y_Rotation_Angle, 166, 1, ecat_float, "Da_Y_Rotation_Angle"}, {ECAT_Da_Z_Rotation_Angle, 170, 1, ecat_float, "Da_Z_Rotation_Angle"}, {ECAT_Da_X_Translation, 174, 1, ecat_float, "Da_X_Translation"}, {ECAT_Da_Y_Translation, 178, 1, ecat_float, "Da_Y_Translation"}, {ECAT_Da_Z_Translation, 182, 1, ecat_float, "Da_Z_Translation"}, {ECAT_Da_X_Scale_Factor, 186, 1, ecat_float, "Da_X_Scale_Factor"}, {ECAT_Da_Y_Scale_Factor, 190, 1, ecat_float, "Da_Y_Scale_Factor"}, {ECAT_Da_Z_Scale_Factor, 194, 1, ecat_float, "Da_Z_Scale_Factor"}, {ECAT_Rfilter_Cutoff, 198, 1, ecat_float, "Rfilter_Cutoff"}, {ECAT_Rfilter_Resolution, 202, 1, ecat_float, "Rfilter_Resolution"}, {ECAT_Rfilter_Code, 206, 1, ecat_short, "Rfilter_Code"}, {ECAT_Rfilter_Order, 208, 1, ecat_short, "Rfilter_Order"}, {ECAT_Zfilter_Cutoff, 210, 1, ecat_float, "Zfilter_Cutoff"}, {ECAT_Zfilter_Resolution, 214, 1, ecat_float, "Zfilter_Resolution"}, {ECAT_Zfilter_Code, 218, 1, ecat_short, "Zfilter_Code"}, {ECAT_Zfilter_Order, 220, 1, ecat_short, "Zfilter_Order"} }; static Ecat_header_table_type version_7_main_table = INITIAL_HEADER_TABLE(version_7_main_list); static Ecat_header_table_type version_7_subhdr_table = INITIAL_HEADER_TABLE(version_7_subhdr_list); static Ecat_header_description_type version_7_description = { &version_7_main_table, &version_7_subhdr_table }; static Ecat_header_description_type *ECAT_VER_7 = &version_7_description; /* Main header and sub header descriptions for ECAT files before version 7 */ static Ecat_field_description_type version_pre7_main_list[] = { {ECAT_Original_Filename, 28, 20, ecat_char, "Original_Filename"}, {ECAT_Sw_Version, 48, 1, ecat_short, "Sw_Version"}, {ECAT_Data_Type, 50, 1, ecat_short, "Data_type"}, {ECAT_System_Type, 52, 1, ecat_short, "System_Type"}, {ECAT_File_Type, 54, 1, ecat_short, "File_Type"}, {ECAT_Serial_Number, 56, 10, ecat_char, "Serial_Number"}, {ECAT_Scan_Start_Day, 66, 1, ecat_short, "Scan_Start_Day"}, {ECAT_Scan_Start_Month, 68, 1, ecat_short, "Scan_Start_Month"}, {ECAT_Scan_Start_Year, 70, 1, ecat_short, "Scan_Start_Year"}, {ECAT_Scan_Start_Hour, 72, 1, ecat_short, "Scan_Start_Hour"}, {ECAT_Scan_Start_Minute, 74, 1, ecat_short, "Scan_Start_Minute"}, {ECAT_Scan_Start_Second, 76, 1, ecat_short, "Scan_Start_Second"}, {ECAT_Isotope_Name, 78, 8, ecat_char, "Isotope_Name"}, {ECAT_Isotope_Halflife, 86, 1, ecat_float, "Isotope_Halflife"}, {ECAT_Radiopharmaceutical, 90, 32, ecat_char, "Radiopharmaceutical"}, {ECAT_Gantry_Tilt, 122, 1, ecat_float, "Gantry_Tilt"}, {ECAT_Gantry_Rotation, 126, 1, ecat_float, "Gantry_Rotation"}, {ECAT_Bed_Elevation, 130, 1, ecat_float, "Bed_Elevation"}, {ECAT_Rot_Source_Speed, 134, 1, ecat_short, "Rot_Source_Speed"}, {ECAT_Wobble_Speed, 136, 1, ecat_short, "Wobble_Speed"}, {ECAT_Transm_Source_Type, 138, 1, ecat_short, "Transm_Source_Type"}, {ECAT_Distance_Scanned, 140, 1, ecat_float, "Distance_Scanned"}, {ECAT_Transaxial_Fov, 144, 1, ecat_float, "Transaxial_Fov"}, {ECAT_Coin_Samp_Mode, 150, 1, ecat_short, "Coin_Samp_Mode"}, {ECAT_Axial_Samp_Mode, 152, 1, ecat_short, "Axial_Samp_Mode"}, {ECAT_Calibration_Factor, 154, 1, ecat_float, "Calibration_Factor"}, {ECAT_Calibration_Units, 158, 1, ecat_short, "Calibration_Units"}, {ECAT_Compression_Code, 160, 1, ecat_short, "Compression_Code"}, {ECAT_Study_Type, 162, 12, ecat_char, "Study_Type"}, {ECAT_Patient_Id, 174, 16, ecat_char, "Patient_Id"}, {ECAT_Patient_Name, 190, 32, ecat_char, "Patient_Name"}, {ECAT_Patient_Sex, 222, 1, ecat_char, "Patient_Sex"}, {ECAT_Patient_Age, 223, 10, ecat_char, "Patient_Age"}, {ECAT_Patient_Height, 233, 10, ecat_char, "Patient_Height"}, {ECAT_Patient_Weight, 243, 10, ecat_char, "Patient_Weight"}, {ECAT_Patient_Dexterity, 253, 1, ecat_char, "Patient_Dexterity"}, {ECAT_Physician_Name, 254, 32, ecat_char, "Physician_Name"}, {ECAT_Operator_Name, 286, 32, ecat_char, "Operator_Name"}, {ECAT_Study_Description, 318, 32, ecat_char, "Study_Description"}, {ECAT_Acquision_Type, 350, 1, ecat_short, "Acquision_Type"}, {ECAT_Facility_Name, 356, 20, ecat_char, "Facility_Name"}, {ECAT_Num_Planes, 376, 1, ecat_short, "Num_Planes"}, {ECAT_Num_Frames, 378, 1, ecat_short, "Num_Frames"}, {ECAT_Num_Gates, 380, 1, ecat_short, "Num_Gates"}, {ECAT_Num_Bed_Pos, 382, 1, ecat_short, "Num_Bed_Pos"}, {ECAT_Init_Bed_Position, 384, 1, ecat_float, "Init_Bed_Position"}, {ECAT_Bed_Position, 388, 15, ecat_float, "Bed_Position"}, {ECAT_Plane_Separation, 448, 1, ecat_float, "Plane_Separation"}, {ECAT_Lwr_Sctr_Thres, 452, 1, ecat_short, "Lwr_Sctr_Thres"}, {ECAT_Lwr_True_Thres, 454, 1, ecat_short, "Lwr_True_Thres"}, {ECAT_Upr_True_Thres, 456, 1, ecat_short, "Upr_True_Thres"}, {ECAT_User_Process_Code, 462, 10, ecat_char, "User_Process_Code"} }; static Ecat_field_description_type version_pre7_subhdr_list[] = { {ECAT_Data_Type, 126, 1, ecat_short, "Data_Type"}, {ECAT_Num_Dimensions, 128, 1, ecat_short, "Num_Dimensions"}, {ECAT_X_Dimension, 132, 1, ecat_short, "X_Dimension"}, {ECAT_Y_Dimension, 134, 1, ecat_short, "Y_Dimension"}, {ECAT_X_Offset, 160, 1, ecat_float, "X_Offset"}, {ECAT_Y_Offset, 164, 1, ecat_float, "Y_Offset"}, {ECAT_Recon_Zoom, 168, 1, ecat_float, "Recon_Zoom"}, {ECAT_Scale_Factor, 172, 1, ecat_float, "Scale_Factor"}, {ECAT_Image_Min, 176, 1, ecat_short, "Image_Min"}, {ECAT_Image_Max, 178, 1, ecat_short, "Image_Max"}, {ECAT_X_Pixel_Size, 184, 1, ecat_float, "X_Pixel_Size"}, {ECAT_Y_Pixel_Size, 184, 1, ecat_float, "Y_Pixel_Size"}, /* Same location */ {ECAT_Z_Pixel_Size, 188, 1, ecat_float, "Z_Pixel_Size"}, {ECAT_Frame_Duration, 192, 1, ecat_long, "Frame_Duration"}, {ECAT_Frame_Start_Time, 196, 1, ecat_long, "Frame_Start_Time"}, {ECAT_Filter_Code, 236, 1, ecat_short, "Filter_Code"}, {ECAT_Z_Rotation_Angle, 296, 1, ecat_float, "Z_Rotation_Angle"}, {ECAT_Decay_Corr_Fctr, 304, 1, ecat_float, "Decay_Corr_Fctr"}, {ECAT_Calibration_Factor, 388, 1, ecat_float, "Calibration_Factor"}, {ECAT_Filter_Cutoff_Frequency, 396, 1, ecat_float, "Filter_Cutoff_Frequency"}, {ECAT_Filter_Dc_Component, 400, 1, ecat_float, "Filter_Dc_Component"}, {ECAT_Filter_Ramp_Slope, 404, 1, ecat_float, "Filter_Ramp_Slope"}, {ECAT_Annotation, 420, 40, ecat_char, "Annotation"} }; static Ecat_header_table_type version_pre7_main_table = INITIAL_HEADER_TABLE(version_pre7_main_list); static Ecat_header_table_type version_pre7_subhdr_table = INITIAL_HEADER_TABLE(version_pre7_subhdr_list); static Ecat_header_description_type version_pre7_description = { &version_pre7_main_table, &version_pre7_subhdr_table }; static Ecat_header_description_type *ECAT_VER_PRE7 = &version_pre7_description; minc-2.2.00/conversion/ecattominc/ecattominc.man10000644000265600003100000000461412027132661016663 00000000000000.TH "ecattominc" "1" "" "" "" .SH "NAME" ecattominc \- convert an ecat format file (version 6.x or 7.x) to a minc format file .SH "SYNOPSIS" \fBecattominc [] \fR \fBecattominc [\-help]\fR .SH "DESCRIPTION" \fIecattominc\fR will convert an ecat data file (version 6.x or 7.x) to a minc file format Unless the \fB\-small_header\fR option is specified, \fBecattominc\fR will conserve the maximum informations from the ecat header and subheader fields which will be respectively stored as attributes of the ecat\-main and ecat\-subhdr minc variables. By default the whole 3D or 4D volume is converted, however, \fBecattominc\fR allows for the selection of slice and frame ranges to be copied. The voxel values of the generated minc file are decay corrected, unless the \fBnodecay_correct\fR flag is specified. Finally, blood data file can be inserted within the minc file with the \fB\-bloodfile\fR option. .SH "OPTIONS" Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH "General options" .TP \fI\-byte:\fR Write out data as bytes (default). .TP \fI\-short:\fR Write out data as short integers. .TP \fI\-clobber:\fR Overwrite existing file. .TP \fI\-noclobber:\fR Don't overwrite existing file (default). .TP \fI\-verbose:\fR List files as they are converted (default) .TP \fI\-quiet:\fR Do not list files as they are converted. .SH "Command specific options" \fI\-decay_correct:\fR Do decay correction on images (default). .TP \fI\-nodecay_correct:\fR Don't do decay correction. .TP \fI\-slices:\fRRange of slices to copy (counting from 0). Default value: \-2147483648 \-2147483648 .TP \fI\-frames:\fR Range of frames to copy (counting from 0). Default value: \-2147483648 \-2147483648 .TP \fI\-frame:\fR Single frame to copy (counting from 0). Default value: \-2147483648 .TP \fI\-small_header:\fR Copy only basic header information. .TP \fI\-all_header:\fR Copy all header information (default). .TP \fI\-bloodfile:\fR Insert blood data from this file. .SH "Generic options for all commands" .TP \fI\-help:\fR Print summary of command\-line options and abort .SH "KNOWN BUGS" No bug listed so far :=) .SH "SEE ALSO" minctoecat(1), rawtominc(1), minctoraw(1), dicomtominc(1) .SH "AUTHOR" Peter Neelin and Anthonin Reilhac (anthonin.reilhac@cermep.fr) .SH "COPYRIGHTS" Copyrights 2005 by Peter Neelin minc-2.2.00/conversion/ecattominc/ecattominc.c0000644000265600003100000017241012027132661016251 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : ecattominc @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : error status @DESCRIPTION: Converts a CTI ECAT file to a minc format file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 3, 1996 (Peter Neelin) @MODIFIED : * $Log: ecattominc.c,v $ * Revision 6.7 2008-04-11 05:16:02 rotor * * added config.h to ecattominc * * removed minc_globdef.h from Makefile.am * * Revision 6.6 2008/01/17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.5 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.4 2005/01/19 19:46:01 bert * Changes from Anthonin Reilhac * * * Revision 7.0 2004/08/13 Anthonin Reilhac * Portage of the code under linux environment * - little / big Indian conversion * - the vax conversion routines are now included within the distribution * - MALLOC, REALLOC and FREE macros definined within the ecat_file.h body * MALLOC and REALLOC use the malloc_check and realloc_check in ecat_file.c * which are not private(static) anymore * mni_def.h is not used anymore and * Fixed x and y flipping when y size is odd. * Did not show up before since normal x and y size are even * * Revision 6.3 2000/09/08 18:17:15 neelin * Fixed swapping of x and y sizes when getting dimensions sizes from ecat file. * This has not previously shown up since normal ECAT images are square. * * Revision 6.2 1999/11/09 13:44:56 neelin * Year 2000 fixes for scan date in minc file. * * Revision 6.1 1999/10/29 17:52:01 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:22 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:21 neelin * Release of minc version 0.5 * * Revision 4.1 1997/05/16 18:21:37 neelin * Changed calculation of z filter width to use BinSize rather than * PlaneSeparation. * * Revision 4.0 1997/05/07 20:06:04 neelin * Release of minc version 0.4 * * Revision 1.2 1996/03/26 15:58:18 neelin * Various changes including changed coordinates in x and y and computing * FWHM from cutoff frequency. * * Revision 1.1 1996/01/18 14:52:14 neelin * Initial revision * @COPYRIGHT : Copyright 1996 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include /*#include modif anthonin */ #include "ecat_file.h" /* Type declarations */ typedef struct { char *name; char *values; } ecat_header_data_type; typedef struct { int nslices; int low_slice; int high_slice; double scan_time; double time_width; double half_life; double zstart; double zstep; double decay_correction; char isotope[16]; int image_xsize; int image_ysize; int ordered_frame; int *ordered_slices; char image_type[16]; } frame_info_type; typedef struct { int low_frame; int high_frame; int num_slices; int max_nslices; int max_xsize; int max_ysize; double xstart; double ystart; double xstep; double ystep; double xwidth; double ywidth; double zwidth; int decay_corrected; char img_units[16]; char patient_name[40]; char patient_sex[8]; long patient_age; char patient_birthdate[40]; char study_id[40]; char start_time[40]; long start_year; long start_month; long start_day; long start_hour; long start_minute; double start_seconds; char tracer[40]; char injection_time[40]; long injection_hour; long injection_minute; double injection_seconds; double injection_dose; int septa_retracted; ecat_header_data_type *main_field_list; int num_main_fields; ecat_header_data_type *subhdr_field_list; int num_subhdr_fields; } general_info_type; typedef struct { double sort_key; void *sort_value; } sort_type; /* Function declarations */ void usage_error(char *progname); int get_frame_info(Ecat_file *ecat_fp, int slice_range[2], int num_frames, frame_info_type *frame_info, general_info_type *general_info); void sort_slices(int sort_over_time, int num_frames, frame_info_type *frame_info, general_info_type *general_info); int sortcmp(const void *val1, const void *val2); int setup_minc_file(int mincid, int write_byte_data, int copy_all_header, int ndims, long count[], int num_frames, frame_info_type *frame_info, general_info_type *general_info, char *blood_file); int get_slice(Ecat_file *ecat_fp, int frame_num, int slice_num, long *pixel_max, double *image_max, short *image, frame_info_type *frame_info, general_info_type *general_info); int write_minc_slice(double scale, int write_byte_data, int mincid, int icvid, int ndims,long start[], long count[], short *image, int image_xsize, int image_ysize, long pixel_max, double image_max, double scan_time, double time_width, double zpos); double decay_correction(double scan_time, double measure_time, double start_time, double half_life); void CreateBloodStructures (int mincHandle, int bloodHandle); void FillBloodStructures (int mincHandle, int bloodHandle); /* Constants */ #define TRUE 1 #define FALSE 0 #define MAX_DIMS 4 #define ECAT_ACTIVITY "ACTIVITY" #define ECAT_CALIB_UNITS_UNKNOWN 0 #define ECAT_CALIB_UNITS_BECQUEREL 1 #define ECAT_CALIB_UNITS_CPS 3 #define MM_PER_CM 10.0 #define BECQUEREL_PER_NCURIE 37 #define BECQUEREL_PER_MCURIE (BECQUEREL_PER_NCURIE * 1e6) #define NCURIE_PER_CC_STRING "nCi/cc" #define SECONDS_PER_HOUR 3600 #define DEFAULT_RANGE INT_MIN #define MINIMUM_HALFLIFE 0.1 #define FWHM_SCALE_FOR_HANN 1.082 /* we don't need mni_def anymore*/ /*#define MALLOC(size) ((void *) malloc(size)) #define FREE(ptr) free( (void *) ptr) #define REALLOC(ptr, size) ((void *) realloc(ptr, size))*/ /* Main program */ int main(int argc, char *argv[]) { /* Variables for arguments */ static int write_byte_data = TRUE; static int clobber = FALSE; static int verbose = TRUE; static int decay_correct = TRUE; static int slice_range[2] = {DEFAULT_RANGE, DEFAULT_RANGE}; static int copy_all_header = TRUE; static char *blood_file = NULL; static int frame_range[2] = {DEFAULT_RANGE, DEFAULT_RANGE}; /* Argument option table */ static ArgvInfo argTable[] = { {"-byte", ARGV_CONSTANT, (char *) TRUE, (char *) &write_byte_data, "Write out data as bytes (default)."}, {"-short", ARGV_CONSTANT, (char *) FALSE, (char *) &write_byte_data, "Write out data as short integers."}, {"-decay_correct", ARGV_CONSTANT, (char *) TRUE, (char *) &decay_correct, "Do decay correction on images (default)."}, {"-nodecay_correct", ARGV_CONSTANT, (char *) FALSE, (char *) &decay_correct, "Don't do decay correction."}, {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "List files as they are converted (default)"}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not list files as they are converted."}, {"-slices", ARGV_INT, (char *) 2, (char *) slice_range, "Range of slices to copy (counting from 0)."}, {"-frames", ARGV_INT, (char *) 2, (char *) frame_range, "Range of frames to copy (counting from 0)."}, {"-frame", ARGV_INT, (char *) 1, (char *) frame_range, "Single frame to copy (counting from 0)."}, {"-small_header", ARGV_CONSTANT, (char *) FALSE, (char *) ©_all_header, "Copy only basic header information."}, {"-all_header", ARGV_CONSTANT, (char *) TRUE, (char *) ©_all_header, "Copy all header information (default)."}, {"-bloodfile", ARGV_STRING, (char *) 1, (char *) &blood_file, "Insert blood data from this file."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Other variables */ char *pname; /*name of the present command ->argv[0]*/ char *mincfile; /*name of the minc file = output*/ char *ecat_filename; /*name of the ecat7 file = input*/ int num_frames; int num_bed_positions; int sort_over_time; frame_info_type *frame_info; general_info_type *general_info; long count[MAX_DIMS], start[MAX_DIMS]; int ndims; int mincid, icvid, varid; int islice, iframe, i, slice_num, ifield, frame_num, low_frame, high_frame; long pixel_max; double image_max; double scale; short *image; Ecat_file *ecat_fp; int status; char *tm_stamp; /******** pk for minchistory*/ double first_z, last_z, zstep; /* Get time stamp */ tm_stamp = time_stamp(argc, argv); /* Check arguments */ pname = argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || (argc != 3)) { usage_error(pname); } /* Check the slice range */ if (slice_range[0] == DEFAULT_RANGE) { slice_range[0] = 0; slice_range[1] = INT_MAX; } else if (slice_range[1] == DEFAULT_RANGE) { slice_range[1] = slice_range[0]; } if ((slice_range[0] < 0) || (slice_range[1] < 0) || (slice_range[1] < slice_range[0])) { (void) fprintf(stderr, "%s: Error in slice range: %d to %d.\n", pname, slice_range[0], slice_range[1]); exit(EXIT_FAILURE); } /* Check the frame range */ if (frame_range[0] == DEFAULT_RANGE) { frame_range[0] = 0; frame_range[1] = INT_MAX; } else if (frame_range[1] == DEFAULT_RANGE) { frame_range[1] = frame_range[0]; } if ((frame_range[0] < 0) || (frame_range[1] < 0) || (frame_range[1] < frame_range[0])) { (void) fprintf(stderr, "%s: Error in frame range: %d to %d.\n", pname, frame_range[0], frame_range[1]); exit(EXIT_FAILURE); } /* Get file names */ ecat_filename = argv[1]; mincfile = argv[2]; /* Open the ECAT file */ if ((ecat_fp=ecat_open(ecat_filename))==NULL) { (void) fprintf(stderr, "%s: Error opening file %s.\n", pname, ecat_filename); exit(EXIT_FAILURE); } /* Get number of frames and bed positions to see if we are varying over time or interleaving slices */ num_frames = ecat_get_num_frames(ecat_fp); num_bed_positions = ecat_get_num_bed_positions(ecat_fp); sort_over_time = TRUE; if ((num_frames > 1) && (num_bed_positions > 1)) { (void) fprintf(stderr, "%s: Cannot handle multiple frames and bed positions.\n", pname); exit(EXIT_FAILURE); } if (num_bed_positions > 1) { num_frames = num_bed_positions; sort_over_time = FALSE; } /* Print log message */ if (verbose) { (void) fprintf(stderr, "Reading headers.\n"); } /* Get frame range */ low_frame = 0; high_frame = num_frames - 1; if (frame_range[0] > low_frame) low_frame = frame_range[0]; if (frame_range[1] < high_frame) high_frame = frame_range[1]; if (low_frame > high_frame) low_frame = high_frame; num_frames = high_frame - low_frame + 1; /* Read the files to get basic information */ general_info=MALLOC(sizeof(*general_info)); frame_info = MALLOC(num_frames * sizeof(*frame_info)); general_info->low_frame = low_frame; general_info->high_frame = high_frame; status=get_frame_info(ecat_fp, slice_range, num_frames, frame_info, general_info); if (status >= 0) { (void) fprintf(stderr, "%s: Error reading ECAT file %s on frame %d.\n", pname, ecat_filename, status); exit(EXIT_FAILURE); } /* Allocate space for ordered slice list if sorting over z position */ if (!sort_over_time) { for (iframe=0; iframe1)) { ndims = 4; count[0]=num_frames; count[1]=general_info->max_nslices; } else { ndims=3; count[0]=general_info->num_slices; } count[ndims-1] = general_info->max_xsize; count[ndims-2] = general_info->max_ysize; mincid = micreate(mincfile, (clobber ? NC_CLOBBER : NC_NOCLOBBER)); (void) miattputstr(mincid, NC_GLOBAL, MIhistory, tm_stamp); icvid=setup_minc_file(mincid, write_byte_data, copy_all_header, ndims, count, num_frames, frame_info, general_info, blood_file); if (icvid==MI_ERROR) { (void) fprintf(stderr, "%s: Error setting up minc file %s.\n", pname, mincfile); exit(EXIT_FAILURE); } /* Initialize minc start and count vectors */ for (i=0; imax_xsize * general_info->max_ysize * sizeof(short)); /* Print log message */ if (verbose) { (void) fprintf(stderr, "Copying frames:"); (void) fflush(stderr); } /* Loop through files */ for (iframe=0; iframedecay_corrected && (strcmp(frame_info[iframe].image_type, ECAT_ACTIVITY) == 0)) { scale = decay_correction(frame_info[iframe].scan_time, frame_info[iframe].time_width, 0.0, frame_info[iframe].half_life); } else if (!decay_correct && general_info->decay_corrected) { scale = 1.0 / frame_info[iframe].decay_correction; } else { scale = 1.0; } /* Loop through slices */ for (islice = 0; islice < frame_info[iframe].nslices; islice++) { /* Set the minc coordinates */ if (sort_over_time && (num_frames>1)) { start[0]=frame_info[iframe].ordered_frame; start[1]=islice; } else if (sort_over_time) start[0]=islice; else start[0]=frame_info[iframe].ordered_slices[islice]; count[ndims-1] = frame_info[iframe].image_xsize; count[ndims-2] = frame_info[iframe].image_ysize; /* Copy the slice */ slice_num = islice + frame_info[iframe].low_slice; frame_num = iframe + general_info->low_frame; if (get_slice(ecat_fp, frame_num, slice_num, &pixel_max, &image_max, image, &frame_info[iframe], general_info) || write_minc_slice(scale, write_byte_data, mincid, icvid, ndims, start, count, image, frame_info[iframe].image_xsize, frame_info[iframe].image_ysize, pixel_max, image_max, frame_info[iframe].scan_time, frame_info[iframe].time_width, frame_info[iframe].zstep * (double) slice_num + frame_info[iframe].zstart)) { (void) fprintf(stderr, "%s: Error copying slice %d from frame %d.\n", pname, slice_num, frame_num); exit(EXIT_FAILURE); } } /* End slice loop */ } /* End frame loop */ /* Write out average z step and start for irregularly spaced slices */ if ((ndims!=MAX_DIMS) && (num_frames>1)) { start[0] = 0; varid = ncvarid(mincid, MIzspace); (void) mivarget1(mincid, varid, start, NC_DOUBLE, NULL, &first_z); start[0] = general_info->num_slices - 1; (void) mivarget1(mincid, varid, start, NC_DOUBLE, NULL, &last_z); if (start[0] > 0) zstep = (last_z - first_z) / ((double) start[0]); else zstep = 1.0; (void) miattputdbl(mincid, varid, MIstep, zstep); (void) miattputdbl(mincid, varid, MIstart, first_z); } /* Close minc file */ (void) miattputstr(mincid, ncvarid(mincid, MIimage), MIcomplete, MI_TRUE); (void) miclose(mincid); /* Write out log message */ if (verbose) { (void) fprintf(stderr, "Done\n"); (void) fflush(stderr); } FREE(image); if (!sort_over_time) { for (iframe=0; iframenum_main_fields; ifield++) { FREE(general_info->main_field_list[ifield].name); FREE(general_info->main_field_list[ifield].values); } for (ifield=0; ifield < general_info->num_subhdr_fields; ifield++) { FREE(general_info->subhdr_field_list[ifield].name); FREE(general_info->subhdr_field_list[ifield].values); } FREE(general_info->main_field_list); FREE(general_info->subhdr_field_list); FREE(general_info); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : usage_error @INPUT : progname - program name @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Prints a usage error message and exits. @METHOD : @GLOBALS : @CALLS : @CREATED : January 3, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void usage_error(char *progname) { (void) fprintf(stderr, "\nUsage: %s [] \n", progname); (void) fprintf(stderr, " %s [-help]\n\n", progname); exit(EXIT_FAILURE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_frame_info @INPUT : ecat_fp - file pointer for ecat file slice_range - 2-component array giving range of slices num_frames - number of frames @OUTPUT : frame_info - array of structures containing information about each frame. general_info - general information about the file. @RETURNS : (-1) if no error occurs, otherwise, the index of the first frame that could not be read. @DESCRIPTION: Reads information for frame in the ECAT file @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int get_frame_info(Ecat_file *ecat_fp, int slice_range[2], int num_frames, frame_info_type *frame_info, general_info_type *general_info) { static char *the_months[]= {NULL, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; int *num_slices, *max_nslices, *max_xsize, *max_ysize; int start_day, start_month, start_year; int start_hour, start_minute, start_seconds; frame_info_type *fip; int lvalue; double fvalue; char svalue[ECAT_MAX_STRING_LENGTH]; int iframe, ifield, imult, num_fields, iheader, curframe; int length, newlength, multiplicity; struct tm *tm_ptr; ecat_header_data_type *field_list; Ecat_field_name field; char *description; time_t the_time; char *ptr; int isotope_name_okay; int septa_state; double cutoff, binsize; /* Initialize number of slices */ num_slices = &(general_info->num_slices); max_nslices = &(general_info->max_nslices); max_xsize = &(general_info->max_xsize); max_ysize = &(general_info->max_ysize); *num_slices = 0; *max_nslices = 0; *max_xsize = *max_ysize = 0; general_info->decay_corrected = FALSE; /* Loop through files, reading information */ for (iframe=0; iframelow_frame; /* Get number of slices */ fip->low_slice = 0; fip->high_slice = ecat_get_num_planes(ecat_fp) - 1; if (slice_range[0] > fip->low_slice) fip->low_slice = slice_range[0]; if (slice_range[1] < fip->high_slice) fip->high_slice = slice_range[1]; if (fip->low_slice > fip->high_slice) fip->low_slice = fip->high_slice; fip->nslices = fip->high_slice - fip->low_slice + 1; *num_slices += fip->nslices; if (fip->nslices > *max_nslices) *max_nslices = fip->nslices; /* Get image width */ if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_X_Dimension, 0, &lvalue, NULL, NULL)) return curframe; fip->image_xsize = lvalue; if (lvalue > *max_xsize) *max_xsize = lvalue; if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Y_Dimension, 0, &lvalue, NULL, NULL)) return curframe; fip->image_ysize = lvalue; if (lvalue > *max_ysize) *max_ysize = lvalue; /* Get frame start time (in seconds) */ if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Frame_Start_Time, 0, &lvalue, NULL, NULL)) return curframe; fip->scan_time = (double) lvalue / 1000.0; /* Get length of frame (in seconds) */ if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Frame_Duration, 0, &lvalue, NULL, NULL)) return curframe; fip->time_width = (double) lvalue / 1000.0; /* Get scan type */ if (ecat_get_main_value(ecat_fp, ECAT_Calibration_Units, 0, &lvalue, NULL, NULL)) return curframe; if ((lvalue == ECAT_CALIB_UNITS_BECQUEREL) || (lvalue == ECAT_CALIB_UNITS_UNKNOWN) || (lvalue == ECAT_CALIB_UNITS_CPS)) { (void) strcpy(fip->image_type, ECAT_ACTIVITY); } else { (void) strcpy(fip->image_type, ""); } /* Get isotope and half-life */ if (ecat_get_main_value(ecat_fp, ECAT_Isotope_Name, 0, NULL, NULL, fip->isotope)) return curframe; if (ecat_get_main_value(ecat_fp, ECAT_Isotope_Halflife, 0, NULL, &fip->half_life, NULL)) return curframe; /* Check that they are reasonable */ isotope_name_okay = TRUE; for (ptr=fip->isotope; (*ptr != '\0') && (ptr < &fip->isotope[sizeof(fip->isotope)]); ptr++) { if (!isprint((int) *ptr)) { isotope_name_okay = FALSE; } } if (ptr == fip->isotope) isotope_name_okay = FALSE; if (!isotope_name_okay || (fip->half_life < MINIMUM_HALFLIFE)) { (void) fprintf(stderr, "Ignoring bad isotope name or half-life.\n"); fip->isotope[0] = '\0'; fip->half_life = 0.0; } /* Get z start and step (correct start for non-zero first slice */ if (ecat_get_main_value(ecat_fp, ECAT_Plane_Separation, 0, NULL, &fip->zstep, NULL)) return curframe; fip->zstep *= -MM_PER_CM; if (ecat_get_num_bed_positions(ecat_fp) <= 1) { if (ecat_get_main_value(ecat_fp, ECAT_Init_Bed_Position, 0, NULL, &fip->zstart, NULL)) return curframe; } else { if (ecat_get_main_value(ecat_fp, ECAT_Bed_Position, curframe, NULL, &fip->zstart, NULL)) return curframe; } fip->zstart *= -MM_PER_CM; fip->zstart += fip->low_slice * fip->zstep; /* Check to see if file has been decay corrected */ fvalue = 1.0; (void) ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Decay_Corr_Fctr, 0, NULL, &fvalue, NULL); if (fvalue <= 0.0) fvalue = 1.0; fip->decay_correction = fvalue; if (fip->decay_correction != 1.0) { general_info->decay_corrected = TRUE; } /* Get general information from first frame */ if (iframe==0) { /* Get pixel sizes */ if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_X_Pixel_Size, 0, NULL, &general_info->xstep, NULL)) return curframe; if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Y_Pixel_Size, 0, NULL, &general_info->ystep, NULL)) return curframe; general_info->xstep *= MM_PER_CM; general_info->ystep *= MM_PER_CM; /* Get location of first voxel */ if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_X_Offset, 0, NULL, &general_info->xstart, NULL)) return curframe; if (ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Y_Offset, 0, NULL, &general_info->ystart, NULL)) return curframe; general_info->xstart *= -MM_PER_CM; general_info->ystart *= MM_PER_CM; general_info->xstart -= general_info->xstep * ((double) fip->image_xsize - 1.0) / 2.0; general_info->ystart -= general_info->ystep * ((double) fip->image_ysize - 1.0) / 2.0; /* Get resolution in each direction (or zero if not found) */ general_info->xwidth = general_info->ywidth = general_info->zwidth = -1.0; (void) ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_X_Resolution, 0, NULL, &general_info->xwidth, NULL); (void) ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Y_Resolution, 0, NULL, &general_info->ywidth, NULL); (void) ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Z_Resolution, 0, NULL, &general_info->zwidth, NULL); general_info->xwidth *= MM_PER_CM; general_info->ywidth *= MM_PER_CM; general_info->zwidth *= MM_PER_CM; /* If resolution is not found, then use cutoff frequency and assume FWHM for Hann filter */ cutoff = -1.0; binsize = -1.0; (void) ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Rfilter_Cutoff, 0, NULL, &cutoff, NULL); if (cutoff <= 0) { (void) ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Filter_Cutoff_Frequency, 0, NULL, &cutoff, NULL); } (void) ecat_get_main_value(ecat_fp, ECAT_Bin_Size, 0, NULL, &binsize, NULL); binsize *= MM_PER_CM; if ((general_info->xwidth <= 0.0) && (cutoff > 0.0) && (binsize > 0.0)) { general_info->xwidth = FWHM_SCALE_FOR_HANN * binsize / cutoff; } if ((general_info->ywidth <= 0.0) && (cutoff > 0.0) && (binsize > 0.0)) { general_info->ywidth = FWHM_SCALE_FOR_HANN * binsize / cutoff; } if ((general_info->zwidth <= 0.0) && !ecat_get_subhdr_value(ecat_fp, curframe, 0, ECAT_Zfilter_Cutoff, 0, NULL, &cutoff, NULL)) { general_info->zwidth = FWHM_SCALE_FOR_HANN * binsize / cutoff; } /* Get image range and units */ if (ecat_get_main_value(ecat_fp, ECAT_Calibration_Units, 0, &lvalue, NULL, NULL)) return curframe; if (lvalue == ECAT_CALIB_UNITS_BECQUEREL) { (void) strcpy(general_info->img_units, NCURIE_PER_CC_STRING); } else { (void) strcpy(general_info->img_units, ""); } /* Get patient information */ if (ecat_get_main_value(ecat_fp, ECAT_Patient_Name, 0, NULL, NULL, general_info->patient_name)) return curframe; if (ecat_get_main_value(ecat_fp, ECAT_Patient_Sex, 0, NULL, NULL, general_info->patient_sex)) return curframe; switch (general_info->patient_sex[0]) { case 1: case 'M': (void) strcpy(general_info->patient_sex, MI_MALE); break; case 2: case 'F': (void) strcpy(general_info->patient_sex, MI_FEMALE); break; default: (void) strcpy(general_info->patient_sex, MI_OTHER); break; } if (ecat_get_main_value(ecat_fp, ECAT_Patient_Age, 0, &lvalue, NULL, NULL)) general_info->patient_age = -1; else general_info->patient_age = lvalue; if (!ecat_get_main_value(ecat_fp, ECAT_Patient_Birth_Date, 0, &lvalue, NULL, NULL)) { /* Try to get the right birthday by adding half a day, using UTC and rounding down. This works because field stores birthday at 0:00 converted using the local scanner timezone. */ the_time = (time_t) (lvalue + 12 * SECONDS_PER_HOUR); tm_ptr = gmtime(&the_time); (void) sprintf(general_info->patient_birthdate, "%d-%s-%d", tm_ptr->tm_mday, the_months[tm_ptr->tm_mon+1], tm_ptr->tm_year+1900); } else { general_info->patient_birthdate[0] = '\0'; } /* Get study information */ if (ecat_get_main_value(ecat_fp, ECAT_Study_Type, 0, NULL, NULL, general_info->study_id)) return curframe; if (!ecat_get_main_value(ecat_fp, ECAT_Scan_Start_Time, 0, &lvalue, NULL, NULL)) { the_time = (time_t) lvalue; tm_ptr = localtime(&the_time); general_info->start_day = tm_ptr->tm_mday; general_info->start_month = tm_ptr->tm_mon + 1; general_info->start_year = tm_ptr->tm_year + 1900; general_info->start_hour = tm_ptr->tm_hour; general_info->start_minute = tm_ptr->tm_min; general_info->start_seconds = tm_ptr->tm_sec; } else { if (ecat_get_main_value(ecat_fp, ECAT_Scan_Start_Day, 0, &start_day, NULL, NULL) || ecat_get_main_value(ecat_fp, ECAT_Scan_Start_Month, 0, &start_month, NULL, NULL) || ecat_get_main_value(ecat_fp, ECAT_Scan_Start_Year, 0, &start_year, NULL, NULL) || ecat_get_main_value(ecat_fp, ECAT_Scan_Start_Hour, 0, &start_hour, NULL, NULL) || ecat_get_main_value(ecat_fp, ECAT_Scan_Start_Minute, 0, &start_minute, NULL, NULL) || ecat_get_main_value(ecat_fp, ECAT_Scan_Start_Second, 0, &start_seconds, NULL, NULL)) { return curframe; } start_year += 1900; if (start_year < 1950) start_year += 100; general_info->start_day = start_day; general_info->start_month = start_month; general_info->start_year = start_year; general_info->start_hour = start_hour; general_info->start_minute = start_minute; general_info->start_seconds = start_seconds; } (void) sprintf(general_info->start_time, "%d-%s-%d %d:%d:%d", (int) general_info->start_day, the_months[general_info->start_month], (int) general_info->start_year, (int) general_info->start_hour, (int) general_info->start_minute, (int) general_info->start_seconds); if ((int) strlen(fip->isotope) > 0) { if (ecat_get_main_value(ecat_fp, ECAT_Radiopharmaceutical, 0, NULL, NULL, general_info->tracer)) return curframe; } else { general_info->tracer[0] = '\0'; } if (!ecat_get_main_value(ecat_fp, ECAT_Dose_Start_Time, 0, &lvalue, NULL, NULL) && (lvalue != 0)) { the_time = (time_t) lvalue; (void) strcpy(general_info->injection_time, ctime(&the_time)); tm_ptr = localtime(&the_time); general_info->injection_hour = tm_ptr->tm_hour; general_info->injection_minute = tm_ptr->tm_min; general_info->injection_seconds = tm_ptr->tm_sec; } else { general_info->injection_time[0] = '\0'; } if (!ecat_get_main_value(ecat_fp, ECAT_Dosage, 0, NULL, &general_info->injection_dose, NULL)) { general_info->injection_dose /= BECQUEREL_PER_MCURIE; } else { general_info->injection_dose = -1.0; } /* Get septa state */ septa_state = 0; if (!ecat_get_main_value(ecat_fp, ECAT_Septa_State, 0, &septa_state, NULL, NULL)) { general_info->septa_retracted = (septa_state == 1); } /* Get list of header values */ for (iheader=0; iheader < 2; iheader++) { /* Get space for first field */ field_list = MALLOC(sizeof(*field_list)); /* Loop through fields */ ifield = 0; num_fields = 0; do { /* Get next field */ if (iheader == 0) { field = ecat_list_main(ecat_fp, ifield); description = ecat_get_main_field_description(ecat_fp, field); multiplicity = ecat_get_main_field_length(ecat_fp, field); } else { field = ecat_list_subhdr(ecat_fp, ifield); description = ecat_get_subhdr_field_description(ecat_fp, field); multiplicity = ecat_get_subhdr_field_length(ecat_fp, field); } ifield++; /* Check for end of list */ if ((field == ECAT_No_Field) || (description == NULL) || (multiplicity <= 0)) continue; /* Save the description */ field_list[num_fields].name = strdup(description); /* Get space for the values */ field_list[num_fields].values = NULL; length = 0; /* Loop through multiplicity */ for (imult=0; imult < multiplicity; imult++) { /* Get value */ svalue[0] = '\0'; if (iheader == 0) { (void) ecat_get_main_value(ecat_fp, field, imult, NULL, NULL, svalue); } else { (void) ecat_get_subhdr_value(ecat_fp, curframe, 0, field, imult, NULL, NULL, svalue); } /* Save it */ if (field_list[num_fields].values == NULL) { field_list[num_fields].values = strdup(svalue); length = strlen(svalue); } else { newlength = length + strlen(svalue) + 1; field_list[num_fields].values = REALLOC(field_list[num_fields].values, (size_t) newlength + 1); field_list[num_fields].values[length] = '\n'; (void) strcpy(&field_list[num_fields].values[length+1], svalue); length = newlength; } } /* End of loop over multiplicity */ /* Get space for next field */ field_list = REALLOC(field_list, (num_fields+2) * sizeof(field_list[0])); /* Increment counter */ num_fields++; } while (field != ECAT_No_Field); /* Save the list */ if (iheader == 0) { general_info->main_field_list=field_list; general_info->num_main_fields=num_fields; } else { general_info->subhdr_field_list=field_list; general_info->num_subhdr_fields=num_fields; } } /* Loop over headers */ } /* If first file */ } /* Loop over files */ return -1; } /* ----------------------------- MNI Header ----------------------------------- @NAME : sort_slices @INPUT : sort_over_time - boolean indicating whether sort should be over time or z position. num_frames - number of frames frame_info - array of frame information. general_info - general information about files. @OUTPUT : frame_info - modified to give slice ordering information. @RETURNS : (nothing) @DESCRIPTION: Sorts the slices for the output file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 12, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void sort_slices(int sort_over_time, int num_frames, frame_info_type *frame_info, general_info_type *general_info) { int iframe, islice, isort, num_sort, slice_num; /* Variables for sorting */ sort_type *sort_array; struct { int file; int slice; } *slice_ptr; frame_info_type *file_ptr; /* Allocate array for sorting */ num_sort = (sort_over_time ? num_frames : general_info->num_slices); sort_array = MALLOC (num_sort * sizeof(*sort_array)); /* Are we sorting over time or z position */ if (sort_over_time) { /* Go through the files */ for (iframe=0; iframefile = iframe; slice_ptr->slice = islice; sort_array[isort].sort_value = slice_ptr; isort++; } } } /* Sort the slices */ qsort(sort_array, num_sort, sizeof(*sort_array), sortcmp); /* Loop through sorted list */ for (isort=0; isortordered_frame = isort; } else { slice_ptr = sort_array[isort].sort_value; iframe = slice_ptr->file; islice = slice_ptr->slice; frame_info[iframe].ordered_slices[islice] = isort; FREE(slice_ptr); } } /* Free the sorting array */ FREE(sort_array); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : sortcmp @INPUT : val1 - first value val2 - second value @OUTPUT : (none) @RETURNS : 0 if values are the same, -1 if val1->sort_key < val2->sort_key and +1 if val1->sort_key > val2->sort_key. @DESCRIPTION: Compares two double precision values. If they are the same, then return 0. If val1 < val2, return -1. If val1 > val2, return +1. @METHOD : @GLOBALS : @CALLS : @CREATED : January 12, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int sortcmp(const void *val1, const void *val2) { if (((sort_type *)val1)->sort_key < ((sort_type *)val2)->sort_key) return -1; else if (((sort_type *)val1)->sort_key > ((sort_type *)val2)->sort_key) return 1; else return 0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_minc_file @INPUT : mincid - id of minc file write_byte_data - boolean indicating whether data should be written as bytes (TRUE) or shorts (FALSE). copy_all_header - boolean indicating whether all of the header information should be copied or not. ndims - number of dimensions for minc file count - lengths of dimensions minc file num_frames - number of frames. frame_info - array of information about frames. general_info - general information about file. blood_file - name of blood file containing data to include. @OUTPUT : (nothing) @RETURNS : Image conversion variable id or MI_ERROR if an error occurs. @DESCRIPTION: Initializes the header of the minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 12, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int setup_minc_file(int mincid, int write_byte_data, int copy_all_header, int ndims, long count[], int num_frames, frame_info_type *frame_info, general_info_type *general_info, char *blood_file) { static char *dim_names_array[]={MItime, MIzspace, MIyspace, MIxspace}; char **dim_names; static char *dimwidth_names_array[]={ MItime_width, MIzspace_width, MIyspace_width, MIxspace_width}; char **dimwidth_names; int dim[MAX_DIMS]; int img, imgmax, imgmin, dimvarid, widvarid, icv, varid, ecat_var; int bloodid; int idim, ifield, num_fields, iheader, iframe; double vrange[2]; char varname[MAX_NC_NAME]; ecat_header_data_type *field_list; double dimwidths[MAX_DIMS]; double *frame_times; double *frame_lengths; /* Set up dimension arrays for looping */ dim_names = dim_names_array + MAX_DIMS - ndims; dimwidth_names = dimwidth_names_array + MAX_DIMS - ndims; for (idim=0; idim < ndims; idim++) { switch (idim + MAX_DIMS - ndims) { case 0: dimwidths[idim] = 1.0; break; case 1: dimwidths[idim] = general_info->zwidth; break; case 2: dimwidths[idim] = general_info->ywidth; break; case 3: dimwidths[idim] = general_info->xwidth; break; } } /* Create the dimensions */ for (idim=0; idim1)) ? 1 : 0), &dim[idim]); if (dimwidths[idim] > 0) { widvarid=micreate_std_variable(mincid, dimwidth_names[idim], NC_DOUBLE, ((strcmp(dim_names[idim], MItime)==0) ? 1 : 0), &dim[idim]); } else { widvarid = MI_ERROR; } /* Add attributes to the dimension variables */ if (strcmp(dim_names[idim], MIzspace)==0) { /* Write out step and start. We will rewrite this for irregularly spaced files */ (void) miattputdbl(mincid, dimvarid, MIstep, frame_info[0].zstep); (void) miattputdbl(mincid, dimvarid, MIstart, frame_info[0].zstart); (void) miattputstr(mincid, dimvarid, MIunits, "mm"); (void) miattputstr(mincid, dimvarid, MIspacetype, MI_NATIVE); if (widvarid != MI_ERROR) { (void) miattputdbl(mincid, widvarid, MIwidth, (double) general_info->zwidth); (void) miattputstr(mincid, widvarid, MIunits, "mm"); (void) miattputstr(mincid, widvarid, MIfiltertype, MI_GAUSSIAN); } } else if (strcmp(dim_names[idim], MIyspace)==0) { (void) miattputstr(mincid, dimvarid, MIunits, "mm"); (void) miattputdbl(mincid, dimvarid, MIstart, (double) general_info->ystart); (void) miattputdbl(mincid, dimvarid, MIstep, (double) general_info->ystep); (void) miattputstr(mincid, dimvarid, MIspacetype, MI_NATIVE); if (widvarid != MI_ERROR) { (void) miattputdbl(mincid, widvarid, MIwidth, (double) general_info->ywidth); (void) miattputstr(mincid, widvarid, MIfiltertype, MI_GAUSSIAN); } } else if (strcmp(dim_names[idim], MIxspace)==0) { (void) miattputstr(mincid, dimvarid, MIunits, "mm"); (void) miattputdbl(mincid, dimvarid, MIstart, (double) general_info->xstart); (void) miattputdbl(mincid, dimvarid, MIstep, (double) general_info->xstep); (void) miattputstr(mincid, dimvarid, MIspacetype, MI_NATIVE); if (widvarid != MI_ERROR) { (void) miattputdbl(mincid, widvarid, MIwidth, (double) general_info->xwidth); (void) miattputstr(mincid, widvarid, MIfiltertype, MI_GAUSSIAN); } } else if (strcmp(dim_names[idim], MItime)==0) { (void) miattputstr(mincid, dimvarid, MIunits, "seconds"); (void) miattputstr(mincid, widvarid, MIunits, "seconds"); } } /* Create the image variable */ if (write_byte_data) { img=micreate_std_variable(mincid, MIimage, NC_BYTE, ndims, dim); (void) miattputstr(mincid, img, MIsigntype, MI_UNSIGNED); vrange[0]=0; vrange[1]=255; } else { img=micreate_std_variable(mincid, MIimage, NC_SHORT, ndims, dim); (void) miattputstr(mincid, img, MIsigntype, MI_SIGNED); vrange[0] = -32000; vrange[1] = 32000; } (void) ncattput(mincid, img, MIvalid_range, NC_DOUBLE, 2, vrange); (void) miattputstr(mincid, img, MIcomplete, MI_FALSE); /* Create the image max and min variables */ imgmax=micreate_std_variable(mincid, MIimagemax, NC_DOUBLE, ndims-2, dim); imgmin=micreate_std_variable(mincid, MIimagemin, NC_DOUBLE, ndims-2, dim); (void) miattputstr(mincid, imgmax, MIunits, general_info->img_units); (void) miattputstr(mincid, imgmin, MIunits, general_info->img_units); /* Create the image conversion variable */ icv=miicv_create(); (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT); /* Save patient info */ varid = micreate_group_variable(mincid, MIpatient); (void) miattputstr(mincid, varid, MIfull_name, general_info->patient_name); (void) miattputstr(mincid, varid, MIsex, general_info->patient_sex); if (general_info->patient_age > 0) (void) ncattput(mincid, varid, MIage, NC_LONG, 1, &general_info->patient_age); if ((int) strlen(general_info->patient_birthdate) > 0) (void) miattputstr(mincid, varid, MIbirthdate, general_info->patient_birthdate); /* Save study info */ varid = micreate_group_variable(mincid, MIstudy); (void) miattputstr(mincid, varid, MImodality, MI_PET); (void) miattputstr(mincid, varid, MImanufacturer, "CTI"); (void) miattputstr(mincid, varid, MIstudy_id, general_info->study_id); (void) miattputstr(mincid, varid, MIstart_time, general_info->start_time); (void) ncattput(mincid, varid, MIstart_year, NC_LONG, 1, &general_info->start_year); (void) ncattput(mincid, varid, MIstart_month, NC_LONG, 1, &general_info->start_month); (void) ncattput(mincid, varid, MIstart_day, NC_LONG, 1, &general_info->start_day); (void) ncattput(mincid, varid, MIstart_hour, NC_LONG, 1, &general_info->start_hour); (void) ncattput(mincid, varid, MIstart_minute, NC_LONG, 1, &general_info->start_minute); (void) ncattput(mincid, varid, MIstart_seconds, NC_DOUBLE, 1, &general_info->start_seconds); /* Save acquisition info */ varid = micreate_group_variable(mincid, MIacquisition); if ((int) strlen(frame_info[0].isotope) > 0) { (void) miattputstr(mincid, varid, MIradionuclide, frame_info[0].isotope); } if (frame_info[0].half_life > 0.0) { (void) miattputdbl(mincid, varid, MIradionuclide_halflife, (double) frame_info[0].half_life); } if ((int) strlen(general_info->tracer) > 0) { (void) miattputstr(mincid, varid, MItracer, general_info->tracer); } if ((int) strlen(general_info->injection_time) > 0) { (void) miattputstr(mincid, varid, MIinjection_time, general_info->injection_time); (void) ncattput(mincid, varid, MIinjection_hour, NC_LONG, 1, &general_info->injection_hour); (void) ncattput(mincid, varid, MIinjection_minute, NC_LONG, 1, &general_info->injection_minute); (void) ncattput(mincid, varid, MIinjection_seconds, NC_DOUBLE, 1, &general_info->injection_seconds); } if (general_info->injection_dose > 0.0) { (void) ncattput(mincid, varid, MIinjection_dose, NC_DOUBLE, 1, &general_info->injection_dose); (void) miattputstr(mincid, varid, MIdose_units, "mCurie"); } /* Save the septa state in a special ECAT variable, along with frame starts and lengths if we are not creating a time dimension. */ varid = ncvardef(mincid, "ecat_acquisition", NC_LONG, 0, NULL); (void) miattputstr(mincid, varid, MIvartype, MI_GROUP); (void) miattputstr(mincid, varid, MIvarid, "ECAT-specific acquisition information"); (void) miadd_child(mincid, ncvarid(mincid, MIrootvariable), varid); (void) miattputstr(mincid, varid, "septa_retracted", (general_info->septa_retracted ? MI_TRUE : MI_FALSE)); if (ndims < MAX_DIMS) { frame_times = MALLOC(sizeof(*frame_times) * num_frames); frame_lengths = MALLOC(sizeof(*frame_lengths) * num_frames); for (iframe=0; iframe < num_frames; iframe++) { frame_times[iframe] = frame_info[iframe].scan_time; frame_lengths[iframe] = frame_info[iframe].time_width; } (void) ncattput(mincid, varid, "frame_times", NC_DOUBLE, num_frames, frame_times); (void) ncattput(mincid, varid, "frame_lengths", NC_DOUBLE, num_frames, frame_lengths); } /* If we want all of the values from the header, get them */ if (copy_all_header) { for (iheader=0; iheader < 2; iheader++) { /* Set up values for either header */ if (iheader == 0) { (void) strcpy(varname, "ecat-main"); field_list = general_info->main_field_list; num_fields = general_info->num_main_fields; } else { (void) strcpy(varname, "ecat-subhdr"); field_list = general_info->subhdr_field_list; num_fields = general_info->num_subhdr_fields; } /* Create a variable for ECAT fields */ ecat_var = ncvardef(mincid, varname, NC_LONG, 0, NULL); (void) miattputstr(mincid, ecat_var, MIvartype, MI_GROUP); (void) miattputstr(mincid, ecat_var, MIvarid, "MNI ECAT variable"); (void) miadd_child(mincid, ncvarid(mincid, MIrootvariable), ecat_var); /* Loop through fields */ for (ifield=0; ifield < num_fields; ifield++){ (void) miattputstr(mincid, ecat_var, field_list[ifield].name, field_list[ifield].values); } } /* Loop over headers */ } /* If copy_all_header */ /* Open the blood file and create the variables if needed */ if (blood_file != NULL) { bloodid = ncopen(blood_file, NC_NOWRITE); CreateBloodStructures(mincid, bloodid); } /* Attach the icv */ (void) ncsetfill(mincid, NC_NOFILL); (void) ncendef(mincid); (void) miicv_attach(icv, mincid, img); /* Copy the blood data */ if (blood_file != NULL) { FillBloodStructures(mincid, bloodid); ncclose(bloodid); } return icv; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_slice @INPUT : ecat_fp - file pointer for file frame_num - number of frame slice_num - slice to copy frame_info - information on frame general_info - general file information @OUTPUT : pixel_max - maximum pixel value image_max - real value to which pixel_max corresponds image - the image @RETURNS : Returns TRUE if an error occurs. @DESCRIPTION: Gets an image from the file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int get_slice(Ecat_file *ecat_fp, int frame_num, int slice_num, long *pixel_max, double *image_max, short *image, frame_info_type *frame_info, general_info_type *general_info) /* ARGSUSED */ { long npix, in, off; int pmax; int lvalue; short temp; double scale, global_scale; /* Get the image from the file */ if (ecat_get_image(ecat_fp, frame_num, slice_num, image)) return TRUE; /* Flip the image to give positive x & y axes */ npix = frame_info->image_xsize * frame_info->image_ysize; for(in = 0; in < npix/2; in++) { off = npix - in - 1; temp = image[off]; image[off] = image[in]; image[in] = temp; } /* Get image and pixel max */ if (ecat_get_subhdr_value(ecat_fp, frame_num, slice_num, ECAT_Image_Max, 0, &pmax, NULL, NULL) || ecat_get_subhdr_value(ecat_fp, frame_num, slice_num, ECAT_Scale_Factor, 0, NULL, &scale, NULL)) return TRUE; if (!ecat_get_main_value(ecat_fp, ECAT_Calibration_Factor, 0, NULL, &global_scale, NULL) && (global_scale > 0.0)) { if (!ecat_get_main_value(ecat_fp, ECAT_Calibration_Units, 0, &lvalue, NULL, NULL) && (lvalue == ECAT_CALIB_UNITS_BECQUEREL)) { global_scale /= BECQUEREL_PER_NCURIE; } } else if (ecat_get_subhdr_value(ecat_fp, frame_num, slice_num, ECAT_Calibration_Factor, 0, NULL, &global_scale, NULL)) { global_scale = 1.0; } *pixel_max = pmax; *image_max = (double) pmax * scale * global_scale; return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_minc_slice @INPUT : scale - scale for decay correcting image write_byte_data - boolean indicating whether data should be written as bytes (TRUE) or shorts (FALSE). mincid - id of minc file icvid - id of image conversion variable start - coordinate of slice in minc file count - edge lengths of image to write in minc file image - pointer to image buffer image_xsize, image_ysize - dimensions of image pixel_max - maximum pixel value image_max - real value to which pixel_max corresponds scan_time - time of slice time_width - time width of slice zpos - z position of slice frame_info - information on frame general_info - general file information @OUTPUT : (nothing) @RETURNS : Returns TRUE if an error occurs. @DESCRIPTION: Writes out the image to the minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 12, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int write_minc_slice(double scale, int write_byte_data, int mincid, int icvid, int ndims, long start[], long count[], short *image, int image_xsize, int image_ysize, long pixel_max, double image_max, double scan_time, double time_width, double zpos) /*ARGSUSED*/ { double pixmin, pixmax; long ipix, npix; double maximum, minimum; /* Search for pixel max and min */ npix = image_xsize * image_ysize; pixmin = pixmax = image[0]; for (ipix=1; ipixpixmax) pixmax = image[ipix]; if (image[ipix] #include #include #define MIbloodroot "blood_analysis" /* ----------------------------- MNI Header ----------------------------------- @NAME : CreateBloodStructures @INPUT : mincHandle -> a handle for an open MINC file. This file should be open for writing, but not in redefinition mode. bloodHandle -> a handle for an open BNC file. This file should be open for reading. @OUTPUT : none @RETURNS : void @DESCRIPTION: Copies all variable definitions (with attributes) from the BNC file to the MINC file. The appropriate dimensions are also copied. @METHOD : none. Just muddled through. @GLOBALS : none @CALLS : micopy_all_var_defs (MINC library) miadd_child (MINC library) @CREATED : May 30, 1994 by MW @MODIFIED : ---------------------------------------------------------------------------- */ void CreateBloodStructures (int mincHandle, int bloodHandle) { int mincRoot; int bloodRoot; /* * Copy all the variables with their attributes. */ (void) micopy_all_var_defs (bloodHandle, mincHandle, 0, NULL); /* * Make the blood analysis root variable a child of * the MINC root variable. */ mincRoot = ncvarid (mincHandle, MIrootvariable); bloodRoot = ncvarid (mincHandle, MIbloodroot); (void) miadd_child (mincHandle, mincRoot, bloodRoot); } /* ----------------------------- MNI Header ----------------------------------- @NAME : FillBloodStructures @INPUT : mincHandle -> a handle for an open MINC file. This file should be open for writing, but not in redefinition mode. bloodHandle -> a handle for an open BNC file. This file should be open for reading. @OUTPUT : none @RETURNS : void @DESCRIPTION: Copies all variable values from the BNC file to the MINC file. The variable themselves should already exist in the MINC file (see CreateBloodStructures). @METHOD : none. Just muddled through. @GLOBALS : none @CALLS : micopy_all_var_values (MINC library) @CREATED : May 30, 1994 by MW @MODIFIED : ---------------------------------------------------------------------------- */ void FillBloodStructures (int mincHandle, int bloodHandle) { (void) micopy_all_var_values (bloodHandle, mincHandle, 0, NULL); } minc-2.2.00/conversion/ecattominc/ecat_file.c0000644000265600003100000012037212027132661016036 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_file.c @DESCRIPTION: File containing routines to read ECAT image files @GLOBALS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : * $Log: ecat_file.c,v $ * Revision 6.5 2011-01-21 01:06:58 nikelski * * Fixed seg fault in ecattominc on 64-bit systems * * Corrected by modifying ecat_file.c and machine_indep.c as follows: * - added include providing access to the int32_t type * - changed the "dirblock" buffer from long to int32_t, making explicit * that this buffer needs to hold 32-bit ints (reflecting the ecat file) * - added function get_int32_value to return 32-bit ints from the * dirblock buffer * * Revision 6.4 2008/01/17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.3 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.2 2005/01/19 19:46:00 bert * Changes from Anthonin Reilhac * * Revision 6.1 1999/10/29 17:52:01 neelin * Fixed Log keyword * * Revision 6.0 1997/09/12 13:24:22 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:21 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:06:04 neelin * Release of minc version 0.4 * * Revision 1.1 1996/01/18 14:52:14 neelin * Initial revision * @COPYRIGHT : Copyright 1996 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include "ecat_file.h" #include "machine_indep.h" /*#include */ /* Set some standard macros */ #ifndef SEEK_SET # define SEEK_SET 0 #endif #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Constants */ #define BLOCK_SIZE 512 #define MAIN_HEADER_SIZE BLOCK_SIZE #define SUBHEADER_SIZE BLOCK_SIZE #define DIRBLOCK_SIZE BLOCK_SIZE #define MAGIC_STRING "MATRIX" #define FIRST_DIRBLOCK 2 #define DRBLK_NEXT 1 #define DRBLK_NUMUSED 3 #define DRBLK_SKIP 4 #define DRBLK_WIDTH 4 #define DRBLK_PTR 1 /* Header definition types */ typedef enum { ecat_byte, ecat_short, ecat_long, ecat_float, ecat_char } Ecat_type; typedef struct { Ecat_field_name name; int offset; int length; Ecat_type type; char *description; } Ecat_field_description_type; typedef struct { int initialized; int num_entries; Ecat_field_description_type *fields; Ecat_field_name *file_order; } Ecat_header_table_type; typedef struct { Ecat_header_table_type *main_header; Ecat_header_table_type *subheader; } Ecat_header_description_type; /* Header definition */ #include "ecat_header_definition.h" /* ECAT file Type */ struct Ecat_file { FILE *file_pointer; Ecat_header_description_type *header_description; int vax_byte_order; int num_planes; int num_frames; int num_bed_positions; int num_gates; int num_volumes; unsigned char *main_header; long cur_subhdr_offset; unsigned char *subheader; int num_subhdrs; long *subhdr_offsets; }; typedef enum { ECAT_MAIN_HEADER, ECAT_SUBHEADER } Ecat_which_header; /* Private functions */ private Ecat_field_name ecat_list_fields(Ecat_file *file, Ecat_which_header which_header, int index); private int ecat_get_field_length(Ecat_file *file, Ecat_which_header which_header, Ecat_field_name field); private char *ecat_get_field_description(Ecat_file *file, Ecat_which_header which_header, Ecat_field_name field); private int ecat_get_value(Ecat_file *file, Ecat_which_header which_header, int volume_number, int slice_number, Ecat_field_name field, int index, int *ivalue, double *fvalue, char *svalue); private int ecat_read_subhdr(Ecat_file *file, int volume, int slice); private int ecat_lookup_field(Ecat_header_table_type *table, Ecat_field_name field, int *offset, int *length, Ecat_type *type, char **description); private void ecat_initialize_table(Ecat_header_table_type *table); private int ecat_table_entry_compare(const void *v1, const void *v2); private int ecat_table_offset_compare(const void *v1, const void *v2); private int ecat_read_directory(Ecat_file *file); private long get_dirblock(Ecat_file *file, int32_t *dirblock, int offset); private int ecat_get_subhdr_offset(Ecat_file *file, int volume, int slice, long *offset); /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_open @INPUT : filename - name of file to open @OUTPUT : (none) @RETURNS : Pointer to ECAT file descriptor or NULL if an error occurs. @DESCRIPTION: Routine to open an ECAT file (for reading only), given its pathname. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Ecat_file *ecat_open(char *filename) { Ecat_file *file; /* Allocate space for an ecat file structure */ file = (void *) MALLOC(sizeof(*file)); file->main_header = (void *) MALLOC(MAIN_HEADER_SIZE); file->subheader = (void *) MALLOC(SUBHEADER_SIZE); file->cur_subhdr_offset = -1; file->subhdr_offsets = NULL; /* Open the file */ if ((file->file_pointer=fopen(filename, "rb")) == NULL) { ecat_close(file); return NULL; } /* Read in the main header */ if (fread(file->main_header, sizeof(char), (size_t) MAIN_HEADER_SIZE, file->file_pointer) != MAIN_HEADER_SIZE) { ecat_close(file); return NULL; } /* Figure out which type of file we are using */ if (strncmp((char *)file->main_header, MAGIC_STRING, strlen(MAGIC_STRING)) == 0) { file->header_description = ECAT_VER_7; file->vax_byte_order = FALSE; } else { file->header_description = ECAT_VER_PRE7; file->vax_byte_order = TRUE; } /* Get the number of frames, slices, bed positions and gates */ if (ecat_get_main_value(file, ECAT_Num_Planes, 0, &file->num_planes, NULL, NULL) || ecat_get_main_value(file, ECAT_Num_Frames, 0, &file->num_frames, NULL, NULL) || ecat_get_main_value(file, ECAT_Num_Bed_Pos, 0, &file->num_bed_positions, NULL, NULL) || ecat_get_main_value(file, ECAT_Num_Gates, 0, &file->num_gates, NULL, NULL)) { ecat_close(file); return NULL; } file->num_volumes = file->num_frames; if (file->num_volumes < file->num_bed_positions) file->num_volumes = file->num_bed_positions; if (file->num_volumes < file->num_gates) file->num_volumes = file->num_gates; /* Read the directory structure */ if (ecat_read_directory(file)) { ecat_close(file); return NULL; } /* Return the file pointer */ return file; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_close @INPUT : file - ecat file pointer @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to close an ECAT file and free the associated structures @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void ecat_close(Ecat_file *file) { if (file==NULL) return; if (file->file_pointer != NULL) { (void) fclose(file->file_pointer); } if (file->subhdr_offsets != NULL) { FREE(file->subhdr_offsets); } if (file->main_header != NULL) FREE(file->main_header); if (file->subheader != NULL) FREE(file->subheader); FREE(file); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_num_{planes,frames,bed_positions,gates} @INPUT : file - ecat file pointer @OUTPUT : (none) @RETURNS : Number of * for an ECAT file. @DESCRIPTION: Routine to get the number of planes (slices), frames, bed_positions or gates in an ECAT file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int ecat_get_num_planes(Ecat_file *file) { return file->num_planes; } public int ecat_get_num_frames(Ecat_file *file) { return file->num_frames; } public int ecat_get_num_bed_positions(Ecat_file *file) { return file->num_bed_positions; } public int ecat_get_num_gates(Ecat_file *file) { return file->num_gates; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_list_main @INPUT : file - ecat file pointer index - index into field list @OUTPUT : (none) @RETURNS : Next Ecat_field_name value, ECAT_No_Field if index is too large. @DESCRIPTION: Routine to list the fields in an ECAT main header. Should be called repeatedly with increasing values of index (starting from 0) until field ECAT_No_Field is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Ecat_field_name ecat_list_main(Ecat_file *file, int index) { return ecat_list_fields(file, ECAT_MAIN_HEADER, index); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_list_subhdr @INPUT : file - ecat file pointer index - index into field list @OUTPUT : (none) @RETURNS : Next Ecat_field_name value, ECAT_No_Field if index is too large. @DESCRIPTION: Routine to list the fields in an ECAT subheader. Should be called repeatedly with increasing values of index (starting from 0) until field ECAT_No_Field is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public Ecat_field_name ecat_list_subhdr(Ecat_file *file, int index) { return ecat_list_fields(file, ECAT_SUBHEADER, index); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_list_fields @INPUT : file - ecat file pointer which_header - header in which to look index - index into field list @OUTPUT : (none) @RETURNS : Next Ecat_field_name value, ECAT_No_Field if index is too large. @DESCRIPTION: Routine to list the fields in an ECAT subheader. Should be called repeatedly with increasing values of index (starting from 0) until field ECAT_No_Field is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private Ecat_field_name ecat_list_fields(Ecat_file *file, Ecat_which_header which_header, int index) { Ecat_header_table_type *table; /* Get the appropriate header */ switch (which_header) { case ECAT_MAIN_HEADER: table = file->header_description->main_header; break; case ECAT_SUBHEADER: table = file->header_description->subheader; break; default: return ECAT_No_Field; } /* Initialize the table, if needed */ if (!table->initialized) { ecat_initialize_table(table); } /* Check the index */ if ((index < 0) || (index >= table->num_entries)) { return ECAT_No_Field; } /* Return the fields in file order */ return table->file_order[index]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_main_field_length @INPUT : file - ecat file pointer field - ecat field name @OUTPUT : (none) @RETURNS : Length of field. Returns -1 if the field is not found. @DESCRIPTION: Routine to get the length of a field from the ECAT main header. Length is the number of elements, not the number of bytes. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int ecat_get_main_field_length(Ecat_file *file, Ecat_field_name field) { return ecat_get_field_length(file, ECAT_MAIN_HEADER, field); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_subhdr_field_length @INPUT : file - ecat file pointer field - ecat field name @OUTPUT : (none) @RETURNS : Length of field. Returns -1 if the field is not found. @DESCRIPTION: Routine to get the length of a field from an ECAT subheader. Length is the number of elements, not the number of bytes. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int ecat_get_subhdr_field_length(Ecat_file *file, Ecat_field_name field) { return ecat_get_field_length(file, ECAT_SUBHEADER, field); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_field_length @INPUT : file - ecat file pointer which_header - header in which to look field - ecat field name @OUTPUT : (none) @RETURNS : Length of field. Returns -1 if the field is not found. @DESCRIPTION: Routine to get the length of a field from an ECAT header. Length is the number of elements, not the number of bytes. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int ecat_get_field_length(Ecat_file *file, Ecat_which_header which_header, Ecat_field_name field) { Ecat_header_table_type *table; Ecat_type type; int length; /* Get the appropriate header */ switch (which_header) { case ECAT_MAIN_HEADER: table = file->header_description->main_header; break; case ECAT_SUBHEADER: table = file->header_description->subheader; break; default: return -1; } /* Look for the field description */ if (ecat_lookup_field(table, field, NULL, &length, &type, NULL)) { return -1; } /* Return the length. If we have a string, then return 1. */ if (type == ecat_char) return 1; else return length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_main_field_description @INPUT : file - ecat file pointer field - ecat field name @OUTPUT : (none) @RETURNS : Description of field. Returns NULL if the field is not found. @DESCRIPTION: Routine to get the description of a field from the ECAT main header. The string returned should not be modified. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public char *ecat_get_main_field_description(Ecat_file *file, Ecat_field_name field) { return ecat_get_field_description(file, ECAT_MAIN_HEADER, field); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_subhdr_field_description @INPUT : file - ecat file pointer field - ecat field name @OUTPUT : (none) @RETURNS : Description of field. Returns NULL if the field is not found. @DESCRIPTION: Routine to get the description of a field from an ECAT subheader. The string returned should not be modified. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public char *ecat_get_subhdr_field_description(Ecat_file *file, Ecat_field_name field) { return ecat_get_field_description(file, ECAT_SUBHEADER, field); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_field_description @INPUT : file - ecat file pointer which_header - header in which to look field - ecat field name @OUTPUT : (none) @RETURNS : Description of field. Returns NULL if the field is not found. @DESCRIPTION: Routine to get the descrition of a field from an ECAT header. The string returned should not be modified. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private char *ecat_get_field_description(Ecat_file *file, Ecat_which_header which_header, Ecat_field_name field) { Ecat_header_table_type *table; char *description; /* Get the appropriate header */ switch (which_header) { case ECAT_MAIN_HEADER: table = file->header_description->main_header; break; case ECAT_SUBHEADER: table = file->header_description->subheader; break; default: return NULL; } /* Look for the field description */ if (ecat_lookup_field(table, field, NULL, NULL, NULL, &description)) { return NULL; } /* Return the description */ return description; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_main_value @INPUT : file - ecat file pointer field - ecat field name index - index for multi-valued fields (counting from zero) @OUTPUT : ivalue - integer value fvalue - floating-point value svalue - string value @RETURNS : FALSE if successful, TRUE otherwise @DESCRIPTION: Routine to get a field value from the ECAT main header. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int ecat_get_main_value(Ecat_file *file, Ecat_field_name field, int index, int *ivalue, double *fvalue, char *svalue) { return ecat_get_value(file, ECAT_MAIN_HEADER, 0, 0, field, index, ivalue, fvalue, svalue); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_subhdr_value @INPUT : file - ecat file pointer volume - frame or bed position for subheader (from 0) slice - slice number (counting from 0) field - ecat field name index - index for multi-valued fields (counting from zero) @OUTPUT : ivalue - integer value fvalue - floating-point value svalue - string value @RETURNS : FALSE if successful, TRUE otherwise @DESCRIPTION: Routine to get a field value from the ECAT main header. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int ecat_get_subhdr_value(Ecat_file *file, int volume, int slice, Ecat_field_name field, int index, int *ivalue, double *fvalue, char *svalue) { return ecat_get_value(file, ECAT_SUBHEADER, volume, slice, field, index, ivalue, fvalue, svalue); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_value @INPUT : file - ECAT file pointer which_header - header in which to look volume_number - frame or bed position for subheader (counting from 0) slice_number - number of slice for subheader (counting from 0) field - field to look for index - index for multi-valued fields (counting from zero) @OUTPUT : ivalue - integer value fvalue - floating-point value svalue - string value @RETURNS : FALSE if successful, TRUE otherwise @DESCRIPTION: Routine to look up a field value in a header table. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int ecat_get_value(Ecat_file *file, Ecat_which_header which_header, int volume_number, int slice_number, Ecat_field_name field, int index, int *ivalue, double *fvalue, char *svalue) { /* Sizes of ECAT types */ static int ecat_type_sizes[] = {1, 2, 4, 4, 1}; /* Variables */ unsigned char *header; Ecat_header_table_type *table; int offset, length; Ecat_type type; unsigned char byte_value; short short_value; long long_value; float float_value; char string[ECAT_MAX_STRING_LENGTH]; /* Get the appropriate header */ switch (which_header) { case ECAT_MAIN_HEADER: header = file->main_header; table = file->header_description->main_header; break; case ECAT_SUBHEADER: if (ecat_read_subhdr(file, volume_number, slice_number)) { return TRUE; } header = file->subheader; table = file->header_description->subheader; break; default: return TRUE; } /* Look for the field description */ if (ecat_lookup_field(table, field, &offset, &length, &type, NULL)) { return TRUE; } /* Check the index */ if ((index < 0) || (index >= length) || ((type == ecat_char) && (index > 0))) { return TRUE; } offset += index * ecat_type_sizes[type]; /* Get the value and convert it */ switch (type) { case ecat_byte: byte_value = header[offset]; if (ivalue != NULL) *ivalue = byte_value; if (fvalue != NULL) *fvalue = byte_value; if (svalue != NULL) (void) sprintf(svalue, "%d", (int) byte_value); break; case ecat_short: if (file->vax_byte_order) { get_vax_short(1, &header[offset], &short_value); } else { get_short_value(& header[offset], &short_value); } if (ivalue != NULL) *ivalue = short_value; if (fvalue != NULL) *fvalue = short_value; if (svalue != NULL) (void) sprintf(svalue, "%d", (int) short_value); break; case ecat_long: if (file->vax_byte_order) { get_vax_long(1, &header[offset], &long_value); } else { get_long_value(& header[offset], &long_value); } if (ivalue != NULL) *ivalue = long_value; if (fvalue != NULL) *fvalue = long_value; if (svalue != NULL) (void) sprintf(svalue, "%d", (int) long_value); break; case ecat_float: offset += index * sizeof(float); if (file->vax_byte_order) { get_vax_float(1, &header[offset], &float_value); } else { get_long_value(& header[offset], &float_value); } if (ivalue != NULL) *ivalue = float_value; if (fvalue != NULL) *fvalue = float_value; if (svalue != NULL) (void) sprintf(svalue, "%.7g", (double) float_value); break; case ecat_char: (void) memcpy(string, &header[offset], length); string[length] = '\0'; if (ivalue != NULL) *ivalue = atoi(svalue); if (fvalue != NULL) *fvalue = atof(svalue); if (svalue != NULL) (void) strcpy(svalue, string); break; default: return TRUE; } return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_read_subhdr @INPUT : file - ecat file pointer volume - frame or bed position for subheader (from 0) slice - slice number (counting from 0) @OUTPUT : file - file structure is modified to include new subheader @RETURNS : FALSE if successful, TRUE otherwise @DESCRIPTION: Routine to read in the appropriate subheader, if needed. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int ecat_read_subhdr(Ecat_file *file, int volume, int slice) { long offset; /* Get subheader offset */ if (ecat_get_subhdr_offset(file, volume, slice, &offset)) { return TRUE; } /* Do we need to read in the header? */ if (offset == file->cur_subhdr_offset) { return FALSE; } /* If so, do it */ if (fseek(file->file_pointer, offset, SEEK_SET) || (fread(file->subheader, sizeof(char), (size_t) SUBHEADER_SIZE, file->file_pointer) != SUBHEADER_SIZE)) { return TRUE; } file->cur_subhdr_offset = offset; return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_lookup_field @INPUT : table - table containing header fields field - field to look for @OUTPUT : offset - offset into header length - length of field (number of values, not bytes) type - type of values description - string describing field (ptr is passed back by reference) @RETURNS : FALSE if successful, TRUE otherwise @DESCRIPTION: Routine to look up a field value in a header table. All output arguments can be NULL to indicate that the corresponding value should not be returned. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int ecat_lookup_field(Ecat_header_table_type *table, Ecat_field_name field, int *offset, int *length, Ecat_type *type, char **description) { Ecat_field_description_type field_description, *result; /* Initialize the table, if needed */ if (!table->initialized) { ecat_initialize_table(table); } /* Set up a dummy entry */ field_description.name = field; /* Search for the field */ result = bsearch(&field_description, table->fields, table->num_entries, sizeof(table->fields[0]), ecat_table_entry_compare); if (result == NULL) { return TRUE; } /* Store the results */ if (offset != NULL) *offset = result->offset; if (length != NULL) *length = result->length; if (type != NULL) *type = result->type; if (description != NULL) *description = result->description; return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_initialize_table @INPUT : table - table containing header fields @OUTPUT : table - modified appropriately @RETURNS : (nothing) @DESCRIPTION: Routine to initialize the header table. @METHOD : Initialized should be set to TRUE, num_entries should already be set and fields should point to a list. The fields list will be sorted and the file_order field will be set. @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private void ecat_initialize_table(Ecat_header_table_type *table) { Ecat_field_description_type *file_order_list; int iel; /* Check that table is not already initialized */ if (table->initialized) return; /* Sort the field list by field name for binary searching */ qsort(table->fields, table->num_entries, sizeof(table->fields[0]), ecat_table_entry_compare); /* Get a list of field names in file order by copying the field list and sorting it by offset */ file_order_list = MALLOC(table->num_entries * sizeof(*file_order_list)); for (iel=0; iel < table->num_entries; iel++) { file_order_list[iel] = table->fields[iel]; } qsort(file_order_list, table->num_entries, sizeof(file_order_list[0]), ecat_table_offset_compare); table->file_order = MALLOC(table->num_entries * sizeof(table->file_order[0])); for (iel=0; iel < table->num_entries; iel++) { table->file_order[iel] = file_order_list[iel].name; } FREE(file_order_list); /* Mark the table as initialized */ table->initialized = TRUE; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_table_entry_compare @INPUT : v1 - first value @OUTPUT : v2 - second value @RETURNS : (nothing) @DESCRIPTION: Routine to compare field list elements for sorting by name. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int ecat_table_entry_compare(const void *v1, const void *v2) { Ecat_field_description_type *first, *second; /* Get pointers */ first = (Ecat_field_description_type *) v1; second = (Ecat_field_description_type *) v2; /* Compare field names */ return ((int) first->name - (int) second->name); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_table_offset_compare @INPUT : v1 - first value @OUTPUT : v2 - second value @RETURNS : (nothing) @DESCRIPTION: Routine to compare field list elements for sorting by offset. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int ecat_table_offset_compare(const void *v1, const void *v2) { Ecat_field_description_type *first, *second; /* Get pointers */ first = (Ecat_field_description_type *) v1; second = (Ecat_field_description_type *) v2; /* Compare field names */ return ((int) first->offset - (int) second->offset); } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_read_directory @INPUT : file - ecat file pointer @OUTPUT : (nothing) @RETURNS : FALSE if successful, TRUE otherwise @DESCRIPTION: Routine to read in the ECAT subheader directory @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private int ecat_read_directory(Ecat_file *file) { int ientry, start_entry, num_alloc; long nextblock, num_used; int32_t dirblock[DIRBLOCK_SIZE / sizeof(int32_t)]; /* Allocate space for the subheader offset array */ num_alloc = file->num_volumes; if (file->header_description == ECAT_VER_PRE7) num_alloc *= file->num_planes; file->num_subhdrs = 0; file->subhdr_offsets = MALLOC(num_alloc * sizeof(file->subhdr_offsets[0])); /* Reading directory blocks until done */ nextblock = FIRST_DIRBLOCK; do { /* Read in the block */ if (fseek(file->file_pointer, (nextblock - 1) * BLOCK_SIZE, SEEK_SET) || (fread(dirblock, sizeof(char), sizeof(dirblock), file->file_pointer) != sizeof(dirblock))) { return TRUE; } /* Get a pointer to the next block and the number of entries used */ nextblock = get_dirblock(file, dirblock, DRBLK_NEXT); num_used = get_dirblock(file, dirblock, DRBLK_NUMUSED); /* Increment the number of subheaders */ start_entry = file->num_subhdrs; file->num_subhdrs += num_used; if (num_alloc < file->num_subhdrs) { num_alloc = file->num_subhdrs; REALLOC(file->subhdr_offsets, num_alloc * sizeof(file->subhdr_offsets[0])); } /* Save the offsets */ for (ientry=0; ientry < num_used; ientry++) { file->subhdr_offsets[start_entry + ientry] = BLOCK_SIZE * (get_dirblock(file, dirblock, DRBLK_SKIP + ientry * DRBLK_WIDTH + DRBLK_PTR) - 1); } } while (nextblock > FIRST_DIRBLOCK); return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dirblock @INPUT : file - ecat file pointer dirblock - directory block offset - offset (in longwords) into the block @OUTPUT : (nothing) @RETURNS : directory block value @DESCRIPTION: Routine to get a value from an ECAT directory block. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private long get_dirblock(Ecat_file *file, int32_t *dirblock, int offset){ long value; if (file->header_description == ECAT_VER_PRE7) { /*get_vax_long(1, &dirblock[offset], &value);*/ } else if (file->header_description == ECAT_VER_7) { /* value = dirblock[offset];*/ get_int32_value(&dirblock[offset], &value); } else { return 0; } return value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : ecat_get_image @INPUT : file - ecat file pointer volume - frame or bed position (from 0) slice - slice number (counting from 0) @OUTPUT : image @RETURNS : FALSE if successful, TRUE otherwise @DESCRIPTION: Routine to get an image from an ECAT file @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int ecat_get_image(Ecat_file *file, int volume, int slice, short *image) { long file_offset; int xsize, ysize, zsize, data_type, bytes_per_pixel; long image_npix, image_size, array_offset, ipix; unsigned char *bimage; /* Get the image size and type */ if (ecat_get_subhdr_value(file, volume, slice, ECAT_X_Dimension, 0, &xsize, NULL, NULL) || ecat_get_subhdr_value(file, volume, slice, ECAT_Y_Dimension, 0, &ysize, NULL, NULL) || ecat_get_subhdr_value(file, volume, slice, ECAT_Data_Type, 0, &data_type, NULL, NULL) || (xsize <= 0) || (ysize <= 0)) { return TRUE; } /* Figure out the image size */ switch (data_type) { case 1: bytes_per_pixel = 1; break; case 2: case 6: bytes_per_pixel = 2; break; default: return TRUE; } image_npix = xsize * ysize; image_size = image_npix * bytes_per_pixel; /* Look for a z size */ zsize = 0; (void) ecat_get_subhdr_value(file, volume, slice, ECAT_Z_Dimension, 0, &zsize, NULL, NULL); /* Check the that the slice is in range */ if ((slice < 0) || ((zsize > 0) && (slice > zsize))) { return TRUE; } /* Find the appropriate subheader */ if (ecat_get_subhdr_offset(file, volume, slice, &file_offset)) { return TRUE; } /* Adjust the offset appropriately */ file_offset += BLOCK_SIZE; if (zsize > 0) { file_offset += image_size * slice; } /* Calculate image size and offsets */ array_offset = image_npix * (sizeof(short) - bytes_per_pixel); bimage = (unsigned char *) image; /* Read in the image */ if (fseek(file->file_pointer, file_offset, SEEK_SET) || (fread(&bimage[array_offset], (size_t) bytes_per_pixel, (size_t) image_npix, file->file_pointer) != image_npix)) { return TRUE; } /* Transform the image to the right type */ switch (bytes_per_pixel) { case 1: for (ipix=0; ipixheader_description == ECAT_VER_PRE7) { /*get_vax_short(image_npix, image, image);*/ } else { for (ipix=0; ipix= file->num_volumes) || (slice < 0) || (slice >= file->num_planes)) { return TRUE; } /* Calculate subheader number */ if (file->header_description == ECAT_VER_7) { subheader_number = volume; } else if (file->header_description == ECAT_VER_PRE7) { subheader_number = volume * file->num_planes + slice; } else { return TRUE; } /* Check the subheader number */ if ((subheader_number < 0) || (subheader_number >= file->num_subhdrs)) { return TRUE; } /* Get the offset for this subheader */ *offset = file->subhdr_offsets[subheader_number]; return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : malloc_check @INPUT : size - number of bytes to allocate @OUTPUT : (nothing) @RETURNS : pointer to memory @DESCRIPTION: Routine to allocate memory. It will never return NULL - the program will exit first. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void *malloc_check(size_t size) { void *ptr; ptr = malloc(size); if (ptr == NULL) { (void) fprintf(stderr, "Out of memory.\n"); exit(EXIT_FAILURE); } return ptr; } /* ----------------------------- MNI Header ----------------------------------- @NAME : realloc_check @INPUT : ptr - old pointer size - number of bytes to allocate @OUTPUT : (nothing) @RETURNS : pointer to memory @DESCRIPTION: Routine to re-allocate memory. It will never return NULL - the program will exit first. @METHOD : @GLOBALS : @CALLS : @CREATED : January 4, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public void *realloc_check(void *ptr, size_t size) { ptr = realloc(ptr, size); if (ptr == NULL) { (void) fprintf(stderr, "Out of memory.\n"); exit(EXIT_FAILURE); } return ptr; } minc-2.2.00/conversion/ecattominc/machine_indep.c0000644000265600003100000001755112027132661016712 00000000000000#include #include #include #ifdef _WIN32 unsigned short ntohs(unsigned short us) { unsigned char *p = (unsigned char*)&us; return ((unsigned short)p[1] + (p[0] >> 8)); } unsigned long ntohl(unsigned long ul) { unsigned char *p = (unsigned char*)&ul; return ((unsigned long)p[3] + (p[2] >> 8) + (p[1] >> 16) + (p[0] >> 24)); } #endif void get_short_value(const void *from, void *to) { short int short_value; (void) memcpy(&short_value, from, sizeof(short int)); *(short int *)to = ntohs(short_value); } void get_long_value(const void *from, void *to) { long int long_value; (void) memcpy(&long_value, from, sizeof(long int)); *(long int *)to = ntohl(long_value); } /* we need this, as the ecat directory block uses 32-bit ints */ void get_int32_value(const void *from, void *to) { int32_t int32_value; (void) memcpy(&int32_value, from, sizeof(int32_t)); *(int32_t *)to = ntohl(int32_value); } /* from vax_conversion.c -Copyright 1993 Peter Neelin */ /* ----------------------------- MNI Header ----------------------------------- @NAME : vax_conversions.c @DESCRIPTION: File containing routines to convert machine values to vax format values. @METHOD : @CREATED : December 10, 1992 (Peter Neelin) @MODIFIED : * $Log: machine_indep.c,v $ * Revision 6.6 2011-01-21 01:06:58 nikelski * * Fixed seg fault in ecattominc on 64-bit systems * * Corrected by modifying ecat_file.c and machine_indep.c as follows: * - added include providing access to the int32_t type * - changed the "dirblock" buffer from long to int32_t, making explicit * that this buffer needs to hold 32-bit ints (reflecting the ecat file) * - added function get_int32_value to return 32-bit ints from the * dirblock buffer * * Revision 6.5 2009/01/20 11:58:13 rotor * * CMakeLists.txt: updated version * * Updated Changelog to include releases * * Warning cleanups below * * conversion/dcm2mnc/minc_file.c: fixed printf type * * conversion/dcm2mnc/siemens_to_dicom.c: fixed printf type * * conversion/ecattominc/machine_indep.c: added string.h and fixed * 2 fprintf missing format args * * conversion/micropet/upet2mnc.c: fixed two fprintf format args * * conversion/minctoecat/ecat_write.c: added string.h * * conversion/minctoecat/minctoecat.c: added missing argument to fprintf * * conversion/nifti1/mnc2nii.c: fixed incorrect printf type * * progs/mincview/invert_raw_image.c: added fwrite checking * * Revision 6.4 2008/01/17 02:33:01 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.3 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.2 2005/05/19 20:58:37 bert * Fixes for Windows builds ported from 1.X branch * * Revision 6.1.2.2 2005/05/04 20:19:30 bert * Modify for Windows builds * * Revision 6.1.2.1 2005/02/15 19:59:54 bert * Initial checkin on 1.X branch * * Revision 6.1 2005/01/19 19:46:28 bert * Changes from Anthonin Reilhac * * Revision 6.2 1999/10/19 15:57:18 neelin * Fixed log message containing log substitution * * Revision 6.1 1999/10/19 14:45:15 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:34:32 neelin * Release of minc version 0.2 * * Revision 1.5 94/09/28 10:34:18 neelin * Pre-release * * Revision 1.4 93/08/04 13:04:01 neelin * Added RCS Log to keep track of modifications in source * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : get_vax_short @INPUT : nvals - number of values to convert vax_value - pointer to array of shorts in vax format @OUTPUT : mach_value - pointer to array of shorts in current machine format @RETURNS : (nothing) @DESCRIPTION: Converts vax short integers to short integers in the format of the current machine. @METHOD : @GLOBALS : (none) @CALLS : memcpy @CREATED : December 10, 1992. @MODIFIED : ---------------------------------------------------------------------------- */ void get_vax_short(int nvals, void *vax_value, short *mach_value) { int i; char *ptr1, *ptr2, v0, v1; #ifdef vax memcpy((void *) mach_value, vax_value, nvals*sizeof(short)); #else ptr1 = (char *) vax_value; ptr2 = (char *) mach_value; for (i=0; i #include #define BYTES 2 #define ARRSIZE 800*BYTES #define VALTYPE char main() { VALTYPE input[ARRSIZE]; VALTYPE output[ARRSIZE]; int i,nread,extra; while ((nread = fread(input, sizeof(VALTYPE), sizeof(input)/sizeof(VALTYPE), stdin)) > 0) { if ((extra = nread % BYTES) != 0) nread = nread-extra; for (i=0; i < nread; i+=BYTES) { output[i] = (VALTYPE) input[i+1]; output[i+1] = (VALTYPE) input[i]; } (void) fwrite(output, sizeof(VALTYPE), nread, stdout); } return 0; } minc-2.2.00/conversion/image_filters/extract.c0000644000265600003100000000521112027132661016253 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : extract.c @INPUT : argc - number of arguments argv - arguments 1 - number of bytes to skip (default = 0) 2 - number of bytes to copy (default = all) 3 - filename (if not present uses stdin) @OUTPUT : (none) @DESCRIPTION: Reads a given number of bytes from a file or standard input starting at a given byte. Writes those bytes to standard output. @METHOD : @GLOBALS : (none) @CALLS : @CREATED : January 13,1991 (P.N.) @MODIFIED : June 3,1992 (P.N.) - added -h argument to print usage ---------------------------------------------------------------------------- */ #include #include #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #define ARRSIZE 1500 #define INTYPE char main(int argc, char **argv) { char *pname; FILE *fp1; INTYPE value[ARRSIZE]; int nread,skip,pass,all; /* Get arguments */ if ((argc--) > 0) pname=(*argv++); /* program name */ if ((argc > 0) && (strcmp(*argv,"-h") == 0)) { (void) fprintf(stderr, "Usage: %s \n", pname); return 0; } if ((argc--)>0) /* bytes to skip */ skip=atol(*argv++); else skip=0; if ((argc--)>0) /* bytes to copy */ pass=atol(*argv++); else pass=(-1); all=(pass<0); if ((argc--) >0) { /* filename */ fp1=fopen(*argv,"r"); if (fp1 == NULL) { fprintf(stderr,"%s can't open %s\n",pname,*argv); exit(2); } /* Seek to right place on file */ if(fseek(fp1, skip, 0) == -1){ fprintf(stderr,"%s can't fseek on a terminal\n",pname); exit(2); } } else { fp1=stdin; /* Read to skip on stdin */ while(skip > 0) { if (skip > ARRSIZE) { nread = fread(value, sizeof(INTYPE),ARRSIZE,fp1); } else { nread = fread(value, sizeof(INTYPE),skip,fp1); } skip -= nread; if (nread <= 0) return 0; } } /* Copy bytes */ while ((pass > 0) || all) { if ((pass > ARRSIZE)||all) { nread = fread(value, sizeof(INTYPE),ARRSIZE,fp1); } else { nread = fread(value, sizeof(INTYPE),pass,fp1); } fwrite(value,sizeof(INTYPE),nread,stdout); pass -= nread; if (nread<=0) { pass = -1; all = FALSE; } } return 0; } minc-2.2.00/conversion/micropet/0000755000265600003100000000000012030114723013517 500000000000000minc-2.2.00/conversion/micropet/upet2mnc.man10000644000265600003100000000322412027132661015762 00000000000000.TH upet2mnc 1 "May 03 2005" "$Revision: 1.3 $" "" .SH NAME .B upet2mnc - convert a Concorde microPET format file to a MINC format file. .SH SYNOPSIS .B upet2mnc .I [] .B upet2mnc .I -help .SH DESCRIPTION The .B upet2mnc command is used to convert Concorde microPET format files to MINC format. The microPET format consists of two files, a binary image and a text header. The header file generally has the same name as the image with the suffix ".hdr" appended. Normally you can specify the name of either the binary image or the text header file on the command line. However, both of the files should be in the same directory for the converter to locate both files correctly. .SH "OPTIONS" Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .TP .BI -head Orient the image according to typical neurological conventions, with the Y axis oriented from the posterior to anterior, the Z axis oriented from inferior to superior, and X oriented from patient left to patient right. .TP .BI -body Orient the image such that the Y axis is oriented from superior to inferior, the Z axis is oriented from posterior to anterior, and X from patient left to patient right. .TP .BI -quiet Quiet operation - do not print progress or debugging information. .SH "Generic options for all commands" .TP .BI -help Print summary of command\-line options and abort .TP .BI -version Print the program and library versions and abort .SH AUTHOR Robert Vincent (bert@bic.mni.mcgill.ca) .SH "COPYRIGHTS" Copyrights 2005 by Robert Vincent for the Montreal Neurological Institute. minc-2.2.00/conversion/micropet/upet2mnc.c0000644000265600003100000012465712027132661015366 00000000000000/* concorde microPET to minc */ #include "config.h" #define _XOPEN_SOURCE 1 #include #include #include #include #include #include #include #include #include #define VERSIONSTR VERSION " built " __DATE__ " " __TIME__ /************************************************************************* * Concorde microPET definitions */ /* file_type field */ #define UPET_FT_UNKNOWN 0 #define UPET_FT_LIST_MODE 1 #define UPET_FT_SINOGRAM 2 #define UPET_FT_NORMALIZATION 3 #define UPET_FT_ATTENUATION_CORRECTION 4 #define UPET_FT_IMAGE 5 /* Standard image data file (typical) */ #define UPET_FT_BLANK 6 #define UPET_FT_MU_MAP 8 /* Mu map data file */ #define UPET_FT_SCATTER_CORRECTION 9 /* acquisition_mode field */ #define UPET_AM_UNKNOWN 0 #define UPET_AM_BLANK 1 #define UPET_AM_EMISSION 2 #define UPET_AM_DYNAMIC 3 #define UPET_AM_GATED 4 #define UPET_AM_CONTINUOUS_BED_MOTION 5 #define UPET_AM_SINGLES_TRANSMISSION 6 #define UPET_AM_WINDOWED_COINCIDENCE_TRANSMISSION 7 #define UPET_AM_NONWINDOWED_COINCIDENCE_TRANSMISSION 8 #define UPET_DT_UNKNOWN 0 #define UPET_DT_BYTE 1 #define UPET_DT_II16 2 /* Intel 16-bit signed integer */ #define UPET_DT_II32 3 /* Intel 32-bit signed integer */ #define UPET_DT_IF32 4 /* Intel 32-bit float */ #define UPET_DT_MF32 5 /* Sun 32-bit float */ #define UPET_DT_MI16 6 /* Sun 16-bit signed integer */ #define UPET_DT_MI32 7 /* Sun 32-bit signed integer */ #define DECLARE_FUNC(x) \ static int x(struct conversion_info *ci_ptr, char *val_str, char *new_var, char *new_att) struct conversion_info { FILE *hdr_fp; FILE *img_fp; int mnc_fd; int frame_index; int frame_zero; int data_type; nc_type minc_type; int dim_count; int dim_lengths[5]; int dim_ids[5]; double dim_steps[5]; int frame_nbytes; int frame_nvoxels; void *frame_buffer; double scale_factor; double deadtime_correction; double decay_correction; double calibration_factor; double isotope_branching_fraction; int swap_size; /* 0, 2, 4 */ }; DECLARE_FUNC(upet_file_type); DECLARE_FUNC(upet_acq_mode); DECLARE_FUNC(upet_bed_motion); DECLARE_FUNC(upet_data_type); DECLARE_FUNC(upet_data_order); DECLARE_FUNC(upet_ndims); DECLARE_FUNC(upet_total_frames); DECLARE_FUNC(upet_x_dim); DECLARE_FUNC(upet_y_dim); DECLARE_FUNC(upet_z_dim); DECLARE_FUNC(upet_vector_dim); DECLARE_FUNC(upet_injection_time); DECLARE_FUNC(upet_scan_time); DECLARE_FUNC(upet_axial_crystal_pitch); DECLARE_FUNC(upet_pixel_size); DECLARE_FUNC(upet_dose_units); DECLARE_FUNC(upet_calibration_factor); DECLARE_FUNC(upet_rotation); DECLARE_FUNC(upet_isotope_branching_fraction); DECLARE_FUNC(upet_frame_no); DECLARE_FUNC(upet_frame_start); DECLARE_FUNC(upet_frame_duration); DECLARE_FUNC(upet_frame_min); DECLARE_FUNC(upet_frame_max); DECLARE_FUNC(upet_frame_file_ptr); DECLARE_FUNC(upet_frame_scale_factor); DECLARE_FUNC(upet_frame_decay_correction); DECLARE_FUNC(upet_frame_deadtime_correction); static void copy_init(struct conversion_info *ci_ptr); static void copy_frame(struct conversion_info *ci_ptr); /* These values are used to represent the field types in the microPET * header file. */ #define UPET_TYPE_STR 1 /* String */ #define UPET_TYPE_INT 2 /* Integer */ #define UPET_TYPE_REAL 3 /* Floating-point */ #define UPET_TYPE_TIME 4 /* Timestamp */ #define UPET_TYPE_FILTER 5 /* Integer type followed by a float cutoff */ #define UPET_TYPE_3X64 6 /* 3 64-bit integers */ #define UPET_TYPE_FPTR 7 /* File pointer (2 32 bit integers) */ #define UPET_TYPE_SINGLE 8 /* Block #, singles/sec, raw singles/sec */ /* concorde keywords */ struct keywd_entry { char *upet_kwd; short upet_type; char *mnc_var; char *mnc_att; int (*func)(struct conversion_info *, char *, char *, char *); }; /* Per-frame attributes in the concorde microPET header */ struct keywd_entry frm_atts[] = { { "frame", UPET_TYPE_INT, NULL, NULL, upet_frame_no }, { "event_type", UPET_TYPE_INT, NULL, NULL, NULL }, { "gate", UPET_TYPE_INT, NULL, NULL, NULL }, { "bed", UPET_TYPE_INT, NULL, NULL, NULL }, { "bed_offset", UPET_TYPE_REAL, NULL, NULL, NULL }, { "ending_bed_offset", UPET_TYPE_REAL, NULL, NULL, NULL }, { "vertical_bed_offset", UPET_TYPE_REAL, NULL, NULL, NULL }, { "data_file_pointer", UPET_TYPE_FPTR, NULL, NULL, upet_frame_file_ptr }, { "frame_start", UPET_TYPE_REAL, NULL, NULL, upet_frame_start }, { "frame_duration", UPET_TYPE_REAL, NULL, NULL, upet_frame_duration }, { "scale_factor", UPET_TYPE_REAL, NULL, NULL, upet_frame_scale_factor }, { "minimum", UPET_TYPE_REAL, NULL, NULL, upet_frame_min }, { "maximum", UPET_TYPE_REAL, NULL, NULL, upet_frame_max }, { "deadtime_correction", UPET_TYPE_REAL, NULL, NULL, upet_frame_deadtime_correction }, { "decay_correction", UPET_TYPE_REAL, NULL, NULL, upet_frame_decay_correction }, { "prompts", UPET_TYPE_3X64, NULL, NULL, NULL }, { "delays", UPET_TYPE_3X64, NULL, NULL, NULL }, { "trues", UPET_TYPE_3X64, NULL, NULL, NULL }, { "prompts_rate", UPET_TYPE_INT, NULL, NULL, NULL }, { "delays_rate", UPET_TYPE_INT, NULL, NULL, NULL }, { "singles", UPET_TYPE_SINGLE, NULL, NULL, NULL }, { NULL, 0, NULL, NULL, NULL } }; /* Per-volume attributes in the concorde microPET header */ struct keywd_entry vol_atts[] = { { "ROI_file:", UPET_TYPE_STR, NULL, NULL, NULL }, { "version", UPET_TYPE_STR, NULL, NULL, NULL }, { "model", UPET_TYPE_INT, MIstudy, MIdevice_model, NULL }, { "institution", UPET_TYPE_STR, MIstudy, MIinstitution, NULL }, { "study", UPET_TYPE_STR, NULL, NULL, NULL }, { "file_name", UPET_TYPE_STR, NULL, NULL, NULL }, /* actual file data */ { "file_type", UPET_TYPE_INT, NULL, NULL, upet_file_type }, { "acquisition_mode", UPET_TYPE_INT, NULL, NULL, upet_acq_mode}, { "bed_motion", UPET_TYPE_INT, NULL, NULL, upet_bed_motion}, { "total_frames", UPET_TYPE_INT, NULL, NULL, upet_total_frames }, { "isotope", UPET_TYPE_STR, MIacquisition, MIradionuclide, NULL }, { "isotope_half_life", UPET_TYPE_REAL, MIacquisition, MIradionuclide_halflife, NULL }, { "isotope_branching_fraction", UPET_TYPE_REAL, NULL, NULL, upet_isotope_branching_fraction }, { "transaxial_crystals_per_block", UPET_TYPE_INT, NULL, NULL, NULL }, { "axial_crystals_per_block", UPET_TYPE_INT, NULL, NULL, NULL }, { "intrinsic_crystal_offset", UPET_TYPE_INT, NULL, NULL, NULL }, { "transaxial_blocks", UPET_TYPE_INT, NULL, NULL, NULL }, { "axial_blocks", UPET_TYPE_INT, NULL, NULL, NULL }, { "transaxial_crystal_pitch", UPET_TYPE_REAL, NULL, NULL, NULL }, { "axial_crystal_pitch", UPET_TYPE_REAL, NULL, NULL, upet_axial_crystal_pitch }, { "radius", UPET_TYPE_REAL, NULL, NULL, NULL }, { "radial_fov", UPET_TYPE_REAL, NULL, NULL, NULL }, { "src_radius", UPET_TYPE_REAL, NULL, NULL, NULL }, {"src_cm_per_rev", UPET_TYPE_REAL, NULL, NULL, NULL }, {"src_steps_per_rev", UPET_TYPE_INT, NULL, NULL, NULL }, {"tx_src_type", UPET_TYPE_INT, NULL, NULL, NULL }, {"default_projections", UPET_TYPE_INT, NULL, NULL, NULL }, {"default_transaxial_angles", UPET_TYPE_INT, NULL, NULL, NULL }, {"crystal_thickness", UPET_TYPE_REAL, NULL, NULL, NULL }, {"depth_of_interaction", UPET_TYPE_REAL, NULL, NULL, NULL }, {"transaxial_bin_size", UPET_TYPE_REAL, NULL, NULL, NULL }, {"axial_plane_size", UPET_TYPE_REAL, NULL, NULL, NULL }, {"lld", UPET_TYPE_REAL, NULL, NULL, NULL }, {"uld", UPET_TYPE_REAL, NULL, NULL, NULL }, {"timing_window", UPET_TYPE_INT, NULL, NULL, NULL }, {"data_type", UPET_TYPE_INT, NULL, NULL, upet_data_type }, {"data_order", UPET_TYPE_INT, NULL, NULL, upet_data_order }, {"span", UPET_TYPE_INT, NULL, NULL, NULL }, {"ring_difference", UPET_TYPE_INT, NULL, NULL, NULL }, {"number_of_dimensions", UPET_TYPE_INT, NULL, NULL, upet_ndims }, {"x_dimension", UPET_TYPE_INT, NULL, NULL, upet_x_dim }, {"y_dimension", UPET_TYPE_INT, NULL, NULL, upet_y_dim }, {"z_dimension", UPET_TYPE_INT, NULL, NULL, upet_z_dim }, {"w_dimension", UPET_TYPE_INT, NULL, NULL, upet_vector_dim }, {"x_filter", UPET_TYPE_FILTER, NULL, NULL, NULL }, {"y_filter", UPET_TYPE_FILTER, NULL, NULL, NULL }, {"z_filter", UPET_TYPE_FILTER, NULL, NULL, NULL }, {"histogram_version", UPET_TYPE_STR, NULL, NULL, NULL }, {"rebinning_type", UPET_TYPE_INT, NULL, NULL, NULL }, {"rebinning_version", UPET_TYPE_STR, NULL, NULL, NULL }, {"recon_algorithm", UPET_TYPE_INT, NULL, NULL, NULL }, {"recon_version", UPET_TYPE_STR, NULL, NULL, NULL }, {"map_subsets", UPET_TYPE_INT, NULL, NULL, NULL }, {"map_osem3d_iterations", UPET_TYPE_INT, NULL, NULL, NULL }, {"map_iterations", UPET_TYPE_INT, NULL, NULL, NULL }, {"map_beta", UPET_TYPE_REAL, NULL, NULL, NULL }, {"map_blur_type", UPET_TYPE_INT, NULL, NULL, NULL }, {"map_prior_type", UPET_TYPE_INT, NULL, NULL, NULL }, {"map_blur_file", UPET_TYPE_STR, NULL, NULL, NULL }, {"map_pmatrix_file", UPET_TYPE_STR, NULL, NULL, NULL }, {"deadtime_correction_applied", UPET_TYPE_INT, NULL, NULL, NULL }, {"decay_correction_applied", UPET_TYPE_INT, NULL, NULL, NULL }, {"normalization_applied", UPET_TYPE_INT, NULL, NULL, NULL }, {"normalization_filename", UPET_TYPE_STR, NULL, NULL, NULL }, {"attenuation_applied", UPET_TYPE_INT, NULL, NULL, NULL }, {"attenuation_filename", UPET_TYPE_STR, NULL, NULL, NULL }, {"scatter_correction", UPET_TYPE_INT, NULL, NULL, NULL }, {"scatter_version", UPET_TYPE_STR, NULL, NULL, NULL }, {"arc_correction_applied", UPET_TYPE_INT, NULL, NULL, NULL }, {"rotation", UPET_TYPE_REAL, NULL, NULL, upet_rotation }, {"x_offset", UPET_TYPE_REAL, NULL, NULL, NULL }, {"y_offset", UPET_TYPE_REAL, NULL, NULL, NULL }, {"z_offset", UPET_TYPE_REAL, NULL, NULL, NULL }, {"zoom", UPET_TYPE_REAL, NULL, NULL, NULL }, {"pixel_size", UPET_TYPE_REAL, NULL, NULL, upet_pixel_size }, {"calibration_units", UPET_TYPE_INT, NULL, NULL, NULL }, {"calibration_factor", UPET_TYPE_REAL, NULL, NULL, upet_calibration_factor }, {"calibration_branching_fraction", UPET_TYPE_REAL, NULL, NULL, NULL }, {"number_of_singles_rates", UPET_TYPE_INT, NULL, NULL, NULL }, {"investigator", UPET_TYPE_STR, MIstudy, "investigator", NULL }, {"operator", UPET_TYPE_STR, MIstudy, MIoperator, NULL }, {"study_identifier", UPET_TYPE_STR, MIstudy, MIstudy_id, NULL }, {"scan_time", UPET_TYPE_TIME, NULL, NULL, upet_scan_time }, {"injected_compound", UPET_TYPE_STR, NULL, NULL, NULL }, {"dose_units", UPET_TYPE_INT, MIacquisition, MIdose_units, upet_dose_units }, {"dose", UPET_TYPE_REAL, MIacquisition, MIinjection_dose, NULL }, {"injection_time", UPET_TYPE_TIME, NULL, NULL, upet_injection_time }, {"injection_decay_correction", UPET_TYPE_REAL, NULL, NULL, NULL }, {"subject_identifier", UPET_TYPE_STR, NULL, NULL, NULL }, {"subject_genus", UPET_TYPE_STR, NULL, NULL, NULL }, {"subject_orientation", UPET_TYPE_INT, NULL, NULL, NULL }, {"subject_length_units", UPET_TYPE_INT, NULL, NULL, NULL }, {"subject_length", UPET_TYPE_REAL, NULL, NULL, NULL }, {"subject_weight_units", UPET_TYPE_INT, NULL, NULL, NULL }, {"subject_weight", UPET_TYPE_REAL, NULL, NULL, NULL }, {"subject_phenotype", UPET_TYPE_STR, NULL, NULL, NULL }, {"study_model", UPET_TYPE_STR, NULL, NULL, NULL }, {"anesthesia", UPET_TYPE_STR, NULL, NULL, NULL }, {"analgesia", UPET_TYPE_STR, NULL, NULL, NULL }, {"other_drugs", UPET_TYPE_STR, NULL, NULL, NULL }, {"food_access", UPET_TYPE_STR, NULL, NULL, NULL }, {"water_access", UPET_TYPE_STR, NULL, NULL, NULL }, {NULL, 0, NULL, NULL, NULL } }; /* Reflects "normal" image data order */ #define DIM_T 0 #define DIM_Z 1 #define DIM_Y 2 #define DIM_X 3 #define DIM_W 4 static char *_dimnames[5]; /* Calculate the overall scaling factor for the image data from the * conversion information structure. */ #define COMBINED_SCALE_FACTOR(ci_ptr) \ ((ci_ptr->scale_factor * ci_ptr->calibration_factor) / \ (ci_ptr->isotope_branching_fraction)) #define ORIENT_BODY 1 #define ORIENT_HEAD 2 int _orient_flag = ORIENT_HEAD; int _verbose_flag = 1; ArgvInfo argTable[] = { {"-head", ARGV_CONSTANT, (char *) ORIENT_HEAD, (char *) &_orient_flag, "Orient image for cerebral viewing (as with human brain)"}, {"-body", ARGV_CONSTANT, (char *) ORIENT_BODY, (char *) &_orient_flag, "Orient image for whole-body viewing (Z along long axis)"}, {"-quiet", ARGV_CONSTANT, (char *) 0, (char *) &_verbose_flag, "Turn off the various progress reporting messages."}, {NULL, ARGV_VERINFO, (char *) VERSIONSTR, (char *) NULL, NULL}, {NULL, ARGV_END, NULL, NULL, NULL} }; typedef enum { MSG_INFO, MSG_WARNING, MSG_ERROR, MSG_FATAL } msg_level_t; static void message(msg_level_t level, char *fmt, ...) { va_list ap; const char *prefix_str; switch (level) { case MSG_WARNING: prefix_str = "WARNING: "; break; case MSG_ERROR: prefix_str = "ERROR: "; break; case MSG_FATAL: prefix_str = "FATAL: "; break; default: prefix_str = NULL; break; } if (_verbose_flag || level != MSG_INFO) { if (level != MSG_INFO) { if (prefix_str != NULL) { fprintf(stderr, "%s", prefix_str); } va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } if (prefix_str != NULL) { fprintf(stdout, "%s", prefix_str); } va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); } } static int is_host_big_endian() { long ltmp = 0x04030201; char *ctmp = (char *) <mp; if (ctmp[0] == 0x01) { return (0); } if (ctmp[0] == 0x04) { return (1); } return (-1); } static void usage(const char *progname) { fprintf(stderr, "\nUsage: %s [] input.img[.hdr] [output.mnc]\n", progname); fprintf(stderr, " %s [-help]\n\n", progname); exit(-1); } int upet_to_minc(char *hdr_fname, char *img_fname, char *out_fname, char *prog_name) { char *line_ptr; char line_buf[1024]; char *val_ptr; int in_header; double dbl_tmp; int int_tmp; struct conversion_info ci; struct keywd_entry *ke_ptr; int is_known; char *argv_tmp[5]; char *out_history; ci.hdr_fp = fopen(hdr_fname, "r"); /* Text file */ if (ci.hdr_fp == NULL) { perror(hdr_fname); return (-1); } ci.img_fp = fopen(img_fname, "rb"); /* Binary file */ if (ci.img_fp == NULL) { perror(img_fname); return (-1); } ci.mnc_fd = micreate(out_fname, NC_NOCLOBBER); if (ci.mnc_fd < 0) { perror(out_fname); return (-1); } ci.frame_zero = -1; /* Initial frame is -1 until set. */ /* Define the basic MINC group variables. */ micreate_group_variable(ci.mnc_fd, MIstudy); micreate_group_variable(ci.mnc_fd, MIacquisition); micreate_group_variable(ci.mnc_fd, MIpatient); ncvardef(ci.mnc_fd, "micropet", NC_SHORT, 0, NULL); /* Fake the history here */ argv_tmp[0] = prog_name; argv_tmp[1] = VERSIONSTR; argv_tmp[2] = hdr_fname; argv_tmp[3] = img_fname; argv_tmp[4] = out_fname; out_history = time_stamp(5, argv_tmp); miattputstr(ci.mnc_fd, NC_GLOBAL, MIhistory, out_history); free(out_history); in_header = 1; ci.frame_nbytes = 1; ci.frame_nvoxels = 1; /* When we read voxels, we need COMBINED_SCALE_FACTOR() to have a sane * value for all modalities. Set defaults for these in case the modality * does not define one of these factors. For example, a CT (modality 2) * will not define isotope_branching_fraction or calibration_factor. */ ci.scale_factor = 1.0; ci.calibration_factor = 1.0; ci.isotope_branching_fraction = 1.0; /* Collect the headers */ while (fgets(line_buf, sizeof(line_buf), ci.hdr_fp) != NULL) { if (line_buf[0] == '#') /* */ continue; line_ptr = line_buf; while (!isspace(*line_ptr)) { line_ptr++; } *line_ptr++ = '\0'; val_ptr = line_ptr; while (*line_ptr != '\n' && *line_ptr != '\r' && *line_ptr != '\0') { line_ptr++; } *line_ptr = '\0'; is_known = 0; if (in_header) { if (*val_ptr != '\0') { /* Save the raw attribute into the file */ ncattput(ci.mnc_fd, ncvarid(ci.mnc_fd, "micropet"), line_buf, NC_CHAR, strlen(val_ptr), val_ptr); } for (ke_ptr = vol_atts; ke_ptr->upet_kwd != NULL; ke_ptr++) { if (!strcmp(ke_ptr->upet_kwd, line_buf)) { is_known = 1; if (ke_ptr->func != NULL) { (*ke_ptr->func)(&ci, val_ptr, ke_ptr->mnc_var, ke_ptr->mnc_att); } else if (ke_ptr->mnc_var != NULL && ke_ptr->mnc_att != NULL) { /* Interpret based upon type */ switch (ke_ptr->upet_type) { case UPET_TYPE_INT: int_tmp = atoi(val_ptr); miattputint(ci.mnc_fd, ncvarid(ci.mnc_fd, ke_ptr->mnc_var), ke_ptr->mnc_att, int_tmp); break; case UPET_TYPE_REAL: dbl_tmp = atof(val_ptr); miattputdbl(ci.mnc_fd, ncvarid(ci.mnc_fd, ke_ptr->mnc_var), ke_ptr->mnc_att, dbl_tmp); break; case UPET_TYPE_STR: miattputstr(ci.mnc_fd, ncvarid(ci.mnc_fd, ke_ptr->mnc_var), ke_ptr->mnc_att, val_ptr); break; } } break; } } } else { /* Not in the header any longer */ for (ke_ptr = frm_atts; ke_ptr->upet_kwd != NULL; ke_ptr++) { if (!strcmp(ke_ptr->upet_kwd, line_buf)) { is_known = 1; if (ke_ptr->func != NULL) { (*ke_ptr->func)(&ci, val_ptr, ke_ptr->mnc_var, ke_ptr->mnc_att); } break; } } } if (!is_known) { if (!strcmp(line_buf, "end_of_header")) { if (in_header) { in_header = 0; copy_init(&ci); } else { copy_frame(&ci); } } else { message(MSG_WARNING, "Unrecognized keyword %s\n", line_buf); } } } fclose(ci.hdr_fp); fclose(ci.img_fp); miclose(ci.mnc_fd); return (0); } int main(int argc, char **argv) { char *line_ptr; int i; char img_fname[1024]; char hdr_fname[1024]; char out_fname[1024]; int result; if (ParseArgv(&argc, argv, argTable, 0) || argc < 2) { usage(argv[0]); return (-1); } ncopts = 0; /* Set the dimension names. This is done here since the correct * arrangement depends on the value of _orient_flag */ _dimnames[DIM_T] = MItime; _dimnames[DIM_X] = MIxspace; _dimnames[DIM_Y] = MIyspace; _dimnames[DIM_Z] = MIzspace; _dimnames[DIM_W] = MIvector_dimension; if (_orient_flag == ORIENT_HEAD) { /* If using head orientation, exchange Y and Z. */ _dimnames[DIM_Y] = MIzspace; _dimnames[DIM_Z] = MIyspace; } /* Open the header and the associated binary file. */ for (i = 1; i < argc; i++) { /* Here we try to be flexible about allowing the user to specify * either the name of the .hdr file or the name of the .img file, * or just the base name of the two files. All three options * should work. */ strcpy(img_fname, argv[i]); strcpy(hdr_fname, argv[i]); /* Find the last extension. */ line_ptr = strrchr(argv[i], '.'); /* Did the user specify the .hdr file?? */ if (line_ptr != NULL && !strcmp(line_ptr, ".hdr")) { line_ptr = strrchr(img_fname, '.'); if (line_ptr != NULL) { *line_ptr = '\0'; } } /* Did the user specify the .img file?? */ else if (line_ptr != NULL && !strcmp(line_ptr, ".img")) { strcat(hdr_fname, ".hdr"); } /* Or perhaps just the base name?? */ else { strcat(img_fname, ".img"); strcat(hdr_fname, ".img.hdr"); } /* See if there is a filename following this one, and if so, does it * end with the ".mnc" extension. If so, take that names as the * output for this conversions. */ if (i < argc - 1 && (line_ptr = strrchr(argv[i+1], '.')) != NULL && !strcmp(line_ptr, ".mnc")) { strcpy(out_fname, argv[i+1]); i++; } else { strcpy(out_fname, img_fname); line_ptr = strrchr(out_fname, '.'); if (line_ptr != NULL) { strcpy(line_ptr, ".mnc"); } } /* Perform the conversion. */ message(MSG_INFO, "Starting conversion\n"); message(MSG_INFO, "- Input header: %s\n", hdr_fname); message(MSG_INFO, "- Input image: %s\n", img_fname); message(MSG_INFO, "- Output file: %s\n", out_fname); result = upet_to_minc(hdr_fname, img_fname, out_fname, argv[0]); if (result < 0) { message(MSG_ERROR, "Error creating %s\n", out_fname); } else { message(MSG_INFO, "Finished creating %s\n", out_fname); } } return 0; } DECLARE_FUNC(upet_file_type) { int file_type = atoi(val_str); switch (file_type) { case UPET_FT_IMAGE: /* Image file */ case UPET_FT_MU_MAP: /* Mu map file */ return (0); default: message(MSG_WARNING, "File type %d is not handled. Conversion results may be problematic...\n", file_type); break; } return (1); } DECLARE_FUNC(upet_acq_mode) { int mode_int = atoi(val_str); char *mode_str; switch (mode_int) { case UPET_AM_UNKNOWN: mode_str = "unknown"; break; case UPET_AM_BLANK: mode_str = "blank"; break; case UPET_AM_EMISSION: mode_str = "emission"; break; case UPET_AM_DYNAMIC: mode_str = "dynamic"; break; case UPET_AM_GATED: mode_str = "gated"; break; case UPET_AM_CONTINUOUS_BED_MOTION: mode_str = "continuous_bed_motion"; break; case UPET_AM_SINGLES_TRANSMISSION: mode_str = "singles_transmission"; break; case UPET_AM_WINDOWED_COINCIDENCE_TRANSMISSION: mode_str = "windowed_coincidence_transmission"; break; case UPET_AM_NONWINDOWED_COINCIDENCE_TRANSMISSION: mode_str = "non-windowed_coincidence_transmission"; break; default: message(MSG_WARNING, "Unknown acquisition mode %d\n", mode_int); mode_str = NULL; break; } if (mode_str != NULL) { miattputstr(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, MIacquisition), "micropet_mode", mode_str); } return (0); } DECLARE_FUNC(upet_bed_motion) { return (0); } DECLARE_FUNC(upet_data_type) { ci_ptr->data_type = atoi(val_str); switch (ci_ptr->data_type) { case UPET_DT_BYTE: ci_ptr->minc_type = NC_BYTE; break; case UPET_DT_II16: ci_ptr->minc_type = NC_SHORT; ci_ptr->frame_nbytes *= 2; if (is_host_big_endian()) { ci_ptr->swap_size = 2; } else { ci_ptr->swap_size = 0; } break; case UPET_DT_II32: ci_ptr->minc_type = NC_INT; ci_ptr->frame_nbytes *= 4; if (is_host_big_endian()) { ci_ptr->swap_size = 4; } else { ci_ptr->swap_size = 0; } break; case UPET_DT_IF32: ci_ptr->minc_type = NC_FLOAT; ci_ptr->frame_nbytes *= 4; if (is_host_big_endian()) { ci_ptr->swap_size = 4; } else { ci_ptr->swap_size = 0; } break; case UPET_DT_MF32: ci_ptr->minc_type = NC_FLOAT; ci_ptr->frame_nbytes *= 4; if (!is_host_big_endian()) { ci_ptr->swap_size = 4; } else { ci_ptr->swap_size = 0; } break; case UPET_DT_MI16: ci_ptr->minc_type = NC_SHORT; ci_ptr->frame_nbytes *= 2; if (!is_host_big_endian()) { ci_ptr->swap_size = 2; } else { ci_ptr->swap_size = 0; } break; case UPET_DT_MI32: ci_ptr->minc_type = NC_INT; ci_ptr->frame_nbytes *= 4; if (!is_host_big_endian()) { ci_ptr->swap_size = 4; } else { ci_ptr->swap_size = 0; } break; default: message(MSG_ERROR, "Unknown data type %d\n", ci_ptr->data_type); return (1); } if (ci_ptr->swap_size != 0) { message(MSG_INFO, "Swapping groups of %d bytes.\n", ci_ptr->swap_size); } else { message(MSG_INFO, "No byte-swapping required.\n"); } return (0); } DECLARE_FUNC(upet_data_order) { if (atoi(val_str) != 1) { message(MSG_WARNING, "Unknown data order.\n"); } return (0); } DECLARE_FUNC(upet_ndims) { ci_ptr->dim_count = atoi(val_str); return (0); } static void create_dimension(struct conversion_info *ci_ptr, int index, int length) { ci_ptr->dim_lengths[index] = length; if (index == DIM_W && length <= 1) { return; } ci_ptr->dim_ids[index] = ncdimdef(ci_ptr->mnc_fd, _dimnames[index], length); if (index == DIM_T) { micreate_std_variable(ci_ptr->mnc_fd, _dimnames[index], NC_DOUBLE, 1, &ci_ptr->dim_ids[index]); micreate_std_variable(ci_ptr->mnc_fd, MItime_width, NC_DOUBLE, 1, &ci_ptr->dim_ids[index]); } else if (index != DIM_W) { micreate_std_variable(ci_ptr->mnc_fd, _dimnames[index], NC_DOUBLE, 0, NULL); } } DECLARE_FUNC(upet_total_frames) { create_dimension(ci_ptr, DIM_T, atoi(val_str)); return (0); } DECLARE_FUNC(upet_x_dim) { int x = atoi(val_str); ci_ptr->frame_nbytes *= x; ci_ptr->frame_nvoxels *= x; create_dimension(ci_ptr, DIM_X, x); return (0); } DECLARE_FUNC(upet_y_dim) { int y = atoi(val_str); ci_ptr->frame_nbytes *= y; ci_ptr->frame_nvoxels *= y; create_dimension(ci_ptr, DIM_Y, y); return (0); } DECLARE_FUNC(upet_z_dim) { int z = atoi(val_str); ci_ptr->frame_nbytes *= z; ci_ptr->frame_nvoxels *= z; create_dimension(ci_ptr, DIM_Z, z); return (0); } DECLARE_FUNC(upet_vector_dim) { int w = atoi(val_str); ci_ptr->frame_nbytes *= w; ci_ptr->frame_nvoxels *= w; create_dimension(ci_ptr, DIM_W, w); return (0); } /* Parse a micropet time string of the form: Ddd Mmm NN HH:MM:SS YYYY * e.g. Fri Jan 7 14:16:31 2005 */ static int parse_time(char *str_ptr, struct tm *tm_ptr) { /* Just skip the first three characters. */ while (*str_ptr != '\0' && *str_ptr != ' ') { str_ptr++; } while (*str_ptr == ' ') { str_ptr++; } /* Decode the month */ if (str_ptr[0] == 'A') { if (str_ptr[1] == 'p') { tm_ptr->tm_mon = 4 - 1; /* April */ } else { tm_ptr->tm_mon = 8 - 1; /* August */ } } else if (str_ptr[0] == 'D') { tm_ptr->tm_mon = 12 - 1; /* December */ } else if (str_ptr[0] == 'F') { /* February */ tm_ptr->tm_mon = 2 - 1; } else if (str_ptr[0] == 'J') { if (str_ptr[1] == 'a') { tm_ptr->tm_mon = 1 - 1; /* January */ } else if (str_ptr[2] == 'l') { tm_ptr->tm_mon = 7 - 1; /* July */ } else { tm_ptr->tm_mon = 6 - 1; /* June */ } } else if (str_ptr[0] == 'M') { if (str_ptr[2] == 'r') { tm_ptr->tm_mon = 3 - 1; /* March */ } else { tm_ptr->tm_mon = 5 - 1; /* May */ } } else if (str_ptr[0] == 'N') { tm_ptr->tm_mon = 11 - 1; /* November */ } else if (str_ptr[0] == 'O') { tm_ptr->tm_mon = 10 - 1; /* October */ } else if (str_ptr[0] == 'S') { tm_ptr->tm_mon = 9 - 1; /* September */ } else { return 0; } /* Skip past the month */ while (*str_ptr != ' ' && *str_ptr != '\0') { str_ptr++; } while (*str_ptr == ' ') { str_ptr++; } tm_ptr->tm_mday = 0; while (isdigit(*str_ptr)) { tm_ptr->tm_mday = (tm_ptr->tm_mday * 10) + (*str_ptr++ - '0'); } while (*str_ptr == ' ') { str_ptr++; } tm_ptr->tm_hour = 0; while (isdigit(*str_ptr)) { tm_ptr->tm_hour = (tm_ptr->tm_hour * 10) + (*str_ptr++ - '0'); } if (*str_ptr == ':') { str_ptr++; } else { return 0; } tm_ptr->tm_min = 0; while (isdigit(*str_ptr)) { tm_ptr->tm_min = (tm_ptr->tm_min * 10) + (*str_ptr++ - '0'); } if (*str_ptr == ':') { str_ptr++; } else { return 0; } tm_ptr->tm_sec = 0; while (isdigit(*str_ptr)) { tm_ptr->tm_sec = (tm_ptr->tm_sec * 10) + (*str_ptr++ - '0'); } while (*str_ptr == ' ') { str_ptr++; } tm_ptr->tm_year = 0; while (isdigit(*str_ptr)) { tm_ptr->tm_year = (tm_ptr->tm_year * 10) + (*str_ptr++ - '0'); } tm_ptr->tm_year -= 1900; return 1; } DECLARE_FUNC(upet_injection_time) { struct tm tmbuf; int id; char str_buf[128]; id = ncvarid(ci_ptr->mnc_fd, MIacquisition); if (!parse_time(val_str, &tmbuf)) { strcpy(str_buf, "unknown"); miattputstr(ci_ptr->mnc_fd, id, MIinjection_time, str_buf); miattputstr(ci_ptr->mnc_fd, id, MIinjection_year, str_buf); miattputstr(ci_ptr->mnc_fd, id, MIinjection_month, str_buf); miattputstr(ci_ptr->mnc_fd, id, MIinjection_day, str_buf); } else { sprintf(str_buf, "%02d%02d%02d", tmbuf.tm_hour, tmbuf.tm_min, tmbuf.tm_sec); miattputstr(ci_ptr->mnc_fd, id, MIinjection_time, str_buf); sprintf(str_buf, "%d", tmbuf.tm_year + 1900); miattputstr(ci_ptr->mnc_fd, id, MIinjection_year, str_buf); sprintf(str_buf, "%d", tmbuf.tm_mon + 1); miattputstr(ci_ptr->mnc_fd, id, MIinjection_month, str_buf); sprintf(str_buf, "%d", tmbuf.tm_mday); miattputstr(ci_ptr->mnc_fd, id, MIinjection_day, str_buf); } return (0); } DECLARE_FUNC(upet_scan_time) { struct tm tmbuf; int id; char str_buf[128]; id = ncvarid(ci_ptr->mnc_fd, MIstudy); if (!parse_time(val_str, &tmbuf)) { strcpy(str_buf, "unknown"); miattputstr(ci_ptr->mnc_fd, id, MIstart_time, str_buf); miattputstr(ci_ptr->mnc_fd, id, MIstart_year, str_buf); miattputstr(ci_ptr->mnc_fd, id, MIstart_month, str_buf); miattputstr(ci_ptr->mnc_fd, id, MIstart_day, str_buf); } else { sprintf(str_buf, "%02d%02d%02d", tmbuf.tm_hour, tmbuf.tm_min, tmbuf.tm_sec); miattputstr(ci_ptr->mnc_fd, id, MIstart_time, str_buf); sprintf(str_buf, "%d", tmbuf.tm_year + 1900); miattputstr(ci_ptr->mnc_fd, id, MIstart_year, str_buf); sprintf(str_buf, "%d", tmbuf.tm_mon + 1); miattputstr(ci_ptr->mnc_fd, id, MIstart_month, str_buf); sprintf(str_buf, "%d", tmbuf.tm_mday); miattputstr(ci_ptr->mnc_fd, id, MIstart_day, str_buf); } return (0); } DECLARE_FUNC(upet_axial_crystal_pitch) { double dbl_tmp = atof(val_str); /* dbl_tmp is in cm. Convert to mm. */ dbl_tmp *= 10.0; /* Now convert from crystal pitch to actual slice width */ dbl_tmp /= 2.0; ci_ptr->dim_steps[DIM_Z] = dbl_tmp; return (0); } DECLARE_FUNC(upet_pixel_size) { double dbl_tmp = atof(val_str); /* dbl_tmp is in cm. Convert to mm. */ dbl_tmp *= 10.0; ci_ptr->dim_steps[DIM_X] = dbl_tmp; ci_ptr->dim_steps[DIM_Y] = dbl_tmp; return (0); } DECLARE_FUNC(upet_dose_units) { int tmp = atoi(val_str); char *str_ptr; if (tmp == 0) { str_ptr = "unknown"; } else if (tmp == 1) { str_ptr = "mCi"; } else if (tmp == 2) { str_ptr = "MBq"; } else { str_ptr = "???????"; message(MSG_WARNING, "Unrecognized dose_units value %d\n", tmp); } miattputstr(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, new_var), new_att, str_ptr); return (0); } DECLARE_FUNC(upet_calibration_factor) { double dbl_tmp = atof(val_str); ci_ptr->calibration_factor = dbl_tmp; return (0); } DECLARE_FUNC(upet_isotope_branching_fraction) { double dbl_tmp = atof(val_str); ci_ptr->isotope_branching_fraction = dbl_tmp; return (0); } DECLARE_FUNC(upet_rotation) { double dbl_tmp = atof(val_str); if (dbl_tmp != 0.0) { message(MSG_WARNING, "Rotation is %f\n", dbl_tmp); } return (0); } /***********************/ /* Per-frame functions */ DECLARE_FUNC(upet_frame_no) { ci_ptr->frame_index = atoi(val_str); /* Set index of "zeroth" frame if not already set. */ if (ci_ptr->frame_zero < 0) { ci_ptr->frame_zero = ci_ptr->frame_index; } return (0); } DECLARE_FUNC(upet_frame_start) { long index = ci_ptr->frame_index - ci_ptr->frame_zero; double dbl_tmp = atof(val_str); mivarput1(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, MItime), &index, NC_DOUBLE, MI_SIGNED, &dbl_tmp); return (0); } DECLARE_FUNC(upet_frame_duration) { long index = ci_ptr->frame_index - ci_ptr->frame_zero; double dbl_tmp = atof(val_str); mivarput1(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, MItime_width), &index, NC_DOUBLE, MI_SIGNED, &dbl_tmp); return (0); } DECLARE_FUNC(upet_frame_min) { long index = ci_ptr->frame_index - ci_ptr->frame_zero; double dbl_tmp = atof(val_str); dbl_tmp *= COMBINED_SCALE_FACTOR(ci_ptr); mivarput1(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, MIimagemin), &index, NC_DOUBLE, MI_SIGNED, &dbl_tmp); return (0); } DECLARE_FUNC(upet_frame_max) { long index = ci_ptr->frame_index - ci_ptr->frame_zero; double dbl_tmp = atof(val_str); dbl_tmp *= COMBINED_SCALE_FACTOR(ci_ptr); mivarput1(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, MIimagemax), &index, NC_DOUBLE, MI_SIGNED, &dbl_tmp); return (0); } DECLARE_FUNC(upet_frame_file_ptr) { long hipart; long lopart; char *end_ptr; lopart = strtol(val_str, &end_ptr, 10); if (*end_ptr == ' ') { while (*end_ptr == ' ') { end_ptr++; } if (isdigit(*end_ptr)) { hipart = lopart; lopart = strtol(end_ptr, NULL, 10); } } /* Seek the image file to the data */ fseek(ci_ptr->img_fp, lopart, SEEK_SET); return (0); } DECLARE_FUNC(upet_frame_scale_factor) { ci_ptr->scale_factor = atof(val_str); return (0); } DECLARE_FUNC(upet_frame_deadtime_correction) { ci_ptr->deadtime_correction = atof(val_str); return (0); } DECLARE_FUNC(upet_frame_decay_correction) { ci_ptr->decay_correction = atof(val_str); return (0); } static void swap_data(int swap_size, long nvox, unsigned char *data) { unsigned char tmp; if (swap_size == 2) { while (nvox--) { tmp = data[0]; data[0] = data[1]; data[1] = tmp; data += 2; } } else if (swap_size == 4) { while (nvox--) { tmp = data[0]; data[0] = data[3]; data[3] = tmp; tmp = data[1]; data[1] = data[2]; data[2] = tmp; data += 4; } } } static void scale_data(nc_type datatype, long nvox, void *data, double scale) { long i; double tmp; switch (datatype) { case NC_BYTE: for (i = 0; i < nvox; i++) { tmp = (double) ((char *)data)[i]; tmp *= scale; ((char *)data)[i] = tmp; } break; case NC_SHORT: for (i = 0; i < nvox; i++) { tmp = (double) ((short *)data)[i]; tmp *= scale; ((short *)data)[i] = tmp; } break; case NC_INT: for (i = 0; i < nvox; i++) { tmp = (double) ((int *)data)[i]; tmp *= scale; ((int *)data)[i] = tmp; } break; case NC_FLOAT: for (i = 0; i < nvox; i++) { tmp = (double) ((float *)data)[i]; tmp *= scale; ((float *)data)[i] = tmp; } break; case NC_DOUBLE: for (i = 0; i < nvox; i++) { tmp = (double) ((double *)data)[i]; tmp *= scale; ((double *)data)[i] = tmp; } break; default: message(MSG_ERROR, "Data type %d not handled\n", datatype); break; } } void copy_init(struct conversion_info *ci_ptr) { ci_ptr->frame_buffer = malloc(ci_ptr->frame_nbytes); if (ci_ptr->frame_buffer == NULL) { message(MSG_FATAL, "Out of memory\n"); exit(-1); } /* Create the image, imagemax, and imagemin variables. */ micreate_std_variable(ci_ptr->mnc_fd, MIimagemax, NC_DOUBLE, 1, ci_ptr->dim_ids); micreate_std_variable(ci_ptr->mnc_fd, MIimagemin, NC_DOUBLE, 1, ci_ptr->dim_ids); micreate_std_variable(ci_ptr->mnc_fd, MIimage, ci_ptr->minc_type, ci_ptr->dim_count + 1, ci_ptr->dim_ids); /* Set up the dimension step and start values. Because of the microPET * data orientation, we set Z and Y to be the inverse of the norm, to * put the animal's nose at the top of the display. * TODO: allow this behavior to be controlled on the command line. */ miattputdbl(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_Z]), MIstep, -ci_ptr->dim_steps[DIM_Z]); miattputdbl(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_X]), MIstep, ci_ptr->dim_steps[DIM_X]); miattputdbl(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_Y]), MIstep, -ci_ptr->dim_steps[DIM_Y]); miattputdbl(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_Z]), MIstart, ci_ptr->dim_steps[DIM_Z] * ci_ptr->dim_lengths[DIM_Z]); miattputdbl(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_X]), MIstart, 0.0); miattputdbl(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_Y]), MIstart, ci_ptr->dim_steps[DIM_Y] * ci_ptr->dim_lengths[DIM_Y]); miattputstr(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_Z]), MIunits, "mm"); miattputstr(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_X]), MIunits, "mm"); miattputstr(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_Y]), MIunits, "mm"); miattputstr(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, _dimnames[DIM_T]), MIunits, "s"); ncendef(ci_ptr->mnc_fd); } static void copy_frame(struct conversion_info *ci_ptr) { long start[5]; long count[5]; size_t nitems; message(MSG_INFO, "Inserting frame #%d\n", ci_ptr->frame_index); /* Actually read the data from the image file. */ nitems = fread(ci_ptr->frame_buffer, ci_ptr->frame_nbytes, 1, ci_ptr->img_fp); if (nitems != 1) { message(MSG_FATAL, "Read failed with error %d, return %d\n", errno, nitems); exit(-1); } /* Setup the starts and counts for the data block. */ start[DIM_T] = ci_ptr->frame_index - ci_ptr->frame_zero; start[DIM_X] = 0; start[DIM_Y] = 0; start[DIM_Z] = 0; start[DIM_W] = 0; count[DIM_T] = 1; count[DIM_X] = ci_ptr->dim_lengths[DIM_X]; count[DIM_Y] = ci_ptr->dim_lengths[DIM_Y]; count[DIM_Z] = ci_ptr->dim_lengths[DIM_Z]; count[DIM_W] = ci_ptr->dim_lengths[DIM_W]; /* Perform swapping if necessary. */ if (ci_ptr->swap_size != 0) { swap_data(ci_ptr->swap_size, ci_ptr->frame_nvoxels, ci_ptr->frame_buffer); } /* Scale the raw data into the final range. */ scale_data(ci_ptr->minc_type, ci_ptr->frame_nvoxels, ci_ptr->frame_buffer, COMBINED_SCALE_FACTOR(ci_ptr)); /* For now we perform no conversions on the data as it is stored. * This may be worth modifying in the future, to allow storage of * non-floating-point formats from a typical microPET file. */ ncvarput(ci_ptr->mnc_fd, ncvarid(ci_ptr->mnc_fd, MIimage), start, count, ci_ptr->frame_buffer); } minc-2.2.00/conversion/minctoecat/0000755000265600003100000000000012030114723014023 500000000000000minc-2.2.00/conversion/minctoecat/ecat_write.h0000644000265600003100000001305512027132661016255 00000000000000#include #include typedef enum { ECAT6, ECAT7, Interfile } FileFormat; typedef enum { MAT_OK, MAT_READ_ERROR, MAT_WRITE_ERROR, MAT_INVALID_DIRBLK, MAT_ACS_FILE_NOT_FOUND, MAT_INTERFILE_OPEN_ERR, MAT_FILE_TYPE_NOT_MATCH, MAT_READ_FROM_NILFPTR, MAT_NOMHD_FILE_OBJECT, MAT_NIL_SHPTR, MAT_NIL_DATA_PTR, MAT_MATRIX_NOT_FOUND, MAT_UNKNOWN_FILE_TYPE, MAT_ACS_CREATE_ERR, MAT_BAD_ATTRIBUTE, MAT_BAD_FILE_ACCESS_MODE, MAT_INVALID_DIMENSION, MAT_NO_SLICES_FOUND, MAT_INVALID_DATA_TYPE, MAT_INVALID_MBED_POSITION } MatrixErrorCode; typedef enum { NoData, Sinogram, PetImage, AttenCor, Normalization, PolarMap, ByteVolume, PetVolume, ByteProjection, PetProjection, ByteImage, Short3dSinogram, Byte3dSinogram, Norm3d, Float3dSinogram,InterfileImage, NumDataSetTypes } DataSetType; typedef enum { UnknownMatDataType, ByteData, VAX_Ix2, VAX_Ix4, VAX_Rx4, IeeeFloat, SunShort, SunLong, NumMatrixDataTypes, ColorData, BitData } MatrixDataType; MatrixErrorCode matrix_errno; char matrix_errtxt[132]; typedef struct XMAIN_HEAD { char magic_number[14]; char original_file_name[32]; short sw_version; short system_type; short file_type; char serial_number[10]; short align_0; /* 4 byte alignment purpose */ unsigned int scan_start_time; char isotope_code[8]; float isotope_halflife; char radiopharmaceutical[32]; float gantry_tilt; float gantry_rotation; float bed_elevation; float intrinsic_tilt; short wobble_speed; short transm_source_type; float distance_scanned; float transaxial_fov; short angular_compression; short coin_samp_mode; short axial_samp_mode; short align_1; float calibration_factor; short calibration_units; short calibration_units_label; short compression_code; char study_name[12]; char patient_id[16]; char patient_name[32]; char patient_sex[1]; char patient_dexterity[1]; float patient_age; float patient_height; float patient_weight; int patient_birth_date; char physician_name[32]; char operator_name[32]; char study_description[32]; short acquisition_type; short patient_orientation; char facility_name[20]; short num_planes; short num_frames; short num_gates; short num_bed_pos; float init_bed_position; float bed_offset[15]; float plane_separation; short lwr_sctr_thres; short lwr_true_thres; short upr_true_thres; char user_process_code[10]; short acquisition_mode; short align_2; float bin_size; float branching_fraction; unsigned int dose_start_time; float dosage; float well_counter_factor; char data_units[32]; short septa_state; short align_3; } Main_header; typedef struct XIMAGE_SUB { short data_type; short num_dimensions; short x_dimension; short y_dimension; short z_dimension; short align_0; float z_offset; float x_offset; float y_offset; float recon_zoom; float scale_factor; short image_min; short image_max; float x_pixel_size; float y_pixel_size; float z_pixel_size; unsigned int frame_duration; unsigned int frame_start_time; short filter_code; short align_1; float x_resolution; float y_resolution; float z_resolution; float num_r_elements; float num_angles; float z_rotation_angle; float decay_corr_fctr; int processing_code; unsigned int gate_duration; int r_wave_offset; int num_accepted_beats; float filter_cutoff_frequency; float filter_resolution; float filter_ramp_slope; short filter_order; short align_2; float filter_scatter_fraction; float filter_scatter_slope; char annotation[40]; float mt_1_1; float mt_1_2; float mt_1_3; float mt_2_1; float mt_2_2; float mt_2_3; float mt_3_1; float mt_3_2; float mt_3_3; float rfilter_cutoff; float rfilter_resolution; short rfilter_code; short rfilter_order; float zfilter_cutoff; float zfilter_resolution; short zfilter_code; short zfilter_order; float mt_1_4; float mt_2_4; float mt_3_4; short scatter_type; short recon_type; short recon_views; short align_3; } Image_subheader; typedef struct matdirnode { int matnum ; int strtblk ; int endblk ; int matstat ; struct matdirnode *next ; } MatDirNode ; typedef struct matdirlist { int nmats ; MatDirNode *first ; MatDirNode *last ; } MatDirList ; typedef struct matrix_file { char *fname ; Main_header *mhptr ; MatDirList *dirlist ; FILE *fptr ; int acs ; FileFormat file_format; char **interfile_header; } MatrixFile; typedef struct matrixdata { int matnum ; /* matrix number */ MatrixFile *matfile ; /* pointer to parent */ DataSetType mat_type ; /* type of matrix? */ MatrixDataType data_type ; /* type of data */ void * shptr ; /* pointer to sub-header */ void * data_ptr ; /* pointer to data */ int data_size ; /* size of data in bytes */ int xdim; /* dimensions of data */ int ydim; /* y dimension */ int zdim; /* for volumes */ float scale_factor ; /* valid if data is int? */ float pixel_size; /* xdim data spacing (cm) */ float y_size; /* ydim data spacing (cm) */ float z_size; /* zdim data spacing (cm) */ float data_min; /* min value of data */ float data_max; /* max value of data */ float x_origin; /* x origin of data */ float y_origin; /* y origin of data */ float z_origin; /* z origin of data */ } MatrixData ; MatrixFile *matrix_create(const char *fname, Main_header * proto_mhptr); int matrix_write(MatrixFile *mptr, int matnum, MatrixData *data); int matrix_close(MatrixFile *mptr); int mat_numcod(int frame, int plane, int gate, int data, int bed); minc-2.2.00/conversion/minctoecat/machine_indep.h0000644000265600003100000000222512027132661016707 00000000000000#ifndef machine_indep_h #define machine_indep_h #include #if defined(__STDC__) || defined(__cplusplus) #if defined(__cplusplus) extern "C" { #endif void SWAB(const void *from, void *to, int length); int file_data_to_host(char *dptr, int nblks, int dtype); int read_matrix_data( FILE *fptr, int strtblk, int nblks, char *dptr, int dtype); int write_matrix_data( FILE *fptr, int strtblk, int nblks, char *dptr, int dtype); void bufWrite(char* s, char* buf, int* i, int len); void bufWrite_s(short val, char* buf, int* i); void bufWrite_i(int val, char* buf, int* i); void bufWrite_u(unsigned int val, char* buf, int* i); void bufWrite_f(float val, char* buf, int* i); void bufRead(char* s, char* buf, int* i, int len); void bufRead_s(short*, char* buf, int* i); void bufRead_i(int*, char* buf, int* i); void bufRead_u(unsigned int*, char* buf, int* i); void bufRead_f(float*, char* buf, int* i); #if defined(__cplusplus) } #endif /* __cpluplus */ #else /* __STDC__ */ extern void bufWrite(), bufWrite_s(), bufWrite_i(), bufWrite_f(); extern void bufRead(), bufRead_s(), bufRead_i(), bufRead_f(); #endif /* __STDC__ */ #endif /* machine_indep_h */ minc-2.2.00/conversion/minctoecat/minctoecat.man10000644000265600003100000000640612027132661016664 00000000000000.TH "minctoecat" "1" "" "" "" .SH "NAME" minctecat \- convert a minc format file to an Ecat7 format file .SH "SYNOPSIS" \fBminctoecat [] \fR \fBminctoecat [\-help]\fR .SH "DESCRIPTION" \fIminctoecat\fR will convert a 2D image, a 3D volumes or a 4D dynamic volumes written in minc file format to a 2D, 3D or 4D Ecat7 file. Whereas the Ecat7 format has been designed for PET volume issued by Ecat scanners (CTI/SIEMENS \- Knoxville, TN, USA) it reads any minc volume type (static PET, dynamic PET, aMRI, fMRI, labels) natively delivered by any tomograph brand and transform it to a viable Ecat7 file in term of number of dimensions, dimension size, dimension step, orientation, spatial position, voxel values and voxel unit. Furthermore, it tries the best as it can to fill optional Ecat7 header fields from the available minc variables and attributes. By default, it extracts these additional information from common minc variables, namely: patient_variable, study_variable, acquisition_variable. In the case of volumes originally delivered by an Ecat PET scanners, then, other variable are generally available within the minc header: ecat_acquisition_variable, ecat_main and ecat_sub\-header_variable. There, for a such minc volume, the conversion yields a Ecat7 volume almost identical to the original native volume in terms of header fields. The user can alter this behaviour using the ignore\-list options (see the option section). .SH "OPTIONS" Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH "Command specific options" .TP \fI\-ignore_patient_variable:\fR Ignore information from the minc patient variable (MIpatient). .TP \fI\-ignore_study_variable:\fR Ignore information from the minc study variable (MIstudy). .TP \fI\-ignore_acquisition_variable:\fR Ignore information from the minc acquisition variable (MIacquisition). .TP \fI\-ignore_ecat_accquisition_variable:\fR Ignore information from the minc ecat acquisition variable (MIecat_acquisition). .TP \fI\-ignore_ecat_main_variable:\fR Ignore information from the minc ecat\-mainheader variable (MIecat\-main). .TP \fI\-ignore_ecat_subheader_variable:\fR Ignore information from the minc ecat\-subheader variable (MIecat\-subheader). .TP \fI\-no_decay_corr_fctr:\fR do not regenerate the decay correction factors employed as part as the reconstruction of the original PET volume. The correction factors is a field in the ecat sub\-headers which can be used by processing programs. By default, if the volume is a PET volume ,those factors are regenerated. This option has no interest in the case of non PET data. .TP \fI\-label:\fR Treats voxel as integer values instead of floating point values. In this case, the scale factors and the calibration factors are both set to unity. This option is particularly useful when the input minc files is a volume of labels. .SH "General options" .TP \fI\-help:\fR Print summary of command\-line options and abort .TP \fI\-version:\fR Print the program's version and abort .SH "KNOWN BUGS" No bug listed so far :=) .SH "SEE ALSO" ecattominc(1), rawtominc(1), minctoraw(1), dicomtominc(1) .SH "AUTHOR" Anthonin Reilhac (anthonin.reilhac@cermep.fr) .SH "COPYRIGHTS" Copyrights 2005 by Anthonin Reilhac minc-2.2.00/conversion/minctoecat/minctoecat.c0000644000265600003100000011001112027132661016236 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minctoecat @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : error status @DESCRIPTION: Converts a minc format file to a CTI ECAT file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 31, 2005 (Anthonin Reilhac) @MODIFIED : @COPYRIGHT : Copyright 2005 Anthonin Reilhac, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include "ecat_write.h" #define ShortMax 32767 #define BECQUEREL_PER_NCURIE 37 typedef enum MODALITY { UNKNOWN_MODALITY, PET, MRI, NUM_MODALITY } modality; typedef enum DATA_UNIT { UNKNOWN_DATA_UNIT, LABEL, NCIPERCC } data_unit; typedef struct MINC_INFO { int dim; long x_size; long y_size; long z_size; long time_length; double x_step; double y_step; double z_step; int x_start_flag; int y_start_flag; int z_start_flag; double x_start; double y_start; double z_start; double *time_points; double *time_widths; data_unit dunit; modality mod; float isotope_halflife; } minc_info; /*Fuction declarations*/ double decay_correction(double scan_time, double measure_time, double start_time, double half_life); minc_info *get_minc_info(char *file); void free_minc_info(minc_info *mi); void get_patient_info(char *file, Main_header *mh); void get_study_info(char *file, Main_header *mh); void get_acquisition_info(char *file, Main_header *mh); void get_ecat_acquisition_info(char *file, Main_header *mh); void get_ecat_main_header_info(char *file, Main_header *mh); void get_ecat_subheader_info(char *file, Image_subheader *sh); Main_header * init_main_header(char *file, minc_info *mi); Image_subheader * init_image_subheader(char *file, minc_info *mi, Main_header *mh); void write_ecat_frame(MatrixFile *mf, Image_subheader *sh, short *ptr,int fr, float min, float max); void usage_error(char *progname); int main ( int argc, char **argv) { /* Variables for arguments */ static int include_patient_info = TRUE; static int include_study_info = TRUE; static int include_acquisition_info = TRUE; static int include_ecat_acquisition_info = TRUE; static int include_ecat_main_info = TRUE; static int include_ecat_subheader_info = TRUE; static int do_decay_corr_factor = TRUE; static int label_data = FALSE; /* Argument option table */ static ArgvInfo argTable[] = { {"-ignore_patient_variable", ARGV_CONSTANT, (char *) FALSE, (char *) &include_patient_info,"Ignore informations from the minc patient variable."}, {"-ignore_study_variable", ARGV_CONSTANT, (char *) FALSE, (char *) &include_study_info,"Ignore informations from the minc study variable."}, {"-ignore_acquisition_variable", ARGV_CONSTANT, (char *) FALSE, (char *) &include_acquisition_info,"Ignore informations from the minc acquisition variable."}, {"-ignore_ecat_acquisition_variable", ARGV_CONSTANT, (char *) FALSE, (char *) &include_ecat_acquisition_info,"Ignore informations from the minc ecat_acquisition variable."}, {"-ignore_ecat_main", ARGV_CONSTANT, (char *) FALSE, (char *) &include_ecat_main_info,"Ignore informations from the minc ecat-main variable."}, {"-ignore_ecat_subheader_variable", ARGV_CONSTANT, (char *) FALSE, (char *) &include_ecat_subheader_info,"Ignore informations from the minc ecat-subhdr variable."}, {"-no_decay_corr_fctr", ARGV_CONSTANT, (char *) FALSE, (char *) &do_decay_corr_factor,"Do not compute the decay correction factors"}, {"-label", ARGV_CONSTANT, (char *) TRUE, (char *) &label_data,"Voxel values are treated as integers, scale and calibration factors are set to unity"}, {NULL, ARGV_END, NULL, NULL, NULL} }; /*other variables*/ char *pname; /*name of the present command ->argv[0]*/ char *minc_file_name = NULL; /*name of the input file (minc format)*/ char *ecat_file_name = NULL; /*name of the output file (to be created into the ecat format*/ minc_info *mi = NULL; Volume volume; short int *ecat_short_ptr = NULL; float ecat_scale_factor = 1; progress_struct progress; STRING DimOrder[MAX_DIMENSIONS]; MatrixFile *out_matrix_file = NULL; Main_header *out_main_header = NULL; Image_subheader *out_image_subheader = NULL; int fr; int incre = 0; int x_ind, y_ind, z_ind; double cal_factor; /* Check arguments */ pname = argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || (argc != 3)) { usage_error(pname); } /* Get file names */ minc_file_name = argv[1]; ecat_file_name = argv[2]; /*getting informations about the dimensions from the minc file*/ if((mi = get_minc_info(minc_file_name)) == NULL) { fprintf(stderr, "Can not get informations from %s.\n", minc_file_name); return (1); } /*checking the number of dimension*/ if((mi->dim != 3) && (mi->dim != 4)) { (void)fprintf(stderr, "input file has not a valid number of dimensions (%d), should be either 3 (static file) or 4 (dynamic file)", mi->dim); return (-1); } /*************************************************************************************** * filling the ecat header fields with the available informations * ***************************************************************************************/ /*MAIN HEADER: filling compulsory fields*/ if((out_main_header = init_main_header(minc_file_name, mi)) == NULL) { fprintf(stderr, "Can not initilize the ecat main header.\n"); return (1); } /*additional informations if available and requested*/ /*getting patient informations from the MIpatient variable*/ if(include_patient_info) get_patient_info(minc_file_name, out_main_header); /*getting study information from the MIstudy variable*/ if(include_study_info) get_study_info(minc_file_name, out_main_header); /*getting acquisition information from the MIacquisition variable*/ if(include_acquisition_info) get_acquisition_info(minc_file_name, out_main_header); /*getting acquisition information from the ecat_acquisition variable*/ if(include_ecat_acquisition_info) get_ecat_acquisition_info(minc_file_name, out_main_header); /*getting ecat main header informations from the ecat-main variable*/ if(include_ecat_main_info) get_ecat_main_header_info(minc_file_name, out_main_header); /*SUBHEADER TEMPLATE: filling compulsory fields*/ if((out_image_subheader = init_image_subheader(minc_file_name, mi, out_main_header)) == NULL) { fprintf(stderr, "Can not initialize the ecat image subheader.\n"); return (1); } /*getting additionnal informations from the ecat-subhdr variable*/ if(include_ecat_subheader_info) get_ecat_subheader_info(minc_file_name, out_image_subheader); /*writting the main header*/ if((out_matrix_file = matrix_create(ecat_file_name, out_main_header)) == NULL) { fprintf(stderr, "cannot create %s \n", ecat_file_name); return(-1); } /*extracting the mincvolume in the order time, X, Y, Z*/ if(mi->dim == 4) { DimOrder[0] = MItime; DimOrder[1] = MIzspace; DimOrder[2] = MIyspace; DimOrder[3] = MIxspace; } else { DimOrder[0] = MIzspace; DimOrder[1] = MIyspace; DimOrder[2] = MIxspace; } /*input the volume*/ if(input_volume(minc_file_name, mi->dim, DimOrder, NC_UNSPECIFIED, FALSE, 1, 1, TRUE, &volume, (minc_input_options *) NULL) != OK) return (1); /*initializing the progress report*/ initialize_progress_report(&progress, FALSE, mi->time_length, "Converting data"); cal_factor = (mi->dunit == NCIPERCC)?BECQUEREL_PER_NCURIE:1; cal_factor /= out_main_header->calibration_factor; /*getting the values*/ for(fr = 0; fr < ((mi->time_length)?mi->time_length:1); fr++) { float max_val = 0, min_val = 0; int vx, vy, vz; Real value; if((ecat_short_ptr = (short int *)calloc((mi->x_size) * (mi->y_size) * (mi->z_size), sizeof(short int))) == NULL) { fprintf(stderr, "allocation error\n"); return 1; } for(vz = 0; vz < mi->z_size; vz++) for(vy = 0; vy < mi->y_size; vy++) for(vx = 0; vx < mi->x_size; vx++) { value = ((mi->time_length)?get_volume_real_value(volume, fr, vz, vy, vx, 0):get_volume_real_value(volume, vz, vy, vx, 0,0)) * cal_factor; if(value > max_val) max_val = value; if(value < min_val) min_val = value; } if((mi->dunit != LABEL) && (!label_data)) ecat_scale_factor = ((max_val > fabs(min_val))?max_val:fabs(min_val))/ShortMax; for(vz = 0; vz < mi->z_size; vz++) { for(vy = 0; vy < mi->y_size; vy++) { for(vx = 0; vx < mi->x_size; vx++) { value = ((mi->time_length)?get_volume_real_value(volume, fr, vz, vy, vx, 0):get_volume_real_value(volume, vz, vy, vx, 0,0)); x_ind = ((mi->x_step > 0)?mi->x_size - 1 - vx:vx); y_ind = ((mi->y_step > 0)?mi->y_size - 1 - vy:vy); z_ind = ((mi->z_step > 0)?mi->z_size - 1 - vz:vz); ecat_short_ptr[IJK(z_ind, y_ind, x_ind, mi->y_size, mi->x_size)] = (short int)ROUND(value * cal_factor/(ecat_scale_factor)); } } } /*filling image subheader*/ if(mi->dim == 4) { out_image_subheader->frame_start_time = (unsigned int)(mi->time_points[fr] * 1000); out_image_subheader->frame_duration = (unsigned int)(mi->time_widths[fr] * 1000); } if((mi->dunit == NCIPERCC) && (do_decay_corr_factor)) out_image_subheader->decay_corr_fctr = decay_correction(mi->time_points[fr],mi->time_widths[fr] , 0.0, mi->isotope_halflife); out_image_subheader->scale_factor = ecat_scale_factor; write_ecat_frame(out_matrix_file, out_image_subheader, ecat_short_ptr, fr, min_val, max_val); free(ecat_short_ptr); ecat_short_ptr = NULL; update_progress_report(&progress, incre); incre++; } free_minc_info(mi); matrix_close(out_matrix_file); free(out_main_header); free(out_image_subheader); terminate_progress_report(&progress); return (0); } double decay_correction(double scan_time, double measure_time, double start_time, double half_life) { double mean_life; double measure_correction; double decay; /* Check for negative half_life and calculate mean life */ if (half_life <= 0.0) return 1.0; mean_life = half_life/ log(2.0); /* Normalize scan time and measure_time */ scan_time = (scan_time - start_time) / mean_life; measure_time /= mean_life; /* Calculate correction for decay over measuring time (assuming a constant activity). Check for possible rounding errors. */ if ((measure_time*measure_time/2.0) < DBL_EPSILON) { measure_correction = 1.0 - measure_time/2.0; } else { measure_correction = (1.0 - exp(-measure_time)) / fabs(measure_time); } /* Calculate decay */ decay = exp(-scan_time) * measure_correction; if (decay<=0.0) decay = DBL_MAX; else decay = 1.0/decay; return decay; } minc_info *get_minc_info(char *file) { int minc_fd; /*minc file descriptor*/ minc_info *mi = NULL; /*minc info structures*/ int var_id; int num_att; char attname[NC_MAX_NAME+1]; char buff[NC_MAX_NAME+1]; int i; /* we first open the netcdf file*/ minc_fd = miopen(file, NC_NOWRITE); if((mi = (minc_info *)calloc(1, sizeof(minc_info))) == NULL) return NULL; /*initlaization*/ mi->time_length = 0; mi->mod = UNKNOWN_MODALITY; mi->dunit = UNKNOWN_DATA_UNIT; mi->x_start_flag = 0; mi->y_start_flag = 0; mi->z_start_flag = 0; /* first we check out the number of dimension. we suppose that the time dimension is the 4th*/ ncinquire(minc_fd, &(mi->dim), NULL, NULL, NULL); /*getting infos about the x, y and and z sizes and width*/ ncdiminq(minc_fd, ncdimid(minc_fd, MIxspace), NULL, &(mi->x_size)); ncdiminq(minc_fd, ncdimid(minc_fd, MIyspace), NULL, &(mi->y_size)); ncdiminq(minc_fd, ncdimid(minc_fd, MIzspace), NULL, &(mi->z_size)); /*getting information about each dimensions*/ /*MIxspace*/ var_id = ncvarid(minc_fd, MIxspace); ncvarinq(minc_fd,var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { ncattname(minc_fd,var_id,i,attname); if(strcmp(MIstart, attname) == 0) { mi->x_start_flag = 1; miattget1(minc_fd,var_id, MIstart, NC_DOUBLE, &(mi->x_start)); } if(strcmp(MIstep, attname) == 0) miattget1(minc_fd,var_id, MIstep, NC_DOUBLE, &(mi->x_step)); } /*MIyspace*/ var_id = ncvarid(minc_fd, MIyspace); ncvarinq(minc_fd,var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { ncattname(minc_fd,var_id,i,attname); if(strcmp(MIstart, attname) == 0) { mi->y_start_flag = 1; miattget1(minc_fd,var_id, MIstart, NC_DOUBLE, &(mi->y_start)); } if(strcmp(MIstep, attname) == 0) miattget1(minc_fd,var_id, MIstep, NC_DOUBLE, &(mi->y_step)); } /*MIzspace*/ var_id = ncvarid(minc_fd, MIzspace); ncvarinq(minc_fd,var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { ncattname(minc_fd,var_id,i,attname); if(strcmp(MIstart, attname) == 0) { mi->z_start_flag = 1; miattget1(minc_fd,var_id, MIstart, NC_DOUBLE, &(mi->z_start)); } if(strcmp(MIstep, attname) == 0) miattget1(minc_fd,var_id, MIstep, NC_DOUBLE, &(mi->z_step)); } /* if it is a dynamic file, then we ask for the number of frames, the frame durations and start time*/ if(mi->dim == 4){ long start_time_vector[1]; long count_time_vector[1]; var_id = ncdimid(minc_fd, MItime); ncdiminq(minc_fd, var_id, NULL, &(mi->time_length)); if((mi->time_points = (double *) calloc(mi->time_length, sizeof(double))) == NULL) return NULL; if((mi->time_widths = (double *) calloc(mi->time_length, sizeof(double))) == NULL) return NULL; start_time_vector[0] = 0; count_time_vector[0] = mi->time_length; mivarget(minc_fd, var_id, start_time_vector, count_time_vector, NC_DOUBLE, MI_SIGNED, mi->time_points); mivarget(minc_fd, ncvarid(minc_fd, MItime_width), start_time_vector, count_time_vector, NC_DOUBLE, MI_SIGNED, mi->time_widths); } /*defining the modality*/ if(mivar_exists(minc_fd, MIstudy)) { var_id = ncvarid(minc_fd, MIstudy); ncvarinq(minc_fd, var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { ncattname(minc_fd,var_id,i,attname); if(strcmp(MImodality, attname) == 0) { miattgetstr(minc_fd, var_id, MImodality, NC_MAX_NAME, buff); if(strcmp(buff, MI_PET) == 0) mi->mod = PET; if(strcmp(buff, MI_MRI) == 0) mi->mod = MRI; if(strcmp(buff, MI_LABEL) == 0) mi->dunit = LABEL; } } } if(mivar_exists(minc_fd, MIimagemin)) { var_id = ncvarid(minc_fd, MIimagemin); ncvarinq(minc_fd, var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { ncattname(minc_fd,var_id,i,attname); if(strcmp(MIunits, attname) == 0) { miattgetstr(minc_fd, var_id, MIunits, NC_MAX_NAME, buff); if(strcmp(buff, "nCi/cc") == 0) mi->dunit = NCIPERCC; } } } /*getting isotope halflife if available*/ if(mivar_exists(minc_fd, MIacquisition)) { var_id = ncvarid(minc_fd, MIacquisition); ncvarinq(minc_fd, var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { ncattname(minc_fd,var_id,i,attname); if(strcmp(MIradionuclide_halflife, attname) == 0) miattget1(minc_fd, var_id, MIradionuclide_halflife, NC_FLOAT, &(mi->isotope_halflife)); } } miclose(minc_fd); return mi; } void free_minc_info(minc_info *mi) { if(mi->time_points != NULL) free(mi->time_points); if(mi->time_widths != NULL) free(mi->time_widths); } void get_patient_info(char *file, Main_header *mh) { int minc_fd; /*minc file descriptor*/ /* we first open the netcdf file*/ minc_fd = miopen(file, NC_NOWRITE); if(mivar_exists(minc_fd, MIpatient)) { int var_id; int num_att; int i; var_id = ncvarid(minc_fd, MIpatient); ncvarinq(minc_fd, var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { char attname[NC_MAX_NAME+1]; char buffer_val[NC_MAX_NAME+1]; ncattname(minc_fd,var_id,i,attname); if(strcmp(MIfull_name, attname) == 0) miattgetstr(minc_fd, var_id, MIfull_name, 32, mh->patient_name); if(strcmp(MIage, attname) == 0) miattget1(minc_fd, var_id, MIage, NC_FLOAT, &(mh->patient_age)); if(strcmp(MIweight, attname) == 0) miattget1(minc_fd, var_id, MIweight, NC_FLOAT, &(mh->patient_weight)); if(strcmp(MIsize, attname) == 0) miattget1(minc_fd, var_id, MIsize, NC_FLOAT, &(mh->patient_height)); if(strcmp(MIsex, attname) == 0) { miattgetstr(minc_fd, var_id, MIsex, NC_MAX_NAME+1, buffer_val); if(strcmp(buffer_val, MI_MALE) == 0) mh->patient_sex[0] = 'M'; if(strcmp(buffer_val, MI_FEMALE) == 0) mh->patient_sex[0] = 'F'; } if(strcmp(MIidentification, attname) == 0) miattgetstr(minc_fd, var_id, MIidentification, 16, mh->patient_id); /*I don't kown how to deal with the patient birth date yet in minc, it is a string, in ecat a int ... I guess this is not important as long as we have the age of the patient Might be filled below if the ecat-header variable exists */ } } miclose(minc_fd); } void get_study_info(char *file, Main_header *mh) { int minc_fd; /*minc file descriptor*/ /* we first open the netcdf file*/ minc_fd = miopen(file, NC_NOWRITE); if(mivar_exists(minc_fd, MIstudy)) { int var_id; int i; struct tm scan_time; int num_att; var_id = ncvarid(minc_fd, MIstudy); ncvarinq(minc_fd, var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { char attname[NC_MAX_NAME+1]; ncattname(minc_fd,var_id,i,attname); if(strcmp(MIstart_year, attname) == 0) { miattget1(minc_fd, var_id, MIstart_year, NC_INT, &scan_time.tm_year); scan_time.tm_year -= 1900; } if(strcmp(MIstart_month, attname) == 0) { miattget1(minc_fd, var_id, MIstart_month, NC_INT, &scan_time.tm_mon); scan_time.tm_mon--; } if(strcmp(MIstart_day, attname) == 0) miattget1(minc_fd, var_id, MIstart_day, NC_INT, &scan_time.tm_mday); if(strcmp(MIstart_hour, attname) == 0) miattget1(minc_fd, var_id, MIstart_hour, NC_INT, &scan_time.tm_hour); if(strcmp(MIstart_minute, attname) == 0) miattget1(minc_fd, var_id, MIstart_minute, NC_INT, &scan_time.tm_min); if(strcmp(MIstart_seconds, attname) == 0) miattget1(minc_fd, var_id, MIstart_seconds, NC_INT, &scan_time.tm_sec); if(strcmp(MIidentification, attname) == 0) miattgetstr(minc_fd, var_id, MIidentification, 16, mh->patient_id); if(strcmp(MIstudy_id, attname) == 0) miattgetstr(minc_fd, var_id, MIstudy_id, 12, mh->study_name); if(strcmp(MIreferring_physician, attname) == 0) miattgetstr(minc_fd, var_id, MIreferring_physician, 32, mh->physician_name); if(strcmp(MIoperator, attname) == 0) miattgetstr(minc_fd, var_id, MIoperator, 32, mh->operator_name); } mh->scan_start_time = mktime(&scan_time); } miclose(minc_fd); } void get_acquisition_info(char *file, Main_header *mh) { int minc_fd; /*minc file descriptor*/ /* we first open the netcdf file*/ minc_fd = miopen(file, NC_NOWRITE); if(mivar_exists(minc_fd, MIacquisition)) { int var_id; int num_att; int i; struct tm injection_time; var_id = ncvarid(minc_fd, MIacquisition); ncvarinq(minc_fd, var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { char attname[NC_MAX_NAME+1]; ncattname(minc_fd,var_id,i,attname); if(strcmp(MIradionuclide, attname) == 0) miattgetstr(minc_fd, var_id, MIradionuclide, 8, mh->isotope_code); if(strcmp(MIradionuclide_halflife, attname) == 0) miattget1(minc_fd, var_id, MIradionuclide_halflife, NC_FLOAT, &(mh->isotope_halflife)); if(strcmp(MItracer, attname) == 0) miattgetstr(minc_fd, var_id, MItracer, 32, mh->radiopharmaceutical); if(strcmp(MIinjection_year, attname) == 0) { miattget1(minc_fd, var_id, MIinjection_year, NC_INT, &injection_time.tm_year); injection_time.tm_year -= 1900; } if(strcmp(MIinjection_month, attname) == 0) { miattget1(minc_fd, var_id, MIinjection_month, NC_INT, &injection_time.tm_mon); injection_time.tm_mon--; } if(strcmp(MIinjection_day, attname) == 0) miattget1(minc_fd, var_id, MIinjection_day, NC_INT, &injection_time.tm_mday); if(strcmp(MIinjection_hour, attname) == 0) miattget1(minc_fd, var_id, MIinjection_hour, NC_INT, &injection_time.tm_hour); if(strcmp(MIinjection_minute, attname) == 0) miattget1(minc_fd, var_id, MIinjection_minute, NC_INT, &injection_time.tm_min); if(strcmp(MIinjection_seconds, attname) == 0) miattget1(minc_fd, var_id, MIinjection_seconds, NC_INT, &injection_time.tm_sec); if(strcmp(MIinjection_dose, attname) == 0) miattget1(minc_fd, var_id, MIinjection_dose, NC_FLOAT, &(mh->dosage)); if(strcmp(MIdose_units, attname) == 0) miattgetstr(minc_fd, var_id, MIdose_units, 32, mh->data_units); } mh->dose_start_time = mktime(&injection_time); } miclose(minc_fd); } void get_ecat_acquisition_info(char *file, Main_header *mh) { int minc_fd; /*minc file descriptor*/ /* we first open the netcdf file*/ minc_fd = miopen(file, NC_NOWRITE); if(mivar_exists(minc_fd, "ecat_acquisition")) { int var_id; int num_att; int i; char attname[NC_MAX_NAME+1]; var_id = ncvarid(minc_fd, "ecat_acquisition"); ncvarinq(minc_fd, var_id, NULL, NULL, NULL, NULL, &num_att); for(i = 0; i < num_att; i++) { ncattname(minc_fd,var_id,i,attname); if(strcmp("septa_retracted", attname) == 0) { char buff[NC_MAX_NAME+1]; miattgetstr(minc_fd, var_id, "septa_retracted", NC_MAX_NAME+1, buff); if(strcmp(buff, MI_TRUE) == 0) mh->septa_state = 1; if(strcmp(buff, MI_FALSE) == 0) mh->septa_state = 0; } } } miclose(minc_fd); } void get_ecat_main_header_info(char *file, Main_header *mh) { int minc_fd; /* we first open the netcdf file*/ minc_fd = miopen(file, NC_NOWRITE); if(mivar_exists(minc_fd, "ecat-main")) { int var_id; char buffer[NC_MAX_NAME+1]; var_id = ncvarid(minc_fd, "ecat-main"); miattgetstr(minc_fd, var_id, "Magic_Number", 14, mh->magic_number); miattgetstr(minc_fd, var_id, "Original_Filename", 32, mh->original_file_name); miattgetstr(minc_fd, var_id, "System_Type", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->system_type)); miattgetstr(minc_fd, var_id, "Serial_Number", 10, mh->serial_number); miattgetstr(minc_fd, var_id, "Scan_Start_Time", sizeof(buffer), buffer); sscanf(buffer, "%u", &(mh->scan_start_time)); miattgetstr(minc_fd, var_id, "Isotope_Name", 8, mh->isotope_code); miattgetstr(minc_fd, var_id, "Isotope_Halflife", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->isotope_halflife)); miattgetstr(minc_fd, var_id, "Radiopharmaceutical", 32, mh->radiopharmaceutical); miattgetstr(minc_fd, var_id, "Gantry_Tilt", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->gantry_tilt)); miattgetstr(minc_fd, var_id, "Gantry_Rotation", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->gantry_rotation)); miattgetstr(minc_fd, var_id, "Bed_Elevation", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->bed_elevation)); miattgetstr(minc_fd, var_id, "Intrinsic_Tilt", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->intrinsic_tilt)); miattgetstr(minc_fd, var_id, "Wobble_Speed", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->wobble_speed)); miattgetstr(minc_fd, var_id, "Transm_Source_Type", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->transm_source_type)); miattgetstr(minc_fd, var_id, "Distance_Scanned", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->distance_scanned)); miattgetstr(minc_fd, var_id, "Transaxial_Fov", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->transaxial_fov)); miattgetstr(minc_fd, var_id, "Angular_Compression", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->angular_compression)); miattgetstr(minc_fd, var_id, "Coin_Samp_Mode", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->coin_samp_mode)); miattgetstr(minc_fd, var_id, "Axial_Samp_Mode", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->axial_samp_mode)); miattgetstr(minc_fd, var_id, "Calibration_Factor", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->calibration_factor)); miattgetstr(minc_fd, var_id, "Study_Type", 12, mh->study_name); miattgetstr(minc_fd, var_id, "Patient_Id", 16, mh->patient_id); miattgetstr(minc_fd, var_id, "Patient_Name", 32, mh->patient_name); miattgetstr(minc_fd, var_id, "Patient_Sex", sizeof(buffer), buffer); sscanf(buffer, "%c", mh->patient_sex); miattgetstr(minc_fd, var_id, "Patient_Dexterity", sizeof(buffer), buffer); sscanf(buffer, "%c", mh->patient_dexterity); miattgetstr(minc_fd, var_id, "Patient_Age", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->patient_age)); miattgetstr(minc_fd, var_id, "Patient_Height", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->patient_height)); miattgetstr(minc_fd, var_id, "Patient_Weight", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->patient_weight)); miattgetstr(minc_fd, var_id, "Patient_Birth_Date", sizeof(buffer), buffer); sscanf(buffer, "%d", &(mh->patient_birth_date)); miattgetstr(minc_fd, var_id, "Physician_Name", 32, mh->physician_name); miattgetstr(minc_fd, var_id, "Operator_Name", 32, mh->operator_name); miattgetstr(minc_fd, var_id, "Study_Description", 32, mh->study_description); /*bugg -> in minc lib, acquisition should be replaced by acquisition*/ miattgetstr(minc_fd, var_id, "Acquision_Type", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->acquisition_type)); miattgetstr(minc_fd, var_id, "Patient_Orientation", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->patient_orientation)); miattgetstr(minc_fd, var_id, "Facility_Name", 20, mh->facility_name); miattgetstr(minc_fd, var_id, "Lwr_Sctr_Thres", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->lwr_sctr_thres)); miattgetstr(minc_fd, var_id, "Lwr_True_Thres", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->lwr_true_thres)); miattgetstr(minc_fd, var_id, "Upr_True_Thres", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->upr_true_thres)); miattgetstr(minc_fd, var_id, "User_Process_Code", 10, mh->user_process_code); miattgetstr(minc_fd, var_id, "Acquisition_Mode", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->acquisition_mode)); miattgetstr(minc_fd, var_id, "Bin_Size", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->bin_size)); miattgetstr(minc_fd, var_id, "Branching_Fraction", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->branching_fraction)); miattgetstr(minc_fd, var_id, "Dose_Start_Time", sizeof(buffer), buffer); sscanf(buffer, "%u", &(mh->dose_start_time)); miattgetstr(minc_fd, var_id, "Dosage", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->dosage)); miattgetstr(minc_fd, var_id, "Well_Counter_Corr_Factor", sizeof(buffer), buffer); sscanf(buffer, "%f", &(mh->well_counter_factor)); miattgetstr(minc_fd, var_id, "Data_Units", 32, mh->data_units); miattgetstr(minc_fd, var_id, "Septa_State", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(mh->septa_state)); } miclose(minc_fd); } void get_ecat_subheader_info(char *file, Image_subheader *sh) { int minc_fd; /*minc file descriptor*/ /* we first open the netcdf file*/ minc_fd = miopen(file, NC_NOWRITE); if(mivar_exists(minc_fd, "ecat-subhdr")) { int var_id; char buffer[NC_MAX_NAME]; var_id = ncvarid(minc_fd, "ecat-subhdr"); miattgetstr(minc_fd, var_id, "Recon_Zoom", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->recon_zoom)); miattgetstr(minc_fd, var_id, "Filter_Code", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(sh->filter_code)); miattgetstr(minc_fd, var_id, "X_Resolution", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->x_resolution)); miattgetstr(minc_fd, var_id, "Y_Resolution", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->y_resolution)); miattgetstr(minc_fd, var_id, "Z_Resolution", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->z_resolution)); miattgetstr(minc_fd, var_id, "X_Rotation_Angle", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->num_r_elements)); miattgetstr(minc_fd, var_id, "Y_Rotation_Angle", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->num_angles)); miattgetstr(minc_fd, var_id, "Z_Rotation_Angle", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->z_rotation_angle)); miattgetstr(minc_fd, var_id, "Decay_Corr_Fctr", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->decay_corr_fctr)); miattgetstr(minc_fd, var_id, "Corrections_Applied", sizeof(buffer), buffer); sscanf(buffer, "%d", &(sh->processing_code)); miattgetstr(minc_fd, var_id, "Gate_Duration", sizeof(buffer), buffer); sscanf(buffer, "%u", &(sh->gate_duration)); miattgetstr(minc_fd, var_id, "R_Wave_Offset", sizeof(buffer), buffer); sscanf(buffer, "%d", &(sh->r_wave_offset)); miattgetstr(minc_fd, var_id, "Num_Accepted_Beats", sizeof(buffer), buffer); sscanf(buffer, "%d", &(sh->num_accepted_beats)); miattgetstr(minc_fd, var_id, "Filter_Cutoff_Frequency", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->filter_cutoff_frequency)); miattgetstr(minc_fd, var_id, "Filter_Dc_Component", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->filter_resolution)); miattgetstr(minc_fd, var_id, "Filter_Ramp_Slope", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->filter_ramp_slope)); miattgetstr(minc_fd, var_id, "Filter_Order", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(sh->filter_order)); miattgetstr(minc_fd, var_id, "Annotation", 40, sh->annotation); miattgetstr(minc_fd, var_id, "Da_X_Rotation_Angle", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_1_1)); miattgetstr(minc_fd, var_id, "Da_Y_Rotation_Angle", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_1_2)); miattgetstr(minc_fd, var_id, "Da_Z_Rotation_Angle", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_1_3)); miattgetstr(minc_fd, var_id, "Da_X_Translation", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_2_1)); miattgetstr(minc_fd, var_id, "Da_Y_Translation", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_2_2)); miattgetstr(minc_fd, var_id, "Da_Z_Translation", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_2_3)); miattgetstr(minc_fd, var_id, "Da_X_Scale_Factor", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_3_1)); miattgetstr(minc_fd, var_id, "Da_Y_Scale_Factor", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_3_2)); miattgetstr(minc_fd, var_id, "Da_Z_Scale_Factor", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->mt_3_3)); miattgetstr(minc_fd, var_id, "Rfilter_Cutoff", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->rfilter_cutoff)); miattgetstr(minc_fd, var_id, "Rfilter_Resolution", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->rfilter_resolution)); miattgetstr(minc_fd, var_id, "Rfilter_Code", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(sh->rfilter_code)); miattgetstr(minc_fd, var_id, "Rfilter_Order", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(sh->rfilter_order)); miattgetstr(minc_fd, var_id, "Zfilter_Cutoff", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->zfilter_cutoff)); miattgetstr(minc_fd, var_id, "Zfilter_Resolution", sizeof(buffer), buffer); sscanf(buffer, "%f", &(sh->zfilter_resolution)); miattgetstr(minc_fd, var_id, "Zfilter_Code", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(sh->zfilter_code)); miattgetstr(minc_fd, var_id, "Zfilter_Order", sizeof(buffer), buffer); sscanf(buffer, "%hd", &(sh->zfilter_order)); } miclose(minc_fd); } Main_header * init_main_header(char *file, minc_info *mi) { Main_header *mh = NULL; if((mh = (Main_header *)calloc(1, sizeof(Main_header))) == NULL) return NULL; /**************************************************************************** * first, we filled the compulsory fields * ****************************************************************************/ /*software version 7*/ mh->sw_version = 72; /*well ecat is a format for PET data, so MRI data in the minc format will have the PetVolume flag in ecat ....*/ mh->file_type = PetVolume; mh->num_planes = mi->z_size; mh->num_frames = (mi->dim == 4)?mi->time_length:1; mh->num_gates = 1; /*not handled for now*/ mh->num_bed_pos = 0; /*not handles for now*/ /*inital bed position, I do the backward calculation of ecattominc - !! MIstart may not exist*/ mh->init_bed_position = -mi->z_start/10.; mh->init_bed_position = (mi->z_step < 0)?-mi->z_start/10.:-(mi->z_step * (mi->z_size - 1) + mi->z_start)/10.; mh->bed_offset[0] = 0; /*for now, the distance_scanned is equal to the number of axial planes times the plane width*/ mh->distance_scanned = fabs(mi->z_step) * (mi->z_size + 1)/10.0; /*cm*/ mh->plane_separation = fabs(mi->z_step)/10.; mh->calibration_factor = 1; /*forced*/ mh->calibration_units = 2; /*2 = processed, by default*/ mh->calibration_units_label = 0; /*by default*/ if(mi->dunit == NCIPERCC) { mh->calibration_units = 1; mh->calibration_units_label = 1; } mh->patient_sex[0] = 'U'; /*for now unknown*/ mh->patient_dexterity[0] = 'U'; /*unknown for now*/; return mh; } Image_subheader * init_image_subheader(char *file, minc_info *mi, Main_header *mh) { Image_subheader *sh = NULL; if((sh = (Image_subheader *)calloc(1, sizeof(Image_subheader))) == NULL) return NULL; sh->data_type = SunShort; /*forced*/ sh->num_dimensions = 3; /*forced*/ sh->x_dimension = mi->x_size; sh->y_dimension = mi->y_size; sh->z_dimension = mi->z_size; sh->x_pixel_size = fabs(mi->x_step)/10.0; /*in cm*/ sh->y_pixel_size = fabs(mi->y_step)/10.0; sh->z_pixel_size = fabs(mi->z_step)/10.0; sh->x_offset = 0; if(mi->x_start_flag) sh->x_offset = -(mi->x_start + (mi->x_size - 1.0)/2.0 * mi->x_step)/10.; sh->y_offset = 0; if(mi->y_start_flag) sh->y_offset = (mi->y_start + (mi->y_size - 1.0)/2.0 * mi->y_step)/10.; sh->z_offset = 0; return sh; } void write_ecat_frame(MatrixFile *mf, Image_subheader *sh, short *ptr,int fr, float min, float max) { MatrixData md = {0}; md.matfile = mf; md.mat_type = mf->mhptr->file_type; md.data_type = sh->data_type; md.shptr = sh; md.data_ptr = ptr; md.xdim = sh->x_dimension; md.ydim = sh->y_dimension; md.zdim = sh->z_dimension; md.scale_factor = sh->scale_factor; md.pixel_size = sh->x_pixel_size; md.y_size = sh->y_pixel_size; md.z_size = sh->z_pixel_size; md.data_min = min; md.data_max = max; md.data_size = (sh->x_dimension) * (sh->y_dimension) * (sh->z_dimension) * sizeof(short int); matrix_write(mf,mat_numcod(fr + 1, 1, 1, 0, 0) , &md); } void usage_error(char *progname) { (void) fprintf(stderr, "\nUsage: %s [] \n", progname); (void) fprintf(stderr, " %s [-help]\n\n", progname); exit(EXIT_FAILURE); } minc-2.2.00/conversion/minctoecat/ecat_write.c0000644000265600003100000004617112027132661016255 00000000000000#include "ecat_write.h" #include "machine_indep.h" #include "string.h" #define MatBLKSIZE 512 #define MatFirstDirBlk 2 #define NameLen 32 #define IDLen 16 #define OK 0 #define ERROR -1 #define V7 70 char* dstypecode[NumDataSetTypes] = { "u","s","i","a","n","pm","v8","v","p8","p","i8","S","S8","N", "FS"}; static char* magicNumber = "MATRIX"; struct MatDir { int matnum; int strtblk; int endblk; int matstat; }; struct matdir { int nmats, nmax; struct MatDir *entry; }; typedef struct matdirblk { int nfree, nextblk, prvblk, nused ; struct MatDir matdir[31] ; } MatDirBlk ; FILE *mat_create(const char *fname,Main_header *mhead); FILE *mat_open( const char *fname, char *fmode); int mat_write_main_header(FILE *fptr, Main_header *header); int map_main_header(char *bufr,Main_header *header); int mat_wblk(FILE *fptr,int blkno, char *bufr,int nblks); MatDirList *mat_read_directory(MatrixFile *mptr); MatDirBlk *mat_rdirblk(MatrixFile *file, int blknum); int write_host_data(MatrixFile *mptr, int matnum, MatrixData *data); int matrix_find(MatrixFile *matfile, int matnum,struct MatDir *matdir); int mat_enter(FILE *fptr, Main_header *mhptr, int matnum, int nblks); int insert_mdir(struct MatDir matdir, MatDirList *dirlist); int mat_write_image_subheader(FILE *fptr, Main_header *mhptr,int blknum, Image_subheader *header); int map_image_header(char *buf, Image_subheader *header); int matrix_freelist(MatDirList *matdirlist); void swaw( short *from, short *to, int length); int mat_close(FILE *fptr); int mat_rblk(FILE *fptr, int blkno, char *bufr, int nblks); MatrixFile *matrix_create(const char *fname, Main_header * proto_mhptr) { MatrixFile *mptr = NULL; FILE *fptr, *mat_create(); matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; fptr = mat_create(fname, proto_mhptr); if (!fptr) return( NULL ); mptr = (MatrixFile *) calloc(1, sizeof(MatrixFile)); if (!mptr) { fclose( fptr ); return( NULL ); } mptr->fptr = fptr; mptr->fname = (char *) malloc(strlen(fname) + 1); if (!mptr->fname) { free( mptr ); fclose( fptr ); return( NULL ); } strcpy(mptr->fname, fname); mptr->mhptr = (Main_header *) malloc(sizeof(Main_header)); if (!mptr->mhptr) { free( mptr->fname ); free( mptr ); fclose( fptr ); return( NULL ); } memcpy(mptr->mhptr, proto_mhptr, sizeof(Main_header)); mptr->dirlist = mat_read_directory(mptr); if (!mptr->dirlist) { free( mptr->fname ); free( mptr->mhptr ); free( mptr ); fclose( fptr ); return( NULL ); } return mptr; } FILE *mat_create(const char *fname,Main_header *mhead) { FILE *fptr; int bufr[MatBLKSIZE/sizeof(int)]; int ret; fptr = mat_open( fname, "w+"); if (!fptr) return( NULL ); ret = mat_write_main_header( fptr, mhead ); if( ret != 0 ) { mat_close( fptr); return( NULL ); } memset(bufr,0,MatBLKSIZE); bufr[0] = 31; bufr[1] = 2; ret = write_matrix_data(fptr,MatFirstDirBlk,1,(char*)bufr,SunLong); if( ret != 0 ) { mat_close( fptr); return( NULL ); } return (fptr); } FILE *mat_open( const char *fname, char *fmode) { FILE *fopen(), *fptr; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; fptr = fopen(fname, fmode); return (fptr); } int mat_write_main_header(FILE *fptr, Main_header *header) { char bufr[MatBLKSIZE]; map_main_header(bufr, header); return mat_wblk(fptr, 1, bufr, 1); /* write main header at block 1 */ } int map_main_header(char *bufr,Main_header *header) { int i = 0, j = 0; char mn[20]; /* set magic number */ sprintf(mn,"%s%d%s", magicNumber,header->sw_version, dstypecode[header->file_type]); bufWrite(mn, bufr, &i, 14); /* copy buffer into struct */ bufWrite(header->original_file_name, bufr, &i, NameLen); bufWrite_s(header->sw_version, bufr, &i); bufWrite_s(header->system_type, bufr, &i); bufWrite_s(header->file_type, bufr, &i); bufWrite(header->serial_number, bufr, &i, 10); bufWrite_u(header->scan_start_time, bufr, &i); bufWrite(header->isotope_code, bufr, &i, 8); bufWrite_f(header->isotope_halflife, bufr, &i); bufWrite(header->radiopharmaceutical, bufr, &i, NameLen); bufWrite_f(header->gantry_tilt, bufr, &i); bufWrite_f(header->gantry_rotation, bufr, &i); bufWrite_f(header->bed_elevation, bufr, &i); bufWrite_f(header->intrinsic_tilt, bufr, &i); bufWrite_s(header->wobble_speed, bufr, &i); bufWrite_s(header->transm_source_type, bufr, &i); bufWrite_f(header->distance_scanned, bufr, &i); bufWrite_f(header->transaxial_fov, bufr, &i); bufWrite_s(header->angular_compression, bufr, &i); bufWrite_s(header->coin_samp_mode, bufr, &i); bufWrite_s(header->axial_samp_mode, bufr, &i); bufWrite_f(header->calibration_factor, bufr, &i); bufWrite_s(header->calibration_units, bufr, &i); bufWrite_s(header->calibration_units_label, bufr, &i); bufWrite_s(header->compression_code, bufr, &i); bufWrite(header->study_name, bufr, &i, 12); bufWrite(header->patient_id, bufr, &i, IDLen); bufWrite(header->patient_name, bufr, &i, NameLen); bufWrite(header->patient_sex, bufr, &i, 1); bufWrite(header->patient_dexterity, bufr, &i, 1); bufWrite_f(header->patient_age, bufr, &i); bufWrite_f(header->patient_height, bufr, &i); bufWrite_f(header->patient_weight, bufr, &i); bufWrite_i(header->patient_birth_date, bufr, &i); bufWrite(header->physician_name, bufr, &i, NameLen); bufWrite(header->operator_name, bufr, &i, NameLen); bufWrite(header->study_description, bufr, &i, NameLen); bufWrite_s(header->acquisition_type, bufr, &i); bufWrite_s(header->patient_orientation, bufr, &i); bufWrite(header->facility_name, bufr, &i, 20); bufWrite_s(header->num_planes, bufr, &i); bufWrite_s(header->num_frames, bufr, &i); bufWrite_s(header->num_gates, bufr, &i); bufWrite_s(header->num_bed_pos, bufr, &i); bufWrite_f(header->init_bed_position, bufr, &i); for(j = 0; j < 15; j++) bufWrite_f(header->bed_offset[j], bufr, &i); bufWrite_f(header->plane_separation, bufr, &i); bufWrite_s(header->lwr_sctr_thres, bufr, &i); bufWrite_s(header->lwr_true_thres, bufr, &i); bufWrite_s(header->upr_true_thres, bufr, &i); bufWrite(header->user_process_code, bufr, &i, 10); bufWrite_s(header->acquisition_mode, bufr, &i); bufWrite_f(header->bin_size, bufr, &i); bufWrite_f(header->branching_fraction, bufr, &i); bufWrite_u(header->dose_start_time, bufr, &i); bufWrite_f(header->dosage, bufr, &i); bufWrite_f(header->well_counter_factor, bufr, &i); bufWrite(header->data_units, bufr, &i, 32); bufWrite_s(header->septa_state, bufr, &i); return 1; } int mat_wblk(FILE *fptr,int blkno, char *bufr,int nblks) { int err; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; /* seek to position in file */ err = fseek(fptr, (blkno - 1) * MatBLKSIZE, 0); if (err) return (ERROR); /* write matrix data */ err = fwrite(bufr, 1, nblks * MatBLKSIZE, fptr); if (err == -1) return (ERROR); if (err != nblks * MatBLKSIZE) { matrix_errno = MAT_WRITE_ERROR; return (ERROR); } return (0); } MatDirList *mat_read_directory(MatrixFile *mptr) { struct MatDir matdir; MatDirList *dirlist; MatDirBlk *matdirblk; int i, blknum; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; dirlist = (MatDirList *) calloc(1, sizeof(MatDirList)); if (dirlist == NULL) return (NULL); blknum = MatFirstDirBlk; do { matdirblk = mat_rdirblk(mptr, blknum); if (matdirblk == NULL) { free(dirlist); return (NULL); } for (i = 0; i < matdirblk->nused; i++) { matdir.matnum = matdirblk->matdir[i].matnum; matdir.strtblk = matdirblk->matdir[i].strtblk; matdir.endblk = matdirblk->matdir[i].endblk; matdir.matstat = matdirblk->matdir[i].matstat; insert_mdir(matdir, dirlist); } blknum = matdirblk->nextblk; free(matdirblk); } while (blknum != MatFirstDirBlk); return (dirlist); } MatDirBlk *mat_rdirblk(MatrixFile *file, int blknum) { MatDirBlk *matdirblk; int i, j, err, ndirs; int dirbufr[MatBLKSIZE / 4]; FILE *fptr = file->fptr; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; matdirblk = (MatDirBlk *) malloc(MatBLKSIZE); if (matdirblk == NULL) return (NULL); err = read_matrix_data(fptr, blknum, 1, (char *) dirbufr, SunLong); if (err == ERROR) { free(matdirblk); return (NULL); } matdirblk->nfree = dirbufr[0]; matdirblk->nextblk = dirbufr[1]; matdirblk->prvblk = dirbufr[2]; matdirblk->nused = dirbufr[3]; if (matdirblk->nused > 31) { matrix_errno = MAT_INVALID_DIRBLK; free(matdirblk); return (NULL); } ndirs = (MatBLKSIZE / 4 - 4) / 4; for (i = 0; i < ndirs; i++) { matdirblk->matdir[i].matnum = 0; matdirblk->matdir[i].strtblk = 0; matdirblk->matdir[i].endblk = 0; matdirblk->matdir[i].matstat = 0; } for (i = 0; i < matdirblk->nused; i++) { j = i + 1; matdirblk->matdir[i].matnum = dirbufr[j * 4 + 0]; matdirblk->matdir[i].strtblk = dirbufr[j * 4 + 1]; matdirblk->matdir[i].endblk = dirbufr[j * 4 + 2]; matdirblk->matdir[i].matstat = dirbufr[j * 4 + 3]; } return (matdirblk); } int matrix_write(MatrixFile *mptr, int matnum,MatrixData *data) { matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; if (mptr == NULL) matrix_errno = MAT_READ_FROM_NILFPTR ; else if (mptr->mhptr == NULL) matrix_errno = MAT_NOMHD_FILE_OBJECT ; else if (data->shptr == NULL) matrix_errno = MAT_NIL_SHPTR ; else if (data->data_ptr == NULL) matrix_errno = MAT_NIL_DATA_PTR ; if (matrix_errno != OK) return (ERROR) ; return write_host_data(mptr, matnum, data); } int write_host_data(MatrixFile *mptr, int matnum, MatrixData *data) { struct MatDir matdir, dir_entry ; Image_subheader *imagesub ; int status, blkno, nblks ; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; status = OK ; nblks = (data->data_size+511)/512; if (matrix_find(mptr, matnum, &matdir) == ERROR) { blkno = mat_enter(mptr->fptr, mptr->mhptr, matnum, nblks) ; if( blkno == ERROR ) return( ERROR ); dir_entry.matnum = matnum ; dir_entry.strtblk = blkno ; /*le 24 Avril 2001, j'ai enleve le -1*/ dir_entry.endblk = dir_entry.strtblk + nblks /*- 1*/ ; dir_entry.matstat = 1 ; insert_mdir(dir_entry, mptr->dirlist) ; matdir = dir_entry ; } imagesub = (Image_subheader *) data->shptr ; if (imagesub == NULL) { imagesub = (Image_subheader *) calloc(1, MatBLKSIZE); data->shptr = imagesub; } /* use MatrixData info */ imagesub->x_pixel_size = data->pixel_size; imagesub->y_pixel_size = data->y_size; imagesub->z_pixel_size = data->z_size; imagesub->num_dimensions = 3; imagesub->x_dimension = data->xdim; imagesub->y_dimension = data->ydim; imagesub->z_dimension = data->zdim; imagesub->image_max = (int)(data->data_max/data->scale_factor); imagesub->image_min = (int)(data->data_min/data->scale_factor); imagesub->scale_factor = data->scale_factor; imagesub->data_type = data->data_type; if( mat_write_image_subheader(mptr->fptr,mptr->mhptr,matdir.strtblk, imagesub) == ERROR ) return( ERROR ); status = write_matrix_data(mptr->fptr, matdir.strtblk+1, nblks, data->data_ptr, imagesub->data_type) ; if( status == ERROR ) return( ERROR ); return(status) ; } int matrix_find(MatrixFile *matfile, int matnum,struct MatDir *matdir) { MatDirNode *node ; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; if (matfile == NULL) return(ERROR) ; if (matfile->dirlist == NULL) return(ERROR) ; node = matfile->dirlist->first ; while (node != NULL) { if (node->matnum == matnum) { matdir->matnum = node->matnum ; matdir->strtblk = node->strtblk ; matdir->endblk = node->endblk ; matdir->matstat = node->matstat ; break ; } node = node->next ; } if (node != NULL) return(OK) ; else return(ERROR) ; } int mat_enter(FILE *fptr, Main_header *mhptr, int matnum, int nblks) { int dirblk, dirbufr[128], i, nxtblk, busy, oldsize; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; dirblk = MatFirstDirBlk; if( fseek(fptr, 0, 0) ) return( ERROR ); /* * nfs locks are very time consuming lockf( fileno(fptr), F_LOCK, 0); */ if (read_matrix_data(fptr, dirblk, 1, (char *) dirbufr, SunLong) == ERROR) return (ERROR); busy = 1; while (busy) { nxtblk = dirblk + 1; for (i = 4; i < 128; i += 4) { if (dirbufr[i] == 0) { busy = 0; break; } else if (dirbufr[i] == matnum) { oldsize = dirbufr[i + 2] - dirbufr[i + 1] + 1; if (oldsize < nblks) { dirbufr[i] = 0xFFFFFFFF; write_matrix_data(fptr, dirblk, 1, (char*)dirbufr, SunLong); nxtblk = dirbufr[i + 2] + 1; } else { nxtblk = dirbufr[i + 1]; dirbufr[0]++; dirbufr[3]--; busy = 0; break; } } else { nxtblk = dirbufr[i + 2] + 1; } } if (!busy) break; if (dirbufr[1] != MatFirstDirBlk) { dirblk = dirbufr[1]; if (read_matrix_data(fptr, dirblk, 1, (char *) dirbufr, SunLong) == ERROR) return (ERROR); } else { dirbufr[1] = nxtblk; if (write_matrix_data(fptr, dirblk, 1, (char *) dirbufr, SunLong) == ERROR) return (ERROR); dirbufr[0] = 31; dirbufr[1] = MatFirstDirBlk; dirbufr[2] = dirblk; dirbufr[3] = 0; dirblk = nxtblk; for (i = 4; i < 128; i++) dirbufr[i] = 0; } } dirbufr[i] = matnum; dirbufr[i + 1] = nxtblk; dirbufr[i + 2] = nxtblk + nblks; dirbufr[i + 3] = 1; dirbufr[0]--; dirbufr[3]++; if (write_matrix_data(fptr, dirblk, 1, (char*)dirbufr, SunLong) == ERROR) return (ERROR); if( fseek(fptr, 0, 0) ) return( ERROR ); /* * nfs locks are very time consuming lockf( fileno(fptr), F_UNLOCK, 0); */ return (nxtblk); } int insert_mdir(struct MatDir matdir, MatDirList *dirlist) { MatDirNode *node ; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; if (dirlist == NULL) { dirlist = (MatDirList *) malloc(sizeof(MatDirList)) ; if (dirlist == NULL) return(ERROR) ; dirlist->nmats = 0 ; dirlist->first = NULL ; dirlist->last = NULL ; } node = (MatDirNode *) malloc(sizeof(MatDirNode)) ; if (node == NULL) return(ERROR) ; node->matnum = matdir.matnum ; node->strtblk = matdir.strtblk ; node->endblk = matdir.endblk ; node->matstat = matdir.matstat; node->next = NULL ; if (dirlist->first == NULL) /* if list was empty, add first node */ { dirlist->first = node ; dirlist->last = node ; dirlist->nmats = 1 ; } else { (dirlist->last)->next = node ; dirlist->last = node ; ++(dirlist->nmats) ; } return OK; } int mat_write_image_subheader(FILE *fptr, Main_header *mhptr,int blknum, Image_subheader *header) { char buf[MatBLKSIZE]; map_image_header(buf, header); return mat_wblk(fptr, blknum, buf, 1); } int map_image_header(char *buf, Image_subheader *header) { int i = 0; bufWrite_s(header->data_type, buf, &i); bufWrite_s(header->num_dimensions, buf, &i); bufWrite_s(header->x_dimension, buf, &i); bufWrite_s(header->y_dimension, buf, &i); bufWrite_s(header->z_dimension, buf, &i); bufWrite_f(header->z_offset, buf, &i); bufWrite_f(header->x_offset, buf, &i); bufWrite_f(header->y_offset, buf, &i); bufWrite_f(header->recon_zoom, buf, &i); bufWrite_f(header->scale_factor, buf, &i); bufWrite_s(header->image_min, buf, &i); bufWrite_s(header->image_max, buf, &i); bufWrite_f(header->x_pixel_size, buf, &i); bufWrite_f(header->y_pixel_size, buf, &i); bufWrite_f(header->z_pixel_size, buf, &i); bufWrite_u(header->frame_duration, buf, &i); bufWrite_u(header->frame_start_time, buf, &i); bufWrite_s(header->filter_code, buf, &i); bufWrite_f(header->x_resolution, buf, &i); bufWrite_f(header->y_resolution, buf, &i); bufWrite_f(header->z_resolution, buf, &i); bufWrite_f(header->num_r_elements, buf, &i); bufWrite_f(header->num_angles, buf, &i); bufWrite_f(header->z_rotation_angle, buf, &i); bufWrite_f(header->decay_corr_fctr, buf, &i); bufWrite_i(header->processing_code, buf, &i); bufWrite_u(header->gate_duration, buf, &i); bufWrite_i(header->r_wave_offset, buf, &i); bufWrite_i(header->num_accepted_beats, buf, &i); bufWrite_f(header->filter_cutoff_frequency, buf, &i); bufWrite_f(header->filter_resolution, buf, &i); bufWrite_f(header->filter_ramp_slope, buf, &i); bufWrite_s(header->filter_order, buf, &i); bufWrite_f(header->filter_scatter_fraction, buf, &i); bufWrite_f(header->filter_scatter_slope, buf, &i); bufWrite(header->annotation, buf, &i, 40); bufWrite_f(header->mt_1_1, buf, &i); bufWrite_f(header->mt_1_2, buf, &i); bufWrite_f(header->mt_1_3, buf, &i); bufWrite_f(header->mt_2_1, buf, &i); bufWrite_f(header->mt_2_2, buf, &i); bufWrite_f(header->mt_2_3, buf, &i); bufWrite_f(header->mt_3_1, buf, &i); bufWrite_f(header->mt_3_2, buf, &i); bufWrite_f(header->mt_3_3, buf, &i); bufWrite_f(header->rfilter_cutoff, buf, &i); bufWrite_f(header->rfilter_resolution, buf, &i); bufWrite_s(header->rfilter_code, buf, &i); bufWrite_s(header->rfilter_order, buf, &i); bufWrite_f(header->zfilter_cutoff, buf, &i); bufWrite_f(header->zfilter_resolution, buf, &i); bufWrite_s(header->zfilter_code, buf, &i); bufWrite_s(header->zfilter_order, buf, &i); bufWrite_f(header->mt_1_4, buf, &i); bufWrite_f(header->mt_2_4, buf, &i); bufWrite_f(header->mt_3_4, buf, &i); bufWrite_s(header->scatter_type, buf, &i); bufWrite_s(header->recon_type, buf, &i); bufWrite_s(header->recon_views, buf, &i); return 1; } int matrix_close(MatrixFile *mptr) { int status = OK; matrix_errno = MAT_OK; if (mptr->fname) strcpy(matrix_errtxt,mptr->fname); else matrix_errtxt[0] = '\0'; if (mptr == NULL) return status; if (mptr->mhptr != NULL) free(mptr->mhptr) ; if (mptr->dirlist != NULL) matrix_freelist(mptr->dirlist) ; if (mptr->fptr) status = fclose(mptr->fptr); if (mptr->fname) free(mptr->fname); free(mptr); return status; } int matrix_freelist(MatDirList *matdirlist) { MatDirNode *node, *next ; if (matdirlist == NULL) return OK; if (matdirlist->first != NULL) { node = matdirlist->first ; do { next = node->next ; free(node) ; node = next ; } while(next != NULL) ; } free(matdirlist) ; return OK; } int mat_numcod(int frame, int plane, int gate, int data, int bed) { return ((frame)|((bed&0xF)<<12)|((plane&0xFF)<<16)|(((plane&0x300)>>8)<<9)| ((gate&0x3F)<<24)|((data&0x3)<<30)|((data&0x4)<<9)); } void swaw( short *from, short *to, int length) { short int temp; int i; for (i=0;i check if byte count less than (nblks-1) (M. Sibomana 23-oct-1997) */ else if( err < (nblks-1)*MatBLKSIZE ) { matrix_errno = MAT_READ_ERROR; return( ERROR ); } return( 0 ); } minc-2.2.00/conversion/minctoecat/machine_indep.c0000644000265600003100000002152312027132661016704 00000000000000#include #include #include "ecat_write.h" #define OK 0 #define ERROR -1 #ifdef _WIN32 unsigned short ntohs(unsigned short us) { unsigned char *p = (unsigned char*)&us; return ((unsigned short)p[1] + (p[0] >> 8)); } unsigned long ntohl(unsigned long ul) { unsigned char *p = (unsigned char*)&ul; return ((unsigned long)p[3] + (p[2] >> 8) + (p[1] >> 16) + (p[0] >> 24)); } #endif #if defined(__STDC__) void SWAB(const void *from, void *to, int length) #else void SWAB( from, to, length) char *from, *to; int length; #endif { if (ntohs(1) == 1) swab(from, to, length); else memcpy(to,from,length); } void SWAW ( from, to, length) #if defined(__STDC__) const short *from; #else short *from; #endif short *to; int length; { if (ntohs(1) == 1) swaw((short*)from,to,length); else memcpy(to,from,length*2); } float vaxftohf( bufr, off) unsigned short *bufr; int off; { unsigned int sign_exp, high, low, mantissa, ret; unsigned u = (bufr[off+1] << 16) + bufr[off]; if (u == 0) return 0.0; sign_exp = u & 0x0000ff80; sign_exp = (sign_exp - 0x0100) & 0xff80; high = u & 0x0000007f; low = u & 0xffff0000; mantissa = (high << 16) + (low >> 16); sign_exp = sign_exp << 16; ret = sign_exp + mantissa; return *(float*)(&ret); } #if defined(__alpha) || defined(_WIN32) /* LITTLE_ENDIAN : alpha, intel */ void ftovaxf(f, bufr) float f; unsigned short *bufr; { unsigned *u, sign_exp, low, high, mantissa, ret; float f_tmp = f; u = (unsigned*)(&f_tmp); if (u == 0) { bufr[0] = bufr[1] = 0; return; } sign_exp = *u & 0xff800000; sign_exp = sign_exp >> 16; sign_exp = (sign_exp + 0x0110) & 0xff80; low = *u & 0x0000ffff; high = *u & 0x007f0000; mantissa = (high >> 16) + (low << 16); ret = sign_exp + mantissa; bufr[0] = ret; bufr[1] = ret >>16; } #else /* BIG ENDIAN : sun hp sgi*/ void ftovaxf(orig,number) unsigned short number[2]; float orig; { /* convert from sun float to vax float */ union { unsigned short t[2]; float t4; } test; unsigned short int exp; number[0] = 0; number[1] = 0; test.t4 = orig; if (test.t4 == 0.0) return; number[1] = test.t[1]; exp = ((test.t[0] & 0x7f00) + 0x0100) & 0x7f00; test.t[0] = (test.t[0] & 0x80ff) + exp; number[0] = test.t[0]; } #endif /* LITTLE VS BIG ENDIAN*/ int file_data_to_host(dptr, nblks, dtype) char *dptr; int nblks, dtype; { int i, j; char *tmp = NULL; matrix_errno = 0; matrix_errtxt[0] = '\0'; if ((tmp = malloc(512)) == NULL) return ERROR; switch(dtype) { case ByteData: break; case VAX_Ix2: if (ntohs(1) == 1) for (i=0, j=0; i 0 in the .hdr/.img file pair storage method is to make the .img file be a copy of (or link to) a pre-existing image file in some other format, such as DICOM; then vox_offset would be set to the offset of the image data in this file. (It may not be possible to follow the "multiple-of-16 rule" with an arbitrary external file; using the NIfTI-1 format in such a case may lead to a file that is incompatible with software that relies on vox_offset being a multiple of 16.) In a .nii file, data bytes between #348 and #vox_offset-1 (inclusive) may be used to store user-defined extra information; similarly, in a .hdr file, any data bytes after byte #347 are available for user-defined extra information. The (very weak) regulation of this extra header data is described elsewhere. -----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* DATA SCALING: ------------ If the scl_slope field is nonzero, then each voxel value in the dataset should be scaled as y = scl_slope * x + scl_inter where x = voxel value stored y = "true" voxel value Normally, we would expect this scaling to be used to store "true" floating values in a smaller integer datatype, but that is not required. That is, it is legal to use scaling even if the datatype is a float type (crazy, perhaps, but legal). - However, the scaling is to be ignored if datatype is DT_RGB24. - If datatype is a complex type, then the scaling is to be applied to both the real and imaginary parts. The cal_min and cal_max fields (if nonzero) are used for mapping (possibly scaled) dataset values to display colors: - Minimum display intensity (black) corresponds to dataset value cal_min. - Maximum display intensity (white) corresponds to dataset value cal_max. - Dataset values below cal_min should display as black also, and values above cal_max as white. - Colors "black" and "white", of course, may refer to any scalar display scheme (e.g., a color lookup table specified via aux_file). - cal_min and cal_max only make sense when applied to scalar-valued datasets (i.e., dim[0] < 5 or dim[5] = 1). -----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* TYPE OF DATA (acceptable values for datatype field): --------------------------------------------------- Values of datatype smaller than 256 are ANALYZE 7.5 compatible. Larger values are NIFTI-1 additions. These are all multiples of 256, so that no bits below position 8 are set in datatype. But there is no need to use only powers-of-2, as the original ANALYZE 7.5 datatype codes do. The additional codes are intended to include a complete list of basic scalar types, including signed and unsigned integers from 8 to 64 bits, floats from 32 to 128 bits, and complex (float pairs) from 64 to 256 bits. Note that most programs will support only a few of these datatypes! A NIFTI-1 program should fail gracefully (e.g., print a warning message) when it encounters a dataset with a type it doesn't like. -----------------------------------------------------------------------------*/ #undef DT_UNKNOWN /* defined in dirent.h on some Unix systems */ /*! \defgroup NIFTI1_DATATYPES \brief nifti1 datatype codes @{ */ /*--- the original ANALYZE 7.5 type codes ---*/ #define DT_NONE 0 #define DT_UNKNOWN 0 /* what it says, dude */ #define DT_BINARY 1 /* binary (1 bit/voxel) */ #define DT_UNSIGNED_CHAR 2 /* unsigned char (8 bits/voxel) */ #define DT_SIGNED_SHORT 4 /* signed short (16 bits/voxel) */ #define DT_SIGNED_INT 8 /* signed int (32 bits/voxel) */ #define DT_FLOAT 16 /* float (32 bits/voxel) */ #define DT_COMPLEX 32 /* complex (64 bits/voxel) */ #define DT_DOUBLE 64 /* double (64 bits/voxel) */ #define DT_RGB 128 /* RGB triple (24 bits/voxel) */ #define DT_ALL 255 /* not very useful (?) */ /*----- another set of names for the same ---*/ #define DT_UINT8 2 #define DT_INT16 4 #define DT_INT32 8 #define DT_FLOAT32 16 #define DT_COMPLEX64 32 #define DT_FLOAT64 64 #define DT_RGB24 128 /*------------------- new codes for NIFTI ---*/ #define DT_INT8 256 /* signed char (8 bits) */ #define DT_UINT16 512 /* unsigned short (16 bits) */ #define DT_UINT32 768 /* unsigned int (32 bits) */ #define DT_INT64 1024 /* long long (64 bits) */ #define DT_UINT64 1280 /* unsigned long long (64 bits) */ #define DT_FLOAT128 1536 /* long double (128 bits) */ #define DT_COMPLEX128 1792 /* double pair (128 bits) */ #define DT_COMPLEX256 2048 /* long double pair (256 bits) */ /* @} */ /*------- aliases for all the above codes ---*/ /*! \defgroup NIFTI1_DATATYPE_ALIASES \brief aliases for the nifti1 datatype codes @{ */ /*! unsigned char. */ #define NIFTI_TYPE_UINT8 2 /*! signed short. */ #define NIFTI_TYPE_INT16 4 /*! signed int. */ #define NIFTI_TYPE_INT32 8 /*! 32 bit float. */ #define NIFTI_TYPE_FLOAT32 16 /*! 64 bit complex = 2 32 bit floats. */ #define NIFTI_TYPE_COMPLEX64 32 /*! 64 bit float = double. */ #define NIFTI_TYPE_FLOAT64 64 /*! 3 8 bit bytes. */ #define NIFTI_TYPE_RGB24 128 /*! signed char. */ #define NIFTI_TYPE_INT8 256 /*! unsigned short. */ #define NIFTI_TYPE_UINT16 512 /*! unsigned int. */ #define NIFTI_TYPE_UINT32 768 /*! signed long long. */ #define NIFTI_TYPE_INT64 1024 /*! unsigned long long. */ #define NIFTI_TYPE_UINT64 1280 /*! 128 bit float = long double. */ #define NIFTI_TYPE_FLOAT128 1536 /*! 128 bit complex = 2 64 bit floats. */ #define NIFTI_TYPE_COMPLEX128 1792 /*! 256 bit complex = 2 128 bit floats */ #define NIFTI_TYPE_COMPLEX256 2048 /* @} */ /*-------- sample typedefs for complicated types ---*/ #if 0 typedef struct { float r,i; } complex_float ; typedef struct { double r,i; } complex_double ; typedef struct { long double r,i; } complex_longdouble ; typedef struct { unsigned char r,g,b; } rgb_byte ; #endif /*---------------------------------------------------------------------------*/ /* INTERPRETATION OF VOXEL DATA: ---------------------------- The intent_code field can be used to indicate that the voxel data has some particular meaning. In particular, a large number of codes is given to indicate that the the voxel data should be interpreted as being drawn from a given probability distribution. VECTOR-VALUED DATASETS: ---------------------- The 5th dimension of the dataset, if present (i.e., dim[0]=5 and dim[5] > 1), contains multiple values (e.g., a vector) to be stored at each spatiotemporal location. For example, the header values - dim[0] = 5 - dim[1] = 64 - dim[2] = 64 - dim[3] = 20 - dim[4] = 1 (indicates no time axis) - dim[5] = 3 - datatype = DT_FLOAT - intent_code = NIFTI_INTENT_VECTOR mean that this dataset should be interpreted as a 3D volume (64x64x20), with a 3-vector of floats defined at each point in the 3D grid. A program reading a dataset with a 5th dimension may want to reformat the image data to store each voxels' set of values together in a struct or array. This programming detail, however, is beyond the scope of the NIFTI-1 file specification! Uses of dimensions 6 and 7 are also not specified here. STATISTICAL PARAMETRIC DATASETS (i.e., SPMs): -------------------------------------------- Values of intent_code from NIFTI_FIRST_STATCODE to NIFTI_LAST_STATCODE (inclusive) indicate that the numbers in the dataset should be interpreted as being drawn from a given distribution. Most such distributions have auxiliary parameters (e.g., NIFTI_INTENT_TTEST has 1 DOF parameter). If the dataset DOES NOT have a 5th dimension, then the auxiliary parameters are the same for each voxel, and are given in header fields intent_p1, intent_p2, and intent_p3. If the dataset DOES have a 5th dimension, then the auxiliary parameters are different for each voxel. For example, the header values - dim[0] = 5 - dim[1] = 128 - dim[2] = 128 - dim[3] = 1 (indicates a single slice) - dim[4] = 1 (indicates no time axis) - dim[5] = 2 - datatype = DT_FLOAT - intent_code = NIFTI_INTENT_TTEST mean that this is a 2D dataset (128x128) of t-statistics, with the t-statistic being in the first "plane" of data and the degrees-of-freedom parameter being in the second "plane" of data. If the dataset 5th dimension is used to store the voxel-wise statistical parameters, then dim[5] must be 1 plus the number of parameters required by that distribution (e.g., intent_code=NIFTI_INTENT_TTEST implies dim[5] must be 2, as in the example just above). Note: intent_code values 2..10 are compatible with AFNI 1.5x (which is why there is no code with value=1, which is obsolescent in AFNI). OTHER INTENTIONS: ---------------- The purpose of the intent_* fields is to help interpret the values stored in the dataset. Some non-statistical values for intent_code and conventions are provided for storing other complex data types. The intent_name field provides space for a 15 character (plus 0 byte) 'name' string for the type of data stored. Examples: - intent_code = NIFTI_INTENT_ESTIMATE; intent_name = "T1"; could be used to signify that the voxel values are estimates of the NMR parameter T1. - intent_code = NIFTI_INTENT_TTEST; intent_name = "House"; could be used to signify that the voxel values are t-statistics for the significance of 'activation' response to a House stimulus. - intent_code = NIFTI_INTENT_DISPVECT; intent_name = "ToMNI152"; could be used to signify that the voxel values are a displacement vector that transforms each voxel (x,y,z) location to the corresponding location in the MNI152 standard brain. - intent_code = NIFTI_INTENT_SYMMATRIX; intent_name = "DTI"; could be used to signify that the voxel values comprise a diffusion tensor image. If no data name is implied or needed, intent_name[0] should be set to 0. -----------------------------------------------------------------------------*/ /*! default: no intention is indicated in the header. */ #define NIFTI_INTENT_NONE 0 /*-------- These codes are for probability distributions ---------------*/ /* Most distributions have a number of parameters, below denoted by p1, p2, and p3, and stored in - intent_p1, intent_p2, intent_p3 if dataset doesn't have 5th dimension - image data array if dataset does have 5th dimension Functions to compute with many of the distributions below can be found in the CDF library from U Texas. Formulas for and discussions of these distributions can be found in the following books: [U] Univariate Discrete Distributions, NL Johnson, S Kotz, AW Kemp. [C1] Continuous Univariate Distributions, vol. 1, NL Johnson, S Kotz, N Balakrishnan. [C2] Continuous Univariate Distributions, vol. 2, NL Johnson, S Kotz, N Balakrishnan. */ /*----------------------------------------------------------------------*/ /*! [C2, chap 32] Correlation coefficient R (1 param): p1 = degrees of freedom R/sqrt(1-R*R) is t-distributed with p1 DOF. */ /*! \defgroup NIFTI1_INTENT_CODES \brief nifti1 intent codes, to describe intended meaning of dataset contents @{ */ #define NIFTI_INTENT_CORREL 2 /*! [C2, chap 28] Student t statistic (1 param): p1 = DOF. */ #define NIFTI_INTENT_TTEST 3 /*! [C2, chap 27] Fisher F statistic (2 params): p1 = numerator DOF, p2 = denominator DOF. */ #define NIFTI_INTENT_FTEST 4 /*! [C1, chap 13] Standard normal (0 params): Density = N(0,1). */ #define NIFTI_INTENT_ZSCORE 5 /*! [C1, chap 18] Chi-squared (1 param): p1 = DOF. Density(x) proportional to exp(-x/2) * x^(p1/2-1). */ #define NIFTI_INTENT_CHISQ 6 /*! [C2, chap 25] Beta distribution (2 params): p1=a, p2=b. Density(x) proportional to x^(a-1) * (1-x)^(b-1). */ #define NIFTI_INTENT_BETA 7 /*! [U, chap 3] Binomial distribution (2 params): p1 = number of trials, p2 = probability per trial. Prob(x) = (p1 choose x) * p2^x * (1-p2)^(p1-x), for x=0,1,...,p1. */ #define NIFTI_INTENT_BINOM 8 /*! [C1, chap 17] Gamma distribution (2 params): p1 = shape, p2 = scale. Density(x) proportional to x^(p1-1) * exp(-p2*x). */ #define NIFTI_INTENT_GAMMA 9 /*! [U, chap 4] Poisson distribution (1 param): p1 = mean. Prob(x) = exp(-p1) * p1^x / x! , for x=0,1,2,.... */ #define NIFTI_INTENT_POISSON 10 /*! [C1, chap 13] Normal distribution (2 params): p1 = mean, p2 = standard deviation. */ #define NIFTI_INTENT_NORMAL 11 /*! [C2, chap 30] Noncentral F statistic (3 params): p1 = numerator DOF, p2 = denominator DOF, p3 = numerator noncentrality parameter. */ #define NIFTI_INTENT_FTEST_NONC 12 /*! [C2, chap 29] Noncentral chi-squared statistic (2 params): p1 = DOF, p2 = noncentrality parameter. */ #define NIFTI_INTENT_CHISQ_NONC 13 /*! [C2, chap 23] Logistic distribution (2 params): p1 = location, p2 = scale. Density(x) proportional to sech^2((x-p1)/(2*p2)). */ #define NIFTI_INTENT_LOGISTIC 14 /*! [C2, chap 24] Laplace distribution (2 params): p1 = location, p2 = scale. Density(x) proportional to exp(-abs(x-p1)/p2). */ #define NIFTI_INTENT_LAPLACE 15 /*! [C2, chap 26] Uniform distribution: p1 = lower end, p2 = upper end. */ #define NIFTI_INTENT_UNIFORM 16 /*! [C2, chap 31] Noncentral t statistic (2 params): p1 = DOF, p2 = noncentrality parameter. */ #define NIFTI_INTENT_TTEST_NONC 17 /*! [C1, chap 21] Weibull distribution (3 params): p1 = location, p2 = scale, p3 = power. Density(x) proportional to ((x-p1)/p2)^(p3-1) * exp(-((x-p1)/p2)^p3) for x > p1. */ #define NIFTI_INTENT_WEIBULL 18 /*! [C1, chap 18] Chi distribution (1 param): p1 = DOF. Density(x) proportional to x^(p1-1) * exp(-x^2/2) for x > 0. p1 = 1 = 'half normal' distribution p1 = 2 = Rayleigh distribution p1 = 3 = Maxwell-Boltzmann distribution. */ #define NIFTI_INTENT_CHI 19 /*! [C1, chap 15] Inverse Gaussian (2 params): p1 = mu, p2 = lambda Density(x) proportional to exp(-p2*(x-p1)^2/(2*p1^2*x)) / x^3 for x > 0. */ #define NIFTI_INTENT_INVGAUSS 20 /*! [C2, chap 22] Extreme value type I (2 params): p1 = location, p2 = scale cdf(x) = exp(-exp(-(x-p1)/p2)). */ #define NIFTI_INTENT_EXTVAL 21 /*! Data is a 'p-value' (no params). */ #define NIFTI_INTENT_PVAL 22 /*! Data is ln(p-value) (no params). To be safe, a program should compute p = exp(-abs(this_value)). The nifti_stats.c library returns this_value as positive, so that this_value = -log(p). */ #define NIFTI_INTENT_LOGPVAL 23 /*! Data is log10(p-value) (no params). To be safe, a program should compute p = pow(10.,-abs(this_value)). The nifti_stats.c library returns this_value as positive, so that this_value = -log10(p). */ #define NIFTI_INTENT_LOG10PVAL 24 /*! Smallest intent_code that indicates a statistic. */ #define NIFTI_FIRST_STATCODE 2 /*! Largest intent_code that indicates a statistic. */ #define NIFTI_LAST_STATCODE 24 /*---------- these values for intent_code aren't for statistics ----------*/ /*! To signify that the value at each voxel is an estimate of some parameter, set intent_code = NIFTI_INTENT_ESTIMATE. The name of the parameter may be stored in intent_name. */ #define NIFTI_INTENT_ESTIMATE 1001 /*! To signify that the value at each voxel is an index into some set of labels, set intent_code = NIFTI_INTENT_LABEL. The filename with the labels may stored in aux_file. */ #define NIFTI_INTENT_LABEL 1002 /*! To signify that the value at each voxel is an index into the NeuroNames labels set, set intent_code = NIFTI_INTENT_NEURONAME. */ #define NIFTI_INTENT_NEURONAME 1003 /*! To store an M x N matrix at each voxel: - dataset must have a 5th dimension (dim[0]=5 and dim[5]>1) - intent_code must be NIFTI_INTENT_GENMATRIX - dim[5] must be M*N - intent_p1 must be M (in float format) - intent_p2 must be N (ditto) - the matrix values A[i][[j] are stored in row-order: - A[0][0] A[0][1] ... A[0][N-1] - A[1][0] A[1][1] ... A[1][N-1] - etc., until - A[M-1][0] A[M-1][1] ... A[M-1][N-1] */ #define NIFTI_INTENT_GENMATRIX 1004 /*! To store an NxN symmetric matrix at each voxel: - dataset must have a 5th dimension - intent_code must be NIFTI_INTENT_SYMMATRIX - dim[5] must be N*(N+1)/2 - intent_p1 must be N (in float format) - the matrix values A[i][[j] are stored in row-order: - A[0][0] - A[1][0] A[1][1] - A[2][0] A[2][1] A[2][2] - etc.: row-by-row */ #define NIFTI_INTENT_SYMMATRIX 1005 /*! To signify that the vector value at each voxel is to be taken as a displacement field or vector: - dataset must have a 5th dimension - intent_code must be NIFTI_INTENT_DISPVECT - dim[5] must be the dimensionality of the displacment vector (e.g., 3 for spatial displacement, 2 for in-plane) */ #define NIFTI_INTENT_DISPVECT 1006 /* specifically for displacements */ #define NIFTI_INTENT_VECTOR 1007 /* for any other type of vector */ /*! To signify that the vector value at each voxel is really a spatial coordinate (e.g., the vertices or nodes of a surface mesh): - dataset must have a 5th dimension - intent_code must be NIFTI_INTENT_POINTSET - dim[0] = 5 - dim[1] = number of points - dim[2] = dim[3] = dim[4] = 1 - dim[5] must be the dimensionality of space (e.g., 3 => 3D space). - intent_name may describe the object these points come from (e.g., "pial", "gray/white" , "EEG", "MEG"). */ #define NIFTI_INTENT_POINTSET 1008 /*! To signify that the vector value at each voxel is really a triple of indexes (e.g., forming a triangle) from a pointset dataset: - dataset must have a 5th dimension - intent_code must be NIFTI_INTENT_TRIANGLE - dim[0] = 5 - dim[1] = number of triangles - dim[2] = dim[3] = dim[4] = 1 - dim[5] = 3 - datatype should be an integer type (preferably DT_INT32) - the data values are indexes (0,1,...) into a pointset dataset. */ #define NIFTI_INTENT_TRIANGLE 1009 /*! To signify that the vector value at each voxel is a quaternion: - dataset must have a 5th dimension - intent_code must be NIFTI_INTENT_QUATERNION - dim[0] = 5 - dim[5] = 4 - datatype should be a floating point type */ #define NIFTI_INTENT_QUATERNION 1010 /*! Dimensionless value - no params - although, as in _ESTIMATE the name of the parameter may be stored in intent_name. */ #define NIFTI_INTENT_DIMLESS 1011 /* @} */ /*---------------------------------------------------------------------------*/ /* 3D IMAGE (VOLUME) ORIENTATION AND LOCATION IN SPACE: --------------------------------------------------- There are 3 different methods by which continuous coordinates can attached to voxels. The discussion below emphasizes 3D volumes, and the continuous coordinates are referred to as (x,y,z). The voxel index coordinates (i.e., the array indexes) are referred to as (i,j,k), with valid ranges: i = 0 .. dim[1]-1 j = 0 .. dim[2]-1 (if dim[0] >= 2) k = 0 .. dim[3]-1 (if dim[0] >= 3) The (x,y,z) coordinates refer to the CENTER of a voxel. In methods 2 and 3, the (x,y,z) axes refer to a subject-based coordinate system, with +x = Right +y = Anterior +z = Superior. This is a right-handed coordinate system. However, the exact direction these axes point with respect to the subject depends on qform_code (Method 2) and sform_code (Method 3). N.B.: The i index varies most rapidly, j index next, k index slowest. Thus, voxel (i,j,k) is stored starting at location (i + j*dim[1] + k*dim[1]*dim[2]) * (bitpix/8) into the dataset array. N.B.: The ANALYZE 7.5 coordinate system is +x = Left +y = Anterior +z = Superior which is a left-handed coordinate system. This backwardness is too difficult to tolerate, so this NIFTI-1 standard specifies the coordinate order which is most common in functional neuroimaging. N.B.: The 3 methods below all give the locations of the voxel centers in the (x,y,z) coordinate system. In many cases, programs will wish to display image data on some other grid. In such a case, the program will need to convert its desired (x,y,z) values into (i,j,k) values in order to extract (or interpolate) the image data. This operation would be done with the inverse transformation to those described below. N.B.: Method 2 uses a factor 'qfac' which is either -1 or 1; qfac is stored in the otherwise unused pixdim[0]. If pixdim[0]=0.0 (which should not occur), we take qfac=1. Of course, pixdim[0] is only used when reading a NIFTI-1 header, not when reading an ANALYZE 7.5 header. N.B.: The units of (x,y,z) can be specified using the xyzt_units field. METHOD 1 (the "old" way, used only when qform_code = 0): ------------------------------------------------------- The coordinate mapping from (i,j,k) to (x,y,z) is the ANALYZE 7.5 way. This is a simple scaling relationship: x = pixdim[1] * i y = pixdim[2] * j z = pixdim[3] * k No particular spatial orientation is attached to these (x,y,z) coordinates. (NIFTI-1 does not have the ANALYZE 7.5 orient field, which is not general and is often not set properly.) This method is not recommended, and is present mainly for compatibility with ANALYZE 7.5 files. METHOD 2 (used when qform_code > 0, which should be the "normal" case): --------------------------------------------------------------------- The (x,y,z) coordinates are given by the pixdim[] scales, a rotation matrix, and a shift. This method is intended to represent "scanner-anatomical" coordinates, which are often embedded in the image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030), and (0018,0050)), and represent the nominal orientation and location of the data. This method can also be used to represent "aligned" coordinates, which would typically result from some post-acquisition alignment of the volume to a standard orientation (e.g., the same subject on another day, or a rigid rotation to true anatomical orientation from the tilted position of the subject in the scanner). The formula for (x,y,z) in terms of header parameters and (i,j,k) is: [ x ] [ R11 R12 R13 ] [ pixdim[1] * i ] [ qoffset_x ] [ y ] = [ R21 R22 R23 ] [ pixdim[2] * j ] + [ qoffset_y ] [ z ] [ R31 R32 R33 ] [ qfac * pixdim[3] * k ] [ qoffset_z ] The qoffset_* shifts are in the NIFTI-1 header. Note that the center of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z). The rotation matrix R is calculated from the quatern_* parameters. This calculation is described below. The scaling factor qfac is either 1 or -1. The rotation matrix R defined by the quaternion parameters is "proper" (has determinant 1). This may not fit the needs of the data; for example, if the image grid is i increases from Left-to-Right j increases from Anterior-to-Posterior k increases from Inferior-to-Superior Then (i,j,k) is a left-handed triple. In this example, if qfac=1, the R matrix would have to be [ 1 0 0 ] [ 0 -1 0 ] which is "improper" (determinant = -1). [ 0 0 1 ] If we set qfac=-1, then the R matrix would be [ 1 0 0 ] [ 0 -1 0 ] which is proper. [ 0 0 -1 ] This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0] (which encodes a 180 degree rotation about the x-axis). METHOD 3 (used when sform_code > 0): ----------------------------------- The (x,y,z) coordinates are given by a general affine transformation of the (i,j,k) indexes: x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3] y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3] z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3] The srow_* vectors are in the NIFTI_1 header. Note that no use is made of pixdim[] in this method. WHY 3 METHODS? -------------- Method 1 is provided only for backwards compatibility. The intention is that Method 2 (qform_code > 0) represents the nominal voxel locations as reported by the scanner, or as rotated to some fiducial orientation and location. Method 3, if present (sform_code > 0), is to be used to give the location of the voxels in some standard space. The sform_code indicates which standard space is present. Both methods 2 and 3 can be present, and be useful in different contexts (method 2 for displaying the data on its original grid; method 3 for displaying it on a standard grid). In this scheme, a dataset would originally be set up so that the Method 2 coordinates represent what the scanner reported. Later, a registration to some standard space can be computed and inserted in the header. Image display software can use either transform, depending on its purposes and needs. In Method 2, the origin of coordinates would generally be whatever the scanner origin is; for example, in MRI, (0,0,0) is the center of the gradient coil. In Method 3, the origin of coordinates would depend on the value of sform_code; for example, for the Talairach coordinate system, (0,0,0) corresponds to the Anterior Commissure. QUATERNION REPRESENTATION OF ROTATION MATRIX (METHOD 2) ------------------------------------------------------- The orientation of the (x,y,z) axes relative to the (i,j,k) axes in 3D space is specified using a unit quaternion [a,b,c,d], where a*a+b*b+c*c+d*d=1. The (b,c,d) values are all that is needed, since we require that a = sqrt(1.0-(b*b+c*c+d*d)) be nonnegative. The (b,c,d) values are stored in the (quatern_b,quatern_c,quatern_d) fields. The quaternion representation is chosen for its compactness in representing rotations. The (proper) 3x3 rotation matrix that corresponds to [a,b,c,d] is [ a*a+b*b-c*c-d*d 2*b*c-2*a*d 2*b*d+2*a*c ] R = [ 2*b*c+2*a*d a*a+c*c-b*b-d*d 2*c*d-2*a*b ] [ 2*b*d-2*a*c 2*c*d+2*a*b a*a+d*d-c*c-b*b ] [ R11 R12 R13 ] = [ R21 R22 R23 ] [ R31 R32 R33 ] If (p,q,r) is a unit 3-vector, then rotation of angle h about that direction is represented by the quaternion [a,b,c,d] = [cos(h/2), p*sin(h/2), q*sin(h/2), r*sin(h/2)]. Requiring a >= 0 is equivalent to requiring -Pi <= h <= Pi. (Note that [-a,-b,-c,-d] represents the same rotation as [a,b,c,d]; there are 2 quaternions that can be used to represent a given rotation matrix R.) To rotate a 3-vector (x,y,z) using quaternions, we compute the quaternion product [0,x',y',z'] = [a,b,c,d] * [0,x,y,z] * [a,-b,-c,-d] which is equivalent to the matrix-vector multiply [ x' ] [ x ] [ y' ] = R [ y ] (equivalence depends on a*a+b*b+c*c+d*d=1) [ z' ] [ z ] Multiplication of 2 quaternions is defined by the following: [a,b,c,d] = a*1 + b*I + c*J + d*K where I*I = J*J = K*K = -1 (I,J,K are square roots of -1) I*J = K J*K = I K*I = J J*I = -K K*J = -I I*K = -J (not commutative!) For example [a,b,0,0] * [0,0,0,1] = [0,0,-b,a] since this expands to (a+b*I)*(K) = (a*K+b*I*K) = (a*K-b*J). The above formula shows how to go from quaternion (b,c,d) to rotation matrix and direction cosines. Conversely, given R, we can compute the fields for the NIFTI-1 header by a = 0.5 * sqrt(1+R11+R22+R33) (not stored) b = 0.25 * (R32-R23) / a => quatern_b c = 0.25 * (R13-R31) / a => quatern_c d = 0.25 * (R21-R12) / a => quatern_d If a=0 (a 180 degree rotation), alternative formulas are needed. See the nifti1_io.c function mat44_to_quatern() for an implementation of the various cases in converting R to [a,b,c,d]. Note that R-transpose (= R-inverse) would lead to the quaternion [a,-b,-c,-d]. The choice to specify the qoffset_x (etc.) values in the final coordinate system is partly to make it easy to convert DICOM images to this format. The DICOM attribute "Image Position (Patient)" (0020,0032) stores the (Xd,Yd,Zd) coordinates of the center of the first voxel. Here, (Xd,Yd,Zd) refer to DICOM coordinates, and Xd=-x, Yd=-y, Zd=z, where (x,y,z) refers to the NIFTI coordinate system discussed above. (i.e., DICOM +Xd is Left, +Yd is Posterior, +Zd is Superior, whereas +x is Right, +y is Anterior , +z is Superior. ) Thus, if the (0020,0032) DICOM attribute is extracted into (px,py,pz), then qoffset_x = -px qoffset_y = -py qoffset_z = pz is a reasonable setting when qform_code=NIFTI_XFORM_SCANNER_ANAT. That is, DICOM's coordinate system is 180 degrees rotated about the z-axis from the neuroscience/NIFTI coordinate system. To transform between DICOM and NIFTI, you just have to negate the x- and y-coordinates. The DICOM attribute (0020,0037) "Image Orientation (Patient)" gives the orientation of the x- and y-axes of the image data in terms of 2 3-vectors. The first vector is a unit vector along the x-axis, and the second is along the y-axis. If the (0020,0037) attribute is extracted into the value (xa,xb,xc,ya,yb,yc), then the first two columns of the R matrix would be [ -xa -ya ] [ -xb -yb ] [ xc yc ] The negations are because DICOM's x- and y-axes are reversed relative to NIFTI's. The third column of the R matrix gives the direction of displacement (relative to the subject) along the slice-wise direction. This orientation is not encoded in the DICOM standard in a simple way; DICOM is mostly concerned with 2D images. The third column of R will be either the cross-product of the first 2 columns or its negative. It is possible to infer the sign of the 3rd column by examining the coordinates in DICOM attribute (0020,0032) "Image Position (Patient)" for successive slices. However, this method occasionally fails for reasons that I (RW Cox) do not understand. -----------------------------------------------------------------------------*/ /* [qs]form_code value: */ /* x,y,z coordinate system refers to: */ /*-----------------------*/ /*---------------------------------------*/ /*! \defgroup NIFTI1_XFORM_CODES \brief nifti1 xform codes to describe the "standard" coordinate system @{ */ /*! Arbitrary coordinates (Method 1). */ #define NIFTI_XFORM_UNKNOWN 0 /*! Scanner-based anatomical coordinates */ #define NIFTI_XFORM_SCANNER_ANAT 1 /*! Coordinates aligned to another file's, or to anatomical "truth". */ #define NIFTI_XFORM_ALIGNED_ANAT 2 /*! Coordinates aligned to Talairach- Tournoux Atlas; (0,0,0)=AC, etc. */ #define NIFTI_XFORM_TALAIRACH 3 /*! MNI 152 normalized coordinates. */ #define NIFTI_XFORM_MNI_152 4 /* @} */ /*---------------------------------------------------------------------------*/ /* UNITS OF SPATIAL AND TEMPORAL DIMENSIONS: ---------------------------------------- The codes below can be used in xyzt_units to indicate the units of pixdim. As noted earlier, dimensions 1,2,3 are for x,y,z; dimension 4 is for time (t). - If dim[4]=1 or dim[0] < 4, there is no time axis. - A single time series (no space) would be specified with - dim[0] = 4 (for scalar data) or dim[0] = 5 (for vector data) - dim[1] = dim[2] = dim[3] = 1 - dim[4] = number of time points - pixdim[4] = time step - xyzt_units indicates units of pixdim[4] - dim[5] = number of values stored at each time point Bits 0..2 of xyzt_units specify the units of pixdim[1..3] (e.g., spatial units are values 1..7). Bits 3..5 of xyzt_units specify the units of pixdim[4] (e.g., temporal units are multiples of 8). This compression of 2 distinct concepts into 1 byte is due to the limited space available in the 348 byte ANALYZE 7.5 header. The macros XYZT_TO_SPACE and XYZT_TO_TIME can be used to mask off the undesired bits from the xyzt_units fields, leaving "pure" space and time codes. Inversely, the macro SPACE_TIME_TO_XYZT can be used to assemble a space code (0,1,2,...,7) with a time code (0,8,16,32,...,56) into the combined value for xyzt_units. Note that codes are provided to indicate the "time" axis units are actually frequency in Hertz (_HZ), in part-per-million (_PPM) or in radians-per-second (_RADS). The toffset field can be used to indicate a nonzero start point for the time axis. That is, time point #m is at t=toffset+m*pixdim[4] for m=0..dim[4]-1. -----------------------------------------------------------------------------*/ /*! \defgroup NIFTI1_UNITS \brief nifti1 units codes to describe the unit of measurement for each dimension of the dataset @{ */ /*! NIFTI code for unspecified units. */ #define NIFTI_UNITS_UNKNOWN 0 /** Space codes are multiples of 1. **/ /*! NIFTI code for meters. */ #define NIFTI_UNITS_METER 1 /*! NIFTI code for millimeters. */ #define NIFTI_UNITS_MM 2 /*! NIFTI code for micrometers. */ #define NIFTI_UNITS_MICRON 3 /** Time codes are multiples of 8. **/ /*! NIFTI code for seconds. */ #define NIFTI_UNITS_SEC 8 /*! NIFTI code for milliseconds. */ #define NIFTI_UNITS_MSEC 16 /*! NIFTI code for microseconds. */ #define NIFTI_UNITS_USEC 24 /*** These units are for spectral data: ***/ /*! NIFTI code for Hertz. */ #define NIFTI_UNITS_HZ 32 /*! NIFTI code for ppm. */ #define NIFTI_UNITS_PPM 40 /*! NIFTI code for radians per second. */ #define NIFTI_UNITS_RADS 48 /* @} */ #undef XYZT_TO_SPACE #undef XYZT_TO_TIME #define XYZT_TO_SPACE(xyzt) ( (xyzt) & 0x07 ) #define XYZT_TO_TIME(xyzt) ( (xyzt) & 0x38 ) #undef SPACE_TIME_TO_XYZT #define SPACE_TIME_TO_XYZT(ss,tt) ( (((char)(ss)) & 0x07) \ | (((char)(tt)) & 0x38) ) /*---------------------------------------------------------------------------*/ /* MRI-SPECIFIC SPATIAL AND TEMPORAL INFORMATION: --------------------------------------------- A few fields are provided to store some extra information that is sometimes important when storing the image data from an FMRI time series experiment. (After processing such data into statistical images, these fields are not likely to be useful.) { freq_dim } = These fields encode which spatial dimension (1,2, or 3) { phase_dim } = corresponds to which acquisition dimension for MRI data. { slice_dim } = Examples: Rectangular scan multi-slice EPI: freq_dim = 1 phase_dim = 2 slice_dim = 3 (or some permutation) Spiral scan multi-slice EPI: freq_dim = phase_dim = 0 slice_dim = 3 since the concepts of frequency- and phase-encoding directions don't apply to spiral scan slice_duration = If this is positive, AND if slice_dim is nonzero, indicates the amount of time used to acquire 1 slice. slice_duration*dim[slice_dim] can be less than pixdim[4] with a clustered acquisition method, for example. slice_code = If this is nonzero, AND if slice_dim is nonzero, AND if slice_duration is positive, indicates the timing pattern of the slice acquisition. The following codes are defined: NIFTI_SLICE_SEQ_INC == sequential increasing NIFTI_SLICE_SEQ_DEC == sequential decreasing NIFTI_SLICE_ALT_INC == alternating increasing NIFTI_SLICE_ALT_DEC == alternating decreasing NIFTI_SLICE_ALT_INC2 == alternating increasing #2 NIFTI_SLICE_ALT_DEC2 == alternating decreasing #2 { slice_start } = Indicates the start and end of the slice acquisition { slice_end } = pattern, when slice_code is nonzero. These values are present to allow for the possible addition of "padded" slices at either end of the volume, which don't fit into the slice timing pattern. If there are no padding slices, then slice_start=0 and slice_end=dim[slice_dim]-1 are the correct values. For these values to be meaningful, slice_start must be non-negative and slice_end must be greater than slice_start. Otherwise, they should be ignored. The following table indicates the slice timing pattern, relative to time=0 for the first slice acquired, for some sample cases. Here, dim[slice_dim]=7 (there are 7 slices, labeled 0..6), slice_duration=0.1, and slice_start=1, slice_end=5 (1 padded slice on each end). slice index SEQ_INC SEQ_DEC ALT_INC ALT_DEC ALT_INC2 ALT_DEC2 6 : n/a n/a n/a n/a n/a n/a n/a = not applicable 5 : 0.4 0.0 0.2 0.0 0.4 0.2 (slice time offset 4 : 0.3 0.1 0.4 0.3 0.1 0.0 doesn't apply to 3 : 0.2 0.2 0.1 0.1 0.3 0.3 slices outside 2 : 0.1 0.3 0.3 0.4 0.0 0.1 the range 1 : 0.0 0.4 0.0 0.2 0.2 0.4 slice_start .. 0 : n/a n/a n/a n/a n/a n/a slice_end) The SEQ slice_codes are sequential ordering (uncommon but not unknown), either increasing in slice number or decreasing (INC or DEC), as illustrated above. The ALT slice codes are alternating ordering. The 'standard' way for these to operate (without the '2' on the end) is for the slice timing to start at the edge of the slice_start .. slice_end group (at slice_start for INC and at slice_end for DEC). For the 'ALT_*2' slice_codes, the slice timing instead starts at the first slice in from the edge (at slice_start+1 for INC2 and at slice_end-1 for DEC2). This latter acquisition scheme is found on some Siemens scanners. The fields freq_dim, phase_dim, slice_dim are all squished into the single byte field dim_info (2 bits each, since the values for each field are limited to the range 0..3). This unpleasantness is due to lack of space in the 348 byte allowance. The macros DIM_INFO_TO_FREQ_DIM, DIM_INFO_TO_PHASE_DIM, and DIM_INFO_TO_SLICE_DIM can be used to extract these values from the dim_info byte. The macro FPS_INTO_DIM_INFO can be used to put these 3 values into the dim_info byte. -----------------------------------------------------------------------------*/ #undef DIM_INFO_TO_FREQ_DIM #undef DIM_INFO_TO_PHASE_DIM #undef DIM_INFO_TO_SLICE_DIM #define DIM_INFO_TO_FREQ_DIM(di) ( ((di) ) & 0x03 ) #define DIM_INFO_TO_PHASE_DIM(di) ( ((di) >> 2) & 0x03 ) #define DIM_INFO_TO_SLICE_DIM(di) ( ((di) >> 4) & 0x03 ) #undef FPS_INTO_DIM_INFO #define FPS_INTO_DIM_INFO(fd,pd,sd) ( ( ( ((char)(fd)) & 0x03) ) | \ ( ( ((char)(pd)) & 0x03) << 2 ) | \ ( ( ((char)(sd)) & 0x03) << 4 ) ) /*! \defgroup NIFTI1_SLICE_ORDER \brief nifti1 slice order codes, describing the acquisition order of the slices @{ */ #define NIFTI_SLICE_UNKNOWN 0 #define NIFTI_SLICE_SEQ_INC 1 #define NIFTI_SLICE_SEQ_DEC 2 #define NIFTI_SLICE_ALT_INC 3 #define NIFTI_SLICE_ALT_DEC 4 #define NIFTI_SLICE_ALT_INC2 5 /* 05 May 2005: RWCox */ #define NIFTI_SLICE_ALT_DEC2 6 /* 05 May 2005: RWCox */ /* @} */ /*---------------------------------------------------------------------------*/ /* UNUSED FIELDS: ------------- Some of the ANALYZE 7.5 fields marked as ++UNUSED++ may need to be set to particular values for compatibility with other programs. The issue of interoperability of ANALYZE 7.5 files is a murky one -- not all programs require exactly the same set of fields. (Unobscuring this murkiness is a principal motivation behind NIFTI-1.) Some of the fields that may need to be set for other (non-NIFTI aware) software to be happy are: extents dbh.h says this should be 16384 regular dbh.h says this should be the character 'r' glmin, } dbh.h says these values should be the min and max voxel glmax } values for the entire dataset It is best to initialize ALL fields in the NIFTI-1 header to 0 (e.g., with calloc()), then fill in what is needed. -----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* MISCELLANEOUS C MACROS -----------------------------------------------------------------------------*/ /*.................*/ /*! Given a nifti_1_header struct, check if it has a good magic number. Returns NIFTI version number (1..9) if magic is good, 0 if it is not. */ #define NIFTI_VERSION(h) \ ( ( (h).magic[0]=='n' && (h).magic[3]=='\0' && \ ( (h).magic[1]=='i' || (h).magic[1]=='+' ) && \ ( (h).magic[2]>='1' && (h).magic[2]<='9' ) ) \ ? (h).magic[2]-'0' : 0 ) /*.................*/ /*! Check if a nifti_1_header struct says if the data is stored in the same file or in a separate file. Returns 1 if the data is in the same file as the header, 0 if it is not. */ #define NIFTI_ONEFILE(h) ( (h).magic[1] == '+' ) /*.................*/ /*! Check if a nifti_1_header struct needs to be byte swapped. Returns 1 if it needs to be swapped, 0 if it does not. */ #define NIFTI_NEEDS_SWAP(h) ( (h).dim[0] < 0 || (h).dim[0] > 7 ) /*.................*/ /*! Check if a nifti_1_header struct contains a 5th (vector) dimension. Returns size of 5th dimension if > 1, returns 0 otherwise. */ #define NIFTI_5TH_DIM(h) ( ((h).dim[0]>4 && (h).dim[5]>1) ? (h).dim[5] : 0 ) /*****************************************************************************/ /*=================*/ #ifdef __cplusplus } #endif /*=================*/ #endif /* _NIFTI_HEADER_ */ minc-2.2.00/conversion/nifti1/nifti1_io.h0000644000265600003100000004432212027132661015055 00000000000000/** \file nifti1_io.h \brief Data structures for using nifti1_io API. - Written by Bob Cox, SSCC NIMH - Revisions by Rick Reynolds, SSCC NIMH */ #ifndef _NIFTI_IO_HEADER_ #define _NIFTI_IO_HEADER_ #include #include #include #include #include #ifndef DONT_INCLUDE_ANALYZE_STRUCT #define DONT_INCLUDE_ANALYZE_STRUCT /*** not needed herein ***/ #endif #include "nifti1.h" /*** NIFTI-1 header specification ***/ #include "znzlib.h" /*=================*/ #ifdef __cplusplus extern "C" { #endif /*=================*/ /*****===================================================================*****/ /***** File nifti1_io.h == Declarations for nifti1_io.c *****/ /*****...................................................................*****/ /***** This code is released to the public domain. *****/ /*****...................................................................*****/ /***** Author: Robert W Cox, SSCC/DIRP/NIMH/NIH/DHHS/USA/EARTH *****/ /***** Date: August 2003 *****/ /*****...................................................................*****/ /***** Neither the National Institutes of Health (NIH), nor any of its *****/ /***** employees imply any warranty of usefulness of this software for *****/ /***** any purpose, and do not assume any liability for damages, *****/ /***** incidental or otherwise, caused by any use of this document. *****/ /*****===================================================================*****/ /* Modified by: Mark Jenkinson (FMRIB Centre, University of Oxford, UK) Date: July/August 2004 Mainly adding low-level IO and changing things to allow gzipped files to be read and written Full backwards compatability should have been maintained Modified by: Rick Reynolds (SSCC/DIRP/NIMH, National Institutes of Health) Date: December 2004 Modified and added many routines for I/O. */ /********************** Some sample data structures **************************/ typedef struct { /** 4x4 matrix struct **/ float m[4][4] ; } mat44 ; typedef struct { /** 3x3 matrix struct **/ float m[3][3] ; } mat33 ; /*...........................................................................*/ /*! \struct nifti_image \brief High level data structure for open nifti datasets in the nifti1_io API. Note that this structure is not part of the nifti1 format definition; it is used to implement one API for reading/writing formats in the nifti1 format. */ typedef struct { /*!< Image storage struct **/ int ndim ; /*!< last dimension greater than 1 (1..7) */ int nx ; /*!< dimensions of grid array */ int ny ; /*!< dimensions of grid array */ int nz ; /*!< dimensions of grid array */ int nt ; /*!< dimensions of grid array */ int nu ; /*!< dimensions of grid array */ int nv ; /*!< dimensions of grid array */ int nw ; /*!< dimensions of grid array */ int dim[8] ; /*!< dim[0]=ndim, dim[1]=nx, etc. */ int nvox ; /*!< number of voxels = nx*ny*nz*...*nw */ int nbyper ; /*!< bytes per voxel, matches datatype */ int datatype ; /*!< type of data in voxels: DT_* code */ float dx ; /*!< grid spacings */ float dy ; /*!< grid spacings */ float dz ; /*!< grid spacings */ float dt ; /*!< grid spacings */ float du ; /*!< grid spacings */ float dv ; /*!< grid spacings */ float dw ; /*!< grid spacings */ float pixdim[8] ; /*!< pixdim[1]=dx, etc. */ float scl_slope ; /*!< scaling parameter - slope */ float scl_inter ; /*!< scaling parameter - intercept */ float cal_min ; /*!< calibration parameter, minimum */ float cal_max ; /*!< calibration parameter, maximum */ int qform_code ; /*!< codes for (x,y,z) space meaning */ int sform_code ; /*!< codes for (x,y,z) space meaning */ int freq_dim ; /*!< indexes (1,2,3, or 0) for MRI */ int phase_dim ; /*!< directions in dim[]/pixdim[] */ int slice_dim ; /*!< directions in dim[]/pixdim[] */ int slice_code ; /*!< code for slice timing pattern */ int slice_start ; /*!< index for start of slices */ int slice_end ; /*!< index for end of slices */ float slice_duration ; /*!< time between individual slices */ /*! quaternion transform parameters [when writing a dataset, these are used for qform, NOT qto_xyz] */ float quatern_b , quatern_c , quatern_d , qoffset_x , qoffset_y , qoffset_z , qfac ; mat44 qto_xyz ; /*!< qform: transform (i,j,k) to (x,y,z) */ mat44 qto_ijk ; /*!< qform: transform (x,y,z) to (i,j,k) */ mat44 sto_xyz ; /*!< sform: transform (i,j,k) to (x,y,z) */ mat44 sto_ijk ; /*!< sform: transform (x,y,z) to (i,j,k) */ float toffset ; /*!< time coordinate offset */ int xyz_units ; /*!< dx,dy,dz units: NIFTI_UNITS_* code */ int time_units ; /*!< dt units: NIFTI_UNITS_* code */ int nifti_type ; /*!< 0==ANALYZE, 1==NIFTI-1 (1 file), 2==NIFTI-1 (2 files), 3==NIFTI-ASCII (1 file) */ int intent_code ; /*!< statistic type (or something) */ float intent_p1 ; /*!< intent parameters */ float intent_p2 ; /*!< intent parameters */ float intent_p3 ; /*!< intent parameters */ char intent_name[16] ; /*!< optional description of intent data */ char descrip[80] ; /*!< optional text to describe dataset */ char aux_file[24] ; /*!< auxiliary filename */ char *fname ; /*!< header filename (.hdr or .nii) */ char *iname ; /*!< image filename (.img or .nii) */ int iname_offset ; /*!< offset into iname where data starts */ int swapsize ; /*!< swap unit in image data (might be 0) */ int byteorder ; /*!< byte order on disk (MSB_ or LSB_FIRST) */ void *data ; /*!< pointer to data: nbyper*nvox bytes */ int num_ext ; /*!< number of extensions in ext_list */ nifti1_extension * ext_list ; /*!< array of extension structs (with data) */ } nifti_image ; /* struct for return from nifti_image_read_bricks() */ typedef struct { int nbricks; /* the number of allocated pointers in 'bricks' */ int bsize; /* the length of each data block, in bytes */ void ** bricks; /* array of pointers to data blocks */ } nifti_brick_list; /*****************************************************************************/ /*--------------- Prototypes of functions defined in this file --------------*/ char *nifti_datatype_string ( int dt ) ; char *nifti_units_string ( int uu ) ; char *nifti_intent_string ( int ii ) ; char *nifti_xform_string ( int xx ) ; char *nifti_slice_string ( int ss ) ; char *nifti_orientation_string( int ii ) ; int nifti_is_inttype( int dt ) ; mat44 nifti_mat44_inverse( mat44 R ) ; mat33 nifti_mat33_inverse( mat33 R ) ; mat33 nifti_mat33_polar ( mat33 A ) ; float nifti_mat33_rownorm( mat33 A ) ; float nifti_mat33_colnorm( mat33 A ) ; float nifti_mat33_determ ( mat33 R ) ; mat33 nifti_mat33_mul ( mat33 A , mat33 B ) ; void nifti_swap_2bytes ( int n , void *ar ) ; void nifti_swap_4bytes ( int n , void *ar ) ; void nifti_swap_8bytes ( int n , void *ar ) ; void nifti_swap_16bytes( int n , void *ar ) ; void nifti_swap_Nbytes ( int n , int siz , void *ar ) ; void swap_nifti_header ( struct nifti_1_header *h , int is_nifti ) ; int nifti_get_filesize( const char *pathname ) ; /* main read/write routines */ nifti_image *nifti_image_read_bricks(const char *hname , int nbricks, const int *blist, nifti_brick_list * NBL); int nifti_image_load_bricks(nifti_image *nim , int nbricks, const int *blist, nifti_brick_list * NBL); void nifti_free_NBL( nifti_brick_list * NBL ); nifti_image *nifti_image_read ( const char *hname , int read_data ) ; int nifti_image_load ( nifti_image *nim ) ; void nifti_image_unload ( nifti_image *nim ) ; void nifti_image_free ( nifti_image *nim ) ; int nifti_read_collapsed_image( nifti_image * nim, const int dims [8], void ** data ); void nifti_image_write ( nifti_image * nim ) ; void nifti_image_write_bricks(nifti_image * nim, const nifti_brick_list * NBL); void nifti_image_infodump( const nifti_image * nim ) ; void nifti_disp_lib_hist( void ) ; /* to display library history */ void nifti_disp_lib_version( void ) ; /* to display library version */ int nifti_disp_matrix_orient( const char * mesg, mat44 mat ); char * nifti_image_to_ascii ( const nifti_image * nim ) ; nifti_image *nifti_image_from_ascii( const char * str, int * bytes_read ) ; size_t nifti_get_volsize(const nifti_image *nim) ; /* basic file operations */ int nifti_set_filenames(nifti_image * nim, const char * prefix, int check, int set_byte_order); char * nifti_makehdrname (const char * prefix, int nifti_type, int check, int comp); char * nifti_makeimgname (const char * prefix, int nifti_type, int check, int comp); int is_nifti_file (const char *hname); char * nifti_find_file_extension(const char * name); int nifti_is_complete_filename(const char* fname); int nifti_validfilename(const char* fname); int disp_nifti_1_header(const char * info, const nifti_1_header * hp ) ; void nifti_set_debug_level( int level ) ; void nifti_set_skip_blank_ext( int skip ) ; int valid_nifti_brick_list(nifti_image * nim , int nbricks, const int * blist, int disp_error); /* znzFile operations */ znzFile nifti_image_open(const char * hname, char * opts, nifti_image ** nim); znzFile nifti_image_write_hdr_img(nifti_image *nim, int write_data, const char* opts); znzFile nifti_image_write_hdr_img2( nifti_image *nim , int write_opts , const char* opts, znzFile imgfile, const nifti_brick_list * NBL); size_t nifti_read_buffer(znzFile fp, void* datatptr, size_t ntot, nifti_image *nim); int nifti_write_all_data(znzFile fp, nifti_image * nim, const nifti_brick_list * NBL); size_t nifti_write_buffer(znzFile fp, const void * buffer, size_t numbytes); nifti_image *nifti_read_ascii_image(znzFile fp, char *fname, int flen, int read_data); znzFile nifti_write_ascii_image(nifti_image *nim, const nifti_brick_list * NBL, const char * opts, int write_data, int leave_open); void nifti_datatype_sizes( int datatype , int *nbyper, int *swapsize ) ; void nifti_mat44_to_quatern( mat44 R , float *qb, float *qc, float *qd, float *qx, float *qy, float *qz, float *dx, float *dy, float *dz, float *qfac ) ; mat44 nifti_quatern_to_mat44( float qb, float qc, float qd, float qx, float qy, float qz, float dx, float dy, float dz, float qfac ); mat44 nifti_make_orthog_mat44( float r11, float r12, float r13 , float r21, float r22, float r23 , float r31, float r32, float r33 ) ; int nifti_short_order(void) ; /* CPU byte order */ /* Orientation codes that might be returned from nifti_mat44_to_orientation().*/ #define NIFTI_L2R 1 /* Left to Right */ #define NIFTI_R2L 2 /* Right to Left */ #define NIFTI_P2A 3 /* Posterior to Anterior */ #define NIFTI_A2P 4 /* Anterior to Posterior */ #define NIFTI_I2S 5 /* Inferior to Superior */ #define NIFTI_S2I 6 /* Superior to Inferior */ void nifti_mat44_to_orientation( mat44 R , int *icod, int *jcod, int *kcod ) ; /*--------------------- Low level IO routines ------------------------------*/ char * nifti_findhdrname (const char* fname); char * nifti_findimgname (const char* fname , int nifti_type); int nifti_is_gzfile (const char* fname); char * nifti_makebasename(const char* fname); /* other routines */ struct nifti_1_header nifti_convert_nim2nhdr(const nifti_image* nim); nifti_1_header * nifti_read_header(const char *hname, int *swapped, int check); nifti_image * nifti_copy_nim_info(const nifti_image * src); nifti_image * nifti_simple_init_nim(void); nifti_image * nifti_convert_nhdr2nim(struct nifti_1_header nhdr, const char * fname); int nifti_hdr_looks_good (const nifti_1_header * hdr); int nifti_is_valid_ecode (int ecode); int nifti_nim_is_valid (nifti_image * nim, int complain); int nifti_nim_has_valid_dims (nifti_image * nim, int complain); int is_valid_nifti_type (int nifti_type); int nifti_type_and_names_match (nifti_image * nim, int show_warn); int nifti_update_dims_from_array(nifti_image * nim); void nifti_set_iname_offset (nifti_image *nim); int nifti_set_type_from_names (nifti_image * nim); int nifti_add_extension(nifti_image * nim, const char * data, int len, int ecode ); int nifti_copy_extensions (nifti_image *nim_dest,const nifti_image *nim_src); int nifti_free_extensions (nifti_image *nim); int * nifti_get_intlist (int nvals , const char *str); char * nifti_strdup (const char *str); int valid_nifti_extensions(const nifti_image *nim); /*-------------------- Some C convenience macros ----------------------------*/ /* NIfTI-1.1 extension codes: see http://nifti.nimh.nih.gov/nifti-1/documentation/faq#Q21 */ #define NIFTI_ECODE_IGNORE 0 /* changed from UNKNOWN, 29 June 2005 */ #define NIFTI_ECODE_DICOM 2 /* intended for raw DICOM attributes */ #define NIFTI_ECODE_AFNI 4 /* Robert W Cox: rwcox@nih.gov http://afni.nimh.nih.gov/afni */ #define NIFTI_ECODE_COMMENT 6 /* plain ASCII text only */ #define NIFTI_ECODE_XCEDE 8 /* David B Keator: dbkeator@uci.edu http://www.nbirn.net/Resources /Users/Applications/ /xcede/index.htm */ #define NIFTI_ECODE_JIMDIMINFO 10 /* Mark A Horsfield: mah5@leicester.ac.uk http://someplace/something */ #define NIFTI_ECODE_WORKFLOW_FWDS 12 /* Kate Fissell: fissel+@pitt.edu http://kraepelin.wpic.pitt.edu /~fissell/NIFTI_ECODE_WORKFLOW_FWDS /NIFTI_ECODE_WORKFLOW_FWDS.html */ #define NIFTI_MAX_ECODE 12 /******* maximum extension code *******/ /* nifti_type file codes */ #define NIFTI_FTYPE_ANALYZE 0 #define NIFTI_FTYPE_NIFTI1_1 1 #define NIFTI_FTYPE_NIFTI1_2 2 #define NIFTI_FTYPE_ASCII 3 #define NIFTI_MAX_FTYPE 3 /* this should match the maximum code */ /*------------------------------------------------------------------------*/ /*-- the rest of these apply only to nifti1_io.c, check for _NIFTI1_IO_C_ */ /* Feb 9, 2005 [rickr] */ #ifdef _NIFTI1_IO_C_ typedef struct { int debug; /*!< debug level for status reports */ int skip_blank_ext; /*!< skip extender if no extensions */ } nifti_global_options; #undef LNI_FERR /* local nifti file error, to be compact and repetative */ #define LNI_FERR(func,msg,file) \ fprintf(stderr,"** ERROR (%s): %s '%s'\n",func,msg,file) #undef swap_2 #undef swap_4 #define swap_2(s) nifti_swap_2bytes(1,&(s)) /* s: 2-byte short; swap in place */ #define swap_4(v) nifti_swap_4bytes(1,&(v)) /* v: 4-byte value; swap in place */ /***** isfinite() is a C99 macro, which is present in many C implementations already *****/ #undef IS_GOOD_FLOAT #undef FIXED_FLOAT #ifdef isfinite /* use isfinite() to check floats/doubles for goodness */ # define IS_GOOD_FLOAT(x) isfinite(x) /* check if x is a "good" float */ # define FIXED_FLOAT(x) (isfinite(x) ? (x) : 0) /* fixed if bad */ #else # define IS_GOOD_FLOAT(x) 1 /* don't check it */ # define FIXED_FLOAT(x) (x) /* don't fix it */ #endif #undef ASSIF /* assign v to *p, if possible */ #define ASSIF(p,v) if( (p)!=NULL ) *(p) = (v) #undef MSB_FIRST #undef LSB_FIRST #undef REVERSE_ORDER #define LSB_FIRST 1 #define MSB_FIRST 2 #define REVERSE_ORDER(x) (3-(x)) /* convert MSB_FIRST <--> LSB_FIRST */ #define LNI_MAX_NIA_EXT_LEN 100000 /* consider a longer extension invalid */ #endif /* _NIFTI1_IO_C_ section */ /*------------------------------------------------------------------------*/ /*=================*/ #ifdef __cplusplus } #endif /*=================*/ #endif /* _NIFTI_IO_HEADER_ */ minc-2.2.00/conversion/nifti1/nifti1_local.h0000644000265600003100000000321312027132661015532 00000000000000/* Additional things we define for the NIfTI-1 format. Some of these * should probably be included in the header files. */ /* NIfTI-1 (Analyze 7.5) files can have at most 8 dimensions. This should * be defined in nifti1.h */ #define MAX_NII_DIMS 8 /* Length of NIfTI-1 description field. Should be defined in nifti1.h */ #define MAX_NII_DESCRIP 80 /* File types. These should be part of the nifti1_io.h header. */ #define FT_UNSPECIFIED (-1) #define FT_ANALYZE 0 #define FT_NIFTI_SINGLE 1 #define FT_NIFTI_DUAL 2 #define FT_NIFTI_ASCII 3 /****** * Private stuff we use for mapping NIfTI-1 dimensions onto MINC dimensions. **/ /* # spatial dimensions */ #define MAX_SPACE_DIMS 3 /* World coordinates */ #define DIM_X 0 #define DIM_Y 1 #define DIM_Z 2 /* Voxel coordinates */ #define DIM_I 0 #define DIM_J 1 #define DIM_K 2 #define DIMORDER_ZYX 0 #define DIMORDER_YZX 1 #define DIMORDER_XZY 2 #define DIMORDER_XYZ 3 #define DIMORDER_ZXY 4 #define DIMORDER_YXZ 5 /* Map dimension index from the actual mapping of the data array to the * "internal header array order". * * In other words, NIfTI-1 seems to store the lengths of dimensions in this * order: X, Y, Z, T, V in the dim[8] entry. * But data is actually stored with the vector dimension varying _slowest_, * with the X dimension varying _fastest_, i.e. as if it were a C array * declared array[V][T][Z][Y][X]; */ static const int dimmap[MAX_NII_DIMS] = { 4, 3, 2, 1, 0, -1, -1, -1 }; /* Names of MINC spatial dimensions, in our "standard" world ordering. */ static const char *mnc_spatial_names[MAX_SPACE_DIMS] = { MIxspace, MIyspace, MIzspace }; minc-2.2.00/conversion/nifti1/znzlib.h0000644000265600003100000000544512027132661014507 00000000000000#ifndef _ZNZLIB_H_ #define _ZNZLIB_H_ /* znzlib.h (zipped or non-zipped library) ***** This code is released to the public domain. ***** ***** Author: Mark Jenkinson, FMRIB Centre, University of Oxford ***** ***** Date: September 2004 ***** ***** Neither the FMRIB Centre, the University of Oxford, nor any of ***** ***** its employees imply any warranty of usefulness of this software ***** ***** for any purpose, and do not assume any liability for damages, ***** ***** incidental or otherwise, caused by any use of this document. ***** */ /* This library provides an interface to both compressed (gzip/zlib) and uncompressed (normal) file IO. The functions are written to have the same interface as the standard file IO functions. To use this library instead of normal file IO, the following changes are required: - replace all instances of FILE* with znzFile - change the name of all function calls, replacing the initial character f with the znz (e.g. fseek becomes znzseek) - add a third parameter to all calls to znzopen (previously fopen) that specifies whether to use compression (1) or not (0) - use znz_isnull rather than any (pointer == NULL) comparisons in the code NB: seeks for writable files with compression are quite restricted */ /*=================*/ #ifdef __cplusplus extern "C" { #endif /*=================*/ #include #include #include #include #include "config.h" #ifdef HAVE_ZLIB #if defined(ITKZLIB) #include "itk_zlib.h" #else #include "zlib.h" #endif #endif struct znzptr { int withz; FILE* nzfptr; #ifdef HAVE_ZLIB gzFile zfptr; #endif } ; /* the type for all file pointers */ typedef struct znzptr * znzFile; /* int znz_isnull(znzFile f); */ /* int znzclose(znzFile f); */ #define znz_isnull(f) ((f) == NULL) #define znzclose(f) Xznzclose(&(f)) /* Note extra argument (use_compression) where use_compression==0 is no compression use_compression!=0 uses zlib (gzip) compression */ znzFile znzopen(const char *path, const char *mode, int use_compression); znzFile znzdopen(int fd, const char *mode, int use_compression); int Xznzclose(znzFile * file); size_t znzread(void* buf, size_t size, size_t nmemb, znzFile file); size_t znzwrite(const void* buf, size_t size, size_t nmemb, znzFile file); long znzseek(znzFile file, long offset, int whence); int znzrewind(znzFile stream); long znztell(znzFile file); int znzputs(const char *str, znzFile file); char * znzgets(char* str, int size, znzFile file); int znzputc(int c, znzFile file); int znzgetc(znzFile file); #if !defined(WIN32) int znzprintf(znzFile stream, const char *format, ...); #endif /*=================*/ #ifdef __cplusplus } #endif /*=================*/ #endif minc-2.2.00/conversion/nifti1/analyze75.h0000644000265600003100000002121012027132661015002 00000000000000/* dbh.h - Analyze 7.5 header file */ /* */ /* Compiled by Andrew Janke (a.janke@gmail.com) */ /* from http://www.mayo.edu/bir/analyze/AnalyzeFileInfo.html */ /* http://homepage2.nifty.com/peco/gpetview/gpetview.html */ /* Chris Rorden - chris.rorden@nottingham.ac.uk */ /* Matthew Brett - matthew.brett@mrc-cbu.cam.ac.uk */ #define DT_NONE 0 /* No data type */ #define DT_UNKNOWN 0 /* Unknown data type */ #define DT_BINARY 1 /* Binary ( 1 bit per voxel) */ #define DT_UNSIGNED_CHAR 2 /* Unsigned character ( 8 bits per voxel) */ #define DT_SIGNED_SHORT 4 /* Signed short (16 bits per voxel) */ #define DT_SIGNED_INT 8 /* Signed integer (32 bits per voxel) */ #define DT_FLOAT 16 /* Floating point (32 bits per voxel) */ #define DT_COMPLEX 32 /* Complex (64 bits per voxel; 2 floating points) */ #define DT_DOUBLE 64 /* Double precision (64 bits per voxel) */ #define DT_RGB 128 /* Uchar x 3 (24 bits per voxel) */ #define DT_ALL 255 /* */ struct header_key{ /* off + size */ int sizeof_hdr; /* 0 + 4 - the byte size of the header file */ char data_type[10]; /* 4 + 10 - the data type of the file */ char db_name[18]; /* 14 + 18 - */ int extents; /* 32 + 4 - should be 16384 */ short int session_error; /* 36 + 2 - */ char regular; /* 38 + 1 - 'r' indicating all images/volumes are the same size */ char hkey_un0; /* 39 + 1 - */ }; /* total=40 bytes */ struct image_dimension{ /* off + size */ short int dim[8]; /* 0 + 16 - array of the image dimensions */ /* dim[0] # of dimensions in database; usually 4 */ /* dim[1] X dim - pixels in an image row */ /* dim[2] Y dim - pixel rows in slice */ /* dim[3] Z dim - slices in a volume */ /* dim[4] Time dim - volumes in database */ char vox_units[4]; /* 16 + 4 - specifies the spatial units of measure for a voxel */ char cal_units[8]; /* 20 + 8 - specifies the name of the calibration unit */ short int unused1; /* 28 + 2 */ short int datatype; /* 30 + 2 - datatype for this image set */ short int bitpix; /* 32 + 2 - # of bits per pixel 1, 8, 16, 32, or 64. */ short int dim_un0; /* 34 + 2 - */ float pixdim[8]; /* 36 + 32 - pixdim[] specifies the voxel dimensions: */ /* pixdim[1] - voxel width */ /* pixdim[2] - voxel height */ /* pixdim[3] - interslice distance */ /* ..etc */ float vox_offset; /* 68 + 4 - byte offset in the .img file at which voxels start. */ /* This value can be negative to specify that the */ /* absolute value is applied for every image */ float scale_factor; /* 72 + 4 = funused1; scale factor used by SPM; non standard */ float funused1; /* 76 + 4 */ float funused2; /* 80 + 4 */ float cal_max, cal_min; /* 84 + 8 - calibrated max and min: */ /* www.mailbase.ac.uk/lists/spm/2000-09/0099.html */ float compressed; /* 92 + 4 */ float verified; /* 96 + 4 */ int glmax, glmin; /* 100 + 8 - global max and min pixel values (entire database) */ }; /* total=108 bytes */ struct data_history{ /* off + size */ char descrip[80]; /* 0 + 80 */ char aux_file[24]; /* 80 + 24 */ char orient; /* 104 + 1 - slice orientation for this database | */ /* 0 transverse unflipped | */ /* 1 coronal unflipped | disregarded */ /* 2 sagittal unflipped | by SPM */ /* 3 transverse flipped | */ /* 4 coronal flipped | */ /* 5 sagittal flipped | */ short int originator[5]; /* 105 + 10 - origin | */ /* originator[0] x-origin | non standard */ /* originator[1] y-origin | SPM use only */ /* originator[2] z-origin | */ char generated[10]; /* 115 + 10 */ char scannum[10]; /* 125 + 10 */ char patient_id[10]; /* 135 + 10 */ char exp_date[10]; /* 145 + 10 */ char exp_time[10]; /* 155 + 10 */ char hist_un0[3]; /* 165 + 3 */ int views; /* 168 + 4 */ int vols_added; /* 172 + 4 */ int start_field; /* 176 + 4 */ int field_skip; /* 180 + 4 */ int omax, omin; /* 184 + 8 */ int smax, smin; /* 192 + 8 */ }; /* total=200 bytes */ struct analyze75_hdr { struct header_key hk; /* 0 + 40 */ struct image_dimension dime; /* 40 + 108 */ struct data_history hist; /* 148 + 200 */ }; /* total= 348 bytes */ typedef struct{ float real; float imag; } COMPLEX; minc-2.2.00/conversion/nifti1/nii2mnc.man10000644000265600003100000000535212027132661015140 00000000000000.TH nii2mnc 1 "Apr 22 2005" "$Revision: 1.4 $" "" .SH NAME .B nii2mnc - convert a NIfTI-1 or Analyze 7.5 format file to a MINC format file. .SH SYNOPSIS .B nii2mnc .I [] .B nii2mnc .I -help .SH DESCRIPTION The .B nii2mnc command is used to convert "NIfTI-1" format files to MINC format. The NIfTI-1 format was developed by the members of the Neuroinformatics Technology Initiative's Data Format Working Group (DFWG). The NIfTI-1 format is based upon the Mayo Clinic's Analyze 7.5 format. The name of the program is derived from the common filename suffixes used for NIfTI-1 and MINC files. NIfTI-1 defines two possible formats, a "header plus raw image" 2-file format, and a single-file format that includes both header information and the image data. As with Analyze 7.5, the 2-file format consists of one file with the suffix ".hdr" and another file with the extension ".img". In NIfTI-1 single-file format, the two files may be combined into a single file with a ".nii" filename suffix. .SH "OPTIONS" Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH "Output voxel format" .TP .BI -float Save voxels in 32-bit floating point format .TP .BI -double Save voxels in 64-bit floating point format .TP .BI -byte Save voxels in 8-bit integer format .TP .BI -short Save voxels in 16-bit integer format .TP .BI -int Save voxels in 32-bit integer format .TP .BI -signed Save voxels in signed (2's complement) integer format .TP .BI -unsigned Save voxels in unsigned integer format .SH Analyze 7.5 specific options .TP .B -transverse Assume data is in ZYX dimension order. .TP .B -sagittal Assume data is in XZY dimension order. .TP .B -coronal Assume data is in YZX dimension order. .TP .B -xyz Assume data is in XYZ dimension order. .TP .B -zxy Assume data is in ZXY dimension order. .TP .B -yxz Assume data is in YXZ dimension order. .TP .B -flipx, -flipy, -flipz Invert the samples along the given axis. .SH "Other options" .TP .BI -noscanrange Don't scan data to determine valid range. .TP .BI -quiet Quiet operation - do not print progress or debugging information. .SH "Generic options for all commands" .TP .BI -help Print summary of command\-line options and abort .TP .BI -version Print the program and library versions and abort .SH "KNOWN BUGS" Current handling of NIfTI-1 qform and sform coordinate transforms should probably be revised as the NIfTI group clarifies the correct usage of these fields. .SH "SEE ALSO" .IR mnc2nii .SH AUTHOR Robert Vincent (bert@bic.mni.mcgill.ca) with assistance from the NIfTI-1 library authored by Robert Cox et al. .SH "COPYRIGHTS" Copyrights 2005 by Robert Vincent for the Montreal Neurological Institute. minc-2.2.00/conversion/nifti1/mnc2nii.man10000644000265600003100000000531012027132661015132 00000000000000.TH mnc2mnc 1 "Apr 22 2005" "$Revision: 1.3 $" "" .SH NAME .B mnc2nii - convert a MINC format file to a NIfTI-1 or Analyze format file. .SH SYNOPSIS .B mnc2nii .I [] .B mnc2nii .I -help .SH DESCRIPTION The .B mnc2nii command is used to convert MINC format files to either NIfTI-1 or Analyze format. The NIfTI-1 format was developed by the members of the Neuroinformatics Technology Initiative's Data Format Working Group (DFWG). The NIfTI-1 format is based upon the Mayo Clinic's Analyze 7.5 format. The name of the program is derived from the common filename suffixes used for NIfTI-1 and MINC files. NIfTI-1 defines two possible formats, a "header plus raw image" 2-file format, and a single-file format that includes both header information and the image data. As with Analyze 7.5, the 2-file format consists of one file with the suffix ".hdr" and another file with the extension ".img". In NIfTI-1 single-file format, the two files may be combined into a single file with a ".nii" filename suffix. In addition to the NIfTI-1 formats, .B mnc2nii can convert MINC files to the Analyze 7.5 format. .SH "OPTIONS" Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH "Output file format" .TP .BI -dual Save file in NIfTI-1 two-file format (.hdr and .img) .TP .BI -ASCII Save file in non-standard NIfTI-1 ASCII file format .TP .BI -nii Save file in NIfTI-1 single-file format (.nii) .TP .BI -analyze Save file in Analyze 7.5 compatible format .SH "Output voxel format" .TP .BI -float Save voxels in 32-bit floating point format .TP .BI -double Save voxels in 64-bit floating point format .TP .BI -byte Save voxels in 8-bit integer format .TP .BI -short Save voxels in 16-bit integer format .TP .BI -int Save voxels in 32-bit integer format .TP .BI -signed Save voxels in signed (2's complement) integer format .TP .BI -unsigned Save voxels in unsigned integer format .SH "Other options" .TP .BI -noscanrange Don't scan data to determine valid range. .TP .BI -quiet Quiet operation - do not print progress or debugging information. .SH "Generic options for all commands" .TP .BI -help Print summary of command\-line options and abort .TP .BI -version Print the program and library versions and abort .SH "KNOWN BUGS" Current handling of NIfTI-1 qform and sform coordinate transforms should probably be revised as the NIfTI group clarifies the correct usage of these fields. .SH "SEE ALSO" .IR nii2mnc .SH AUTHOR Robert Vincent (bert@bic.mni.mcgill.ca) with assistance from the NIfTI-1 library authored by Robert Cox et al. .SH "COPYRIGHTS" Copyrights 2005 by Robert Vincent for the Montreal Neurological Institute. minc-2.2.00/conversion/nifti1/mnc2nii.c0000644000265600003100000005072512027132661014532 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #include #include "nifti1_io.h" #include "nifti1_local.h" /* Our local definitions */ /* This list is in the order in which dimension lengths and sample * widths are stored in the NIfTI-1 structure. */ static const char *dimnames[MAX_NII_DIMS] = { MIvector_dimension, MItime, MIzspace, MIyspace, MIxspace, NULL, NULL, NULL }; void test_xform(mat44 m, int i, int j, int k) { double x, y, z; x = m.m[DIM_X][DIM_I] * i + m.m[DIM_X][DIM_J] * j + m.m[DIM_X][DIM_K] * k + m.m[DIM_X][3]; y = m.m[DIM_Y][DIM_I] * i + m.m[DIM_Y][DIM_J] * j + m.m[DIM_Y][DIM_K] * k + m.m[DIM_Y][3]; z = m.m[DIM_Z][DIM_I] * i + m.m[DIM_Z][DIM_J] * j + m.m[DIM_Z][DIM_K] * k + m.m[DIM_Z][3]; printf("%d %d %d => ", i, j, k); printf("%f %f %f\n", x, y, z); } static int usage(void) { static const char msg[] = { "mnc2nii: Convert MINC files to NIfTI-1 format\n" "usage: mnc2nii [-q] [filetype] [datatype] filename.mnc [filename.nii]\n" }; fprintf(stderr, "%s", msg); return (-1); } /* Explicitly set all of the fields of the NIfTI I/O header structure to * something reasonable. Right now this is overkill since a simple memset() * would do the same job, but I want this function to help me keep track * of all of the header fields and to allow me to easily override a default * if it becomes useful. */ void init_nifti_header(nifti_image *nii_ptr) { int i, j; nii_ptr->ndim = 0; nii_ptr->nx = nii_ptr->ny = nii_ptr->nz = nii_ptr->nt = nii_ptr->nu = nii_ptr->nv = nii_ptr->nw = 0; for (i = 0; i < MAX_NII_DIMS; i++) { /* Fix suggested by Hyun-Pil Kim (hpkim@ihanyang.ac.kr): Use 1 as the default, not zero */ nii_ptr->dim[i] = 1; } nii_ptr->nvox = 0; nii_ptr->nbyper = 0; nii_ptr->datatype = DT_UNKNOWN; nii_ptr->dx = nii_ptr->dy = nii_ptr->dz = nii_ptr->dt = nii_ptr->du = nii_ptr->dv = nii_ptr->dw = 0.0; for (i = 0; i < MAX_NII_DIMS; i++) { nii_ptr->pixdim[i] = 0.0; } nii_ptr->scl_slope = 0.0; nii_ptr->scl_inter = 0.0; nii_ptr->cal_min = 0.0; nii_ptr->cal_max = 0.0; nii_ptr->qform_code = NIFTI_XFORM_UNKNOWN; nii_ptr->sform_code = NIFTI_XFORM_UNKNOWN; nii_ptr->freq_dim = 0; nii_ptr->phase_dim = 0; nii_ptr->slice_dim = 0; nii_ptr->slice_code = 0; nii_ptr->slice_start = 0; nii_ptr->slice_end = 0; nii_ptr->slice_duration = 0.0; nii_ptr->quatern_b = 0.0; nii_ptr->quatern_c = 0.0; nii_ptr->quatern_d = 0.0; nii_ptr->qoffset_x = 0.0; nii_ptr->qoffset_y = 0.0; nii_ptr->qoffset_z = 0.0; nii_ptr->qfac = 0.0; nii_ptr->toffset = 0.0; nii_ptr->xyz_units = NIFTI_UNITS_MM; /* Default spatial units */ nii_ptr->time_units = NIFTI_UNITS_SEC; /* Default time units */ nii_ptr->nifti_type = FT_ANALYZE; nii_ptr->intent_code = 0; nii_ptr->intent_p1 = 0.0; nii_ptr->intent_p2 = 0.0; nii_ptr->intent_p3 = 0.0; memset(nii_ptr->intent_name, 0, sizeof (nii_ptr->intent_name)); memset(nii_ptr->descrip, 0, sizeof (nii_ptr->descrip)); memset(nii_ptr->aux_file, 0, sizeof (nii_ptr->aux_file)); nii_ptr->fname = NULL; nii_ptr->iname = NULL; nii_ptr->iname_offset = 0; nii_ptr->swapsize = 0; nii_ptr->byteorder = 1; /* default order (LSB) */ nii_ptr->data = NULL; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { nii_ptr->qto_xyz.m[i][j] = 0.0; nii_ptr->qto_ijk.m[i][j] = 0.0; nii_ptr->sto_xyz.m[i][j] = 0.0; nii_ptr->sto_ijk.m[i][j] = 0.0; } } nii_ptr->num_ext = 0; } /* private function from from libminc2. This function is private partially because it's parameters are somewhat bizarre. It would be a good idea to rework them into a more rational and easily described form. */ extern void restructure_array(int ndims, unsigned char *array, const unsigned long *lengths_perm, int el_size, const int *map, const int *dir); int main(int argc, char **argv) { /* NIFTI stuff */ nifti_image *nii_ptr; nifti_image nii_rec; int nii_dimids[MAX_NII_DIMS]; int nii_dir[MAX_NII_DIMS]; int nii_map[MAX_NII_DIMS]; unsigned long nii_lens[MAX_NII_DIMS]; int nii_ndims; static int nifti_filetype; static int nifti_datatype; static int nifti_signed = 1; /* MINC stuff */ int mnc_fd; /* MINC file descriptor */ nc_type mnc_type; /* MINC data type as read */ int mnc_ndims; /* MINC image dimension count */ int mnc_dimids[MAX_VAR_DIMS]; /* MINC image dimension identifiers */ long mnc_dlen; /* MINC dimension length value */ double mnc_dstep; /* MINC dimension step value */ int mnc_icv; /* MINC image conversion variable */ int mnc_vid; /* MINC Image variable ID */ long mnc_start[MAX_VAR_DIMS]; /* MINC data starts */ long mnc_count[MAX_VAR_DIMS]; /* MINC data counts */ int mnc_signed; /* MINC if output voxels are signed */ double mnc_rrange[2]; /* MINC real range (min, max) */ double mnc_vrange[2]; /* MINC valid range (min, max) */ /* Other stuff */ char out_str[1024]; /* Big string for filename */ char att_str[1024]; /* Big string for attribute values */ int i; /* Generic loop counter the first */ int j; /* Generic loop counter the second */ char *str_ptr; /* Generic ASCIZ string pointer */ int r; /* Result code. */ static int qflag = 0; /* Quiet flag (default is non-quiet) */ static ArgvInfo argTable[] = { {NULL, ARGV_HELP, NULL, NULL, "Output voxel data type specification"}, {"-byte", ARGV_CONSTANT, (char *)DT_INT8, (char *)&nifti_datatype, "Write voxel data in 8-bit signed integer format."}, {"-short", ARGV_CONSTANT, (char *)DT_INT16, (char *)&nifti_datatype, "Write voxel data in 16-bit signed integer format."}, {"-int", ARGV_CONSTANT, (char *)DT_INT32, (char *)&nifti_datatype, "Write voxel data in 32-bit signed integer format."}, {"-float", ARGV_CONSTANT, (char *)DT_FLOAT32, (char *)&nifti_datatype, "Write voxel data in 32-bit floating point format."}, {"-double", ARGV_CONSTANT, (char *)DT_FLOAT64, (char *)&nifti_datatype, "Write voxel data in 64-bit floating point format."}, {"-signed", ARGV_CONSTANT, (char *)1, (char *)&nifti_signed, "Write integer voxel data in signed format."}, {"-unsigned", ARGV_CONSTANT, (char *)0, (char *)&nifti_signed, "Write integer voxel data in unsigned format."}, {NULL, ARGV_HELP, NULL, NULL, "Output file format specification"}, {"-dual", ARGV_CONSTANT, (char *)FT_NIFTI_DUAL, (char *)&nifti_filetype, "Write NIfTI-1 two-file format (.img and .hdr)"}, {"-ASCII", ARGV_CONSTANT, (char *)FT_NIFTI_ASCII, (char *)&nifti_filetype, "Write NIfTI-1 ASCII header format (.nia)"}, {"-nii", ARGV_CONSTANT, (char *)FT_NIFTI_SINGLE, (char *)&nifti_filetype, "Write NIfTI-1 one-file format (.nii)"}, {"-analyze", ARGV_CONSTANT, (char *)FT_ANALYZE, (char *)&nifti_filetype, "Write an Analyze two-file format file (.img and .hdr)"}, {NULL, ARGV_HELP, NULL, NULL, "Other options"}, {"-quiet", ARGV_CONSTANT, (char *)0, (char *)&qflag, "Quiet operation"}, {NULL, ARGV_END, NULL, NULL, NULL} }; ncopts = 0; /* Clear global netCDF error reporting flag */ /* Default NIfTI file type is "NII", single binary file */ nifti_filetype = FT_UNSPECIFIED; nifti_datatype = DT_UNKNOWN; if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) { fprintf(stderr, "Too few arguments\n"); return usage(); } if (!nifti_signed) { switch (nifti_datatype) { case DT_INT8: nifti_datatype = DT_UINT8; break; case DT_INT16: nifti_datatype = DT_UINT16; break; case DT_INT32: nifti_datatype = DT_UINT32; break; } } switch (nifti_datatype){ case DT_INT8: case DT_UINT8: mnc_type = NC_BYTE; break; case DT_INT16: case DT_UINT16: mnc_type = NC_SHORT; break; case DT_INT32: case DT_UINT32: mnc_type = NC_INT; break; case DT_FLOAT32: mnc_type = NC_FLOAT; break; case DT_FLOAT64: mnc_type = NC_DOUBLE; break; } if (argc == 2) { strcpy(out_str, argv[1]); str_ptr = strrchr(out_str, '.'); if (str_ptr != NULL && !strcmp(str_ptr, ".mnc")) { *str_ptr = '\0'; } } else if (argc == 3) { strcpy(out_str, argv[2]); str_ptr = strrchr(out_str, '.'); if (str_ptr != NULL) { /* See if a recognized file extension was specified. If so, * we trim it off and set the output file type if none was * specified. If the extension is not recognized, assume * that we will form the filename by just adding the right * extension for the selected output format. */ if (!strcmp(str_ptr, ".nii")) { if (nifti_filetype == FT_UNSPECIFIED) { nifti_filetype = FT_NIFTI_SINGLE; } *str_ptr = '\0'; } else if (!strcmp(str_ptr, ".img") || !strcmp(str_ptr, ".hdr")) { if (nifti_filetype == FT_UNSPECIFIED) { nifti_filetype = FT_NIFTI_DUAL; } *str_ptr = '\0'; } else if (!strcmp(str_ptr, ".nia")) { if (nifti_filetype == FT_UNSPECIFIED) { nifti_filetype = FT_NIFTI_ASCII; } *str_ptr = '\0'; } } } else { fprintf(stderr, "Filename argument required\n"); return usage(); } /* Open the MINC file. It needs to exist. */ mnc_fd = miopen(argv[1], NC_NOWRITE); if (mnc_fd < 0) { fprintf(stderr, "Can't find input file '%s'\n", argv[1]); return (-1); } /* Find the MINC image variable. If we can't find it, there is no * further processing possible... */ mnc_vid = ncvarid(mnc_fd, MIimage); if (mnc_vid < 0) { fprintf(stderr, "Can't locate the image variable (mnc_vid=%d)\n", mnc_vid); return (-1); } /* Find out about the MINC image variable - specifically, how many * dimensions, and which dimensions. */ r = ncvarinq(mnc_fd, mnc_vid, NULL, NULL, &mnc_ndims, mnc_dimids, NULL); if (r < 0) { fprintf(stderr, "Can't read information from image variable\n"); return (-1); } if (mnc_ndims > MAX_NII_DIMS) { fprintf(stderr, "NIfTI-1 files may contain at most %d dimensions\n", MAX_NII_DIMS); return (-1); } /* Initialize the NIfTI structure */ nii_ptr = &nii_rec; init_nifti_header(nii_ptr); /* For now we just use the mnc2nii command line as the description * field. Probably we should use something better, perhaps a * combination of some other standard MINC fields that might * provide more information. */ str_ptr = nii_ptr->descrip; for (i = 0; i < argc; i++) { char *arg_ptr = argv[i]; if ((str_ptr - nii_ptr->descrip) >= MAX_NII_DESCRIP) { break; } if (i != 0) { *str_ptr++ = ' '; } while (*arg_ptr != '\0' && (str_ptr - nii_ptr->descrip) < MAX_NII_DESCRIP) { *str_ptr++ = *arg_ptr++; } *str_ptr = '\0'; } nii_ptr->fname = malloc(strlen(out_str) + 4 + 1); nii_ptr->iname = malloc(strlen(out_str) + 4 + 1); strcpy(nii_ptr->fname, out_str); strcpy(nii_ptr->iname, out_str); switch (nifti_filetype) { case FT_ANALYZE: strcat(nii_ptr->fname, ".hdr"); strcat(nii_ptr->iname, ".img"); break; case FT_NIFTI_SINGLE: strcat(nii_ptr->fname, ".nii"); strcat(nii_ptr->iname, ".nii"); break; case FT_NIFTI_DUAL: strcat(nii_ptr->fname, ".hdr"); strcat(nii_ptr->iname, ".img"); break; case FT_NIFTI_ASCII: strcat(nii_ptr->fname, ".nia"); strcat(nii_ptr->iname, ".nia"); break; default: fprintf(stderr, "Unknown output file type %d\n", nifti_filetype); return (-1); } miget_image_range(mnc_fd, mnc_rrange); /* Get real range */ miget_valid_range(mnc_fd, mnc_vid, mnc_vrange); /* Get voxel range */ if (mnc_vrange[1] != mnc_vrange[0] && mnc_rrange[1] != mnc_rrange[0]) { nii_ptr->scl_slope = ((mnc_rrange[1] - mnc_rrange[0]) / (mnc_vrange[1] - mnc_vrange[0])); nii_ptr->scl_inter = mnc_rrange[0] - (mnc_vrange[0] * nii_ptr->scl_slope); } else { nii_ptr->scl_slope = 0.0; } nii_ptr->nvox = 1; /* Initial value for voxel count */ /* Find all of the dimensions of the MINC file, in the order they * will be listed in the NIfTI-1/Analyze file. We use this to build * a map for restructuring the data according to the normal rules * of NIfTI-1. */ nii_ndims = 0; for (i = 0; i < MAX_NII_DIMS; i++) { if (dimnames[i] == NULL) { nii_dimids[nii_ndims] = -1; continue; } nii_dimids[nii_ndims] = ncdimid(mnc_fd, dimnames[i]); if (nii_dimids[nii_ndims] == -1) { continue; } /* Make sure the dimension is actually used to define the image. */ for (j = 0; j < mnc_ndims; j++) { if (nii_dimids[nii_ndims] == mnc_dimids[j]) { nii_map[nii_ndims] = j; break; } } if (j < mnc_ndims) { mnc_dlen = 1; mnc_dstep = 0; ncdiminq(mnc_fd, nii_dimids[nii_ndims], NULL, &mnc_dlen); ncattget(mnc_fd, ncvarid(mnc_fd, dimnames[i]), MIstep, &mnc_dstep); if (mnc_dstep < 0) { nii_dir[nii_ndims] = -1; mnc_dstep = -mnc_dstep; } else { nii_dir[nii_ndims] = 1; } nii_lens[nii_ndims] = mnc_dlen; nii_ndims++; } nii_ptr->dim[dimmap[i]] = (int) mnc_dlen; nii_ptr->nvox *= mnc_dlen; nii_ptr->pixdim[dimmap[i]] = (float) mnc_dstep; } /* Here we do some "post-processing" of the results. Make certain that * the nt value is never zero, and make certain that ndim is set to * 4 if there is a time dimension and 5 if there is a vector dimension */ if (nii_ptr->dim[3] > 1 && nii_ndims < 4) { nii_ndims = 4; } if (nii_ptr->dim[4] > 1) { nii_ptr->intent_code = NIFTI_INTENT_VECTOR; nii_ndims = 5; } nii_ptr->ndim = nii_ndims; /* Total number of dimensions in file */ nii_ptr->nx = nii_ptr->dim[0]; nii_ptr->ny = nii_ptr->dim[1]; nii_ptr->nz = nii_ptr->dim[2]; nii_ptr->nt = nii_ptr->dim[3]; nii_ptr->nu = nii_ptr->dim[4]; nii_ptr->dx = nii_ptr->pixdim[0]; nii_ptr->dy = nii_ptr->pixdim[1]; nii_ptr->dz = nii_ptr->pixdim[2]; nii_ptr->dt = nii_ptr->pixdim[3]; nii_ptr->du = 1; /* MINC files don't define a sample size for a vector_dimension */ nii_ptr->nifti_type = nifti_filetype; if (nifti_datatype == DT_UNKNOWN) { nii_ptr->datatype = DT_FLOAT32; /* Default */ mnc_type = NC_FLOAT; mnc_signed = 1; } else { nii_ptr->datatype = nifti_datatype; } /* Load the direction_cosines and start values into the NIfTI-1 * sform structure. * */ for (i = 0; i < MAX_SPACE_DIMS; i++) { int id = ncvarid(mnc_fd, mnc_spatial_names[i]); double start; double step; double dircos[MAX_SPACE_DIMS]; int tmp; if (id < 0) { continue; } /* Set default values */ start = 0.0; step = 1.0; dircos[DIM_X] = dircos[DIM_Y] = dircos[DIM_Z] = 0.0; dircos[i] = 1.0; miattget(mnc_fd, id, MIstart, NC_DOUBLE, 1, &start, &tmp); miattget(mnc_fd, id, MIstep, NC_DOUBLE, 1, &step, &tmp); miattget(mnc_fd, id, MIdirection_cosines, NC_DOUBLE, MAX_SPACE_DIMS, dircos, &tmp); ncdiminq(mnc_fd, ncdimid(mnc_fd, mnc_spatial_names[i]), NULL, &mnc_dlen); if (step < 0) { step = -step; start = start - step * (mnc_dlen - 1); } nii_ptr->sto_xyz.m[0][i] = step * dircos[0]; nii_ptr->sto_xyz.m[1][i] = step * dircos[1]; nii_ptr->sto_xyz.m[2][i] = step * dircos[2]; nii_ptr->sto_xyz.m[0][3] += start * dircos[0]; nii_ptr->sto_xyz.m[1][3] += start * dircos[1]; nii_ptr->sto_xyz.m[2][3] += start * dircos[2]; miattgetstr(mnc_fd, id, MIspacetype, sizeof(att_str), att_str); /* Try to set the S-transform code correctly. */ if (!strcmp(att_str, MI_TALAIRACH)) { nii_ptr->sform_code = NIFTI_XFORM_TALAIRACH; } else if (!strcmp(att_str, MI_CALLOSAL)) { /* TODO: Not clear what do do here... */ nii_ptr->sform_code = NIFTI_XFORM_SCANNER_ANAT; } else { /* MI_NATIVE or unknown */ nii_ptr->sform_code = NIFTI_XFORM_SCANNER_ANAT; } } /* So the last row is right... */ nii_ptr->sto_xyz.m[3][0] = 0.0; nii_ptr->sto_xyz.m[3][1] = 0.0; nii_ptr->sto_xyz.m[3][2] = 0.0; nii_ptr->sto_xyz.m[3][3] = 1.0; nii_ptr->sto_ijk = nifti_mat44_inverse(nii_ptr->sto_xyz); nifti_datatype_sizes(nii_ptr->datatype, &nii_ptr->nbyper, &nii_ptr->swapsize); if (!qflag) { nifti_image_infodump(nii_ptr); } /* Now load the actual MINC data. */ nii_ptr->data = malloc(nii_ptr->nbyper * nii_ptr->nvox); if (nii_ptr->data == NULL) { fprintf(stderr, "Out of memory.\n"); return (-1); } if (!qflag) { fprintf(stderr, "MINC type %d signed %d\n", mnc_type, mnc_signed); } mnc_icv = miicv_create(); miicv_setint(mnc_icv, MI_ICV_TYPE, mnc_type); miicv_setstr(mnc_icv, MI_ICV_SIGN, (mnc_signed) ? MI_SIGNED : MI_UNSIGNED); miicv_setdbl(mnc_icv, MI_ICV_VALID_MAX, mnc_vrange[1]); miicv_setdbl(mnc_icv, MI_ICV_VALID_MIN, mnc_vrange[0]); miicv_setint(mnc_icv, MI_ICV_DO_NORM, 1); miicv_attach(mnc_icv, mnc_fd, mnc_vid); /* Read in the entire hyperslab from the file. */ for (i = 0; i < mnc_ndims; i++) { ncdiminq(mnc_fd, mnc_dimids[i], NULL, &mnc_count[i]); mnc_start[i] = 0; } r = miicv_get(mnc_icv, mnc_start, mnc_count, nii_ptr->data); if (r < 0) { fprintf(stderr, "Read error\n"); return (-1); } /* Shut down the MINC stuff now that it has done its work. */ miicv_detach(mnc_icv); miicv_free(mnc_icv); miclose(mnc_fd); if (!qflag) { /* Debugging stuff - just to check the contents of these arrays. */ for (i = 0; i < nii_ndims; i++) { printf("%d: %ld %d %d\n", i, nii_lens[i], nii_map[i], nii_dir[i]); } printf("bytes per voxel %d\n", nii_ptr->nbyper); printf("# of voxels %d\n", nii_ptr->nvox); } /* Rearrange the data to correspond to the NIfTI dimension ordering. */ restructure_array(nii_ndims, nii_ptr->data, nii_lens, nii_ptr->nbyper, nii_map, nii_dir); if (!qflag) { /* More debugging stuff - check coordinate transform. */ test_xform(nii_ptr->sto_xyz, 0, 0, 0); test_xform(nii_ptr->sto_xyz, 10, 0, 0); test_xform(nii_ptr->sto_xyz, 0, 10, 0); test_xform(nii_ptr->sto_xyz, 0, 0, 10); test_xform(nii_ptr->sto_xyz, 10, 10, 10); } fprintf(stdout, "Calling NIFTI-1 Write routine\n"); nifti_image_write(nii_ptr); return (0); } minc-2.2.00/conversion/nifti1/nifti1_io.c0000644000265600003100000070477212027132661015064 00000000000000#define _NIFTI1_IO_C_ #include "nifti1_io.h" /* typedefs, prototypes, macros, etc. */ /*****===================================================================*****/ /***** Sample functions to deal with NIFTI-1 and ANALYZE files *****/ /*****...................................................................*****/ /***** This code is released to the public domain. *****/ /*****...................................................................*****/ /***** Author: Robert W Cox, SSCC/DIRP/NIMH/NIH/DHHS/USA/EARTH *****/ /***** Date: August 2003 *****/ /*****...................................................................*****/ /***** Neither the National Institutes of Health (NIH), nor any of its *****/ /***** employees imply any warranty of usefulness of this software for *****/ /***** any purpose, and do not assume any liability for damages, *****/ /***** incidental or otherwise, caused by any use of this document. *****/ /*****===================================================================*****/ /** \file nifti1_io.c \brief main collection of nifti1 i/o routines - written by Bob Cox, SSCC NIMH - revised by Mark Jenkinson, FMRIB - revised by Rick Reynolds, SSCC, NIMH - revised by Kate Fissell, University of Pittsburgh The library history can be viewed via "nifti_tool -nifti_hist".
The library version can be viewed via "nifti_tool -nifti_ver". */ /*! global history and version strings, for printing */ static char * gni_history[] = { "----------------------------------------------------------------------\n" "history (of nifti library changes):\n" "\n", "0.0 August, 2003 [rwcox]\n" " (Robert W Cox of the National Institutes of Health, SSCC/DIRP/NIMH)\n" " - initial version\n" "\n", "0.1 July/August, 2004 [Mark Jenkinson]\n" " (FMRIB Centre, University of Oxford, UK)\n" " - Mainly adding low-level IO and changing things to allow gzipped\n" " files to be read and written\n" " - Full backwards compatability should have been maintained\n" "\n", "0.2 16 Nov 2004 [rickr]\n" " (Rick Reynolds of the National Institutes of Health, SSCC/DIRP/NIMH)\n" " - included Mark's changes in the AFNI distribution (including znzlib/)\n" " (HAVE_ZLIB is commented out for the standard distribution)\n" " - modified nifti_validfilename() and nifti_makebasename()\n" " - added nifti_find_file_extension()\n" "\n", "0.3 3 Dec 2004 [rickr]\n" " - note: header extensions are not yet checked for\n" " - added formatted history as global string, for printing\n" " - added nifti_disp_lib_hist(), to display the nifti library history\n" " - added nifti_disp_lib_version(), to display the nifti library history\n", " - re-wrote nifti_findhdrname()\n" " o used nifti_find_file_extension()\n" " o changed order of file tests (default is .nii, depends on input)\n" " o free hdrname on failure\n" " - made similar changes to nifti_findimgname()\n" " - check for NULL return from nifti_findhdrname() calls\n", " - removed most of ERREX() macros\n" " - modified nifti_image_read()\n" " o added debug info and error checking (on gni_debug > 0, only)\n" " o fail if workingname is NULL\n" " o check for failure to open header file\n" " o free workingname on failure\n" " o check for failure of nifti_image_load()\n" " o check for failure of nifti_convert_nhdr2nim()\n", " - changed nifti_image_load() to int, and check nifti_read_buffer return\n" " - changed nifti_read_buffer() to fail on short read, and to count float\n" " fixes (to print on debug)\n" " - changed nifti_image_infodump to print to stderr\n" " - updated function header comments, or moved comments above header\n" " - removed const keyword\n" " - added LNI_FERR() macro for error reporting on input files\n" "\n", "0.4 10 Dec 2004 [rickr] - added header extensions\n" " - in nifti1_io.h:\n" " o added num_ext and ext_list to the definition of nifti_image\n" " o made many functions static (more to follow)\n" " o added LNI_MAX_NIA_EXT_LEN, for max nifti_type 3 extension length\n", " - added __DATE__ to version output in nifti_disp_lib_version()\n" " - added nifti_disp_matrix_orient() to print orientation information\n" " - added '.nia' as a valid file extension in nifti_find_file_extension()\n" " - added much more debug output\n" " - in nifti_image_read(), in the case of an ASCII header, check for\n" " extensions after the end of the header\n", " - added nifti_read_extensions() function\n" " - added nifti_read_next_extension() function\n" " - added nifti_add_exten_to_list() function\n" " - added nifti_check_extension() function\n" " - added nifti_write_extensions() function\n" " - added nifti_extension_size() function\n" " - in nifti_set_iname_offest():\n" " o adjust offset by the extension size and the extender size\n", " o fixed the 'ceiling modulo 16' computation\n" " - in nifti_image_write_hdr_img2(): \n" " o added extension writing\n" " o check for NULL return from nifti_findimgname()\n" " - include number of extensions in nifti_image_to_ascii() output\n" " - in nifti_image_from_ascii():\n" " o return bytes_read as a parameter, computed from the final spos\n" " o extract num_ext from ASCII header\n" "\n", "0.5 14 Dec 2004 [rickr] - added sub-brick reading functions\n" " - added nifti_brick_list type to nifti1_io.h, along with new prototypes\n" " - added main nifti_image_read_bricks() function, with description\n" " - added nifti_image_load_bricks() - library function (requires nim)\n" " - added valid_nifti_brick_list() - library function\n" " - added free_NBL() - library function\n", " - added update_nifti_image_for_brick_list() for dimension update\n" " - added nifti_load_NBL_bricks(), nifti_alloc_NBL_mem(),\n" " nifti_copynsort() and force_positive() (static functions)\n" " - in nifti_image_read(), check for failed load only if read_data is set\n" " - broke most of nifti_image_load() into nifti_image_load_prep()\n" "\n", "0.6 15 Dec 2004 [rickr] - added sub-brick writing functionality\n" " - in nifti1_io.h, removed znzlib directory from include - all nifti\n" " library files are now under the nifti directory\n" " - nifti_read_extensions(): print no offset warning for nifti_type 3\n" " - nifti_write_all_data():\n" " o pass nifti_brick_list * NBL, for optional writing\n" " o if NBL, write each sub-brick, sequentially\n", " - nifti_set_iname_offset(): case 1 must have sizeof() cast to int\n" " - pass NBL to nifti_image_write_hdr_img2(), and allow NBL or data\n" " - added nifti_image_write_bricks() wrapper for ...write_hdr_img2()\n" " - included compression abilities\n" "\n", "0.7 16 Dec 2004 [rickr] - minor changes to extension reading\n" "\n", "0.8 21 Dec 2004 [rickr] - restrict extension reading, and minor changes\n" " - in nifti_image_read(), compute bytes for extensions (see remaining)\n" " - in nifti_read_extensions(), pass 'remain' as space for extensions,\n" " pass it to nifti_read_next_ext(), and update for each one read \n" " - in nifti_check_extension(), require (size <= remain)\n", " - in update_nifti_image_brick_list(), update nvox\n" " - in nifti_image_load_bricks(), make explicit check for nbricks <= 0\n" " - in int_force_positive(), check for (!list)\n" " - in swap_nifti_header(), swap sizeof_hdr, and reorder to struct order\n" " - change get_filesize functions to signed ( < 0 is no file or error )\n", " - in nifti_validfilename(), lose redundant (len < 0) check\n" " - make print_hex_vals() static\n" " - in disp_nifti_1_header, restrict string field widths\n" "\n", "0.9 23 Dec 2004 [rickr] - minor changes\n" " - broke ASCII header reading out of nifti_image_read(), into new\n" " functions has_ascii_header() and read_ascii_image()\n", " - check image_read failure and znzseek failure\n" " - altered some debug output\n" " - nifti_write_all_data() now returns an int\n" "\n", "0.10 29 Dec 2004 [rickr]\n" " - renamed nifti_valid_extension() to nifti_check_extension()\n" " - added functions nifti_makehdrname() and nifti_makeimgname()\n" " - added function valid_nifti_extensions()\n" " - in nifti_write_extensions(), check for validity before writing\n", " - rewrote nifti_image_write_hdr_img2():\n" " o set write_data and leave_open flags from write_opts\n" " o add debug print statements\n" " o use nifti_write_ascii_image() for the ascii case\n" " o rewrote the logic of all cases to be easier to follow\n", " - broke out code as nifti_write_ascii_image() function\n" " - added debug to top-level write functions, and free the znzFile\n" " - removed unused internal function nifti_image_open()\n" "\n", "0.11 30 Dec 2004 [rickr] - small mods\n" " - moved static function prototypes from header to C file\n" " - free extensions in nifti_image_free()\n" "\n", "1.0 07 Jan 2005 [rickr] - INITIAL RELEASE VERSION\n" " - added function nifti_set_filenames()\n" " - added function nifti_read_header()\n" " - added static function nhdr_looks_good()\n" " - added static function need_nhdr_swap()\n" " - exported nifti_add_exten_to_list symbol\n", " - fixed #bytes written in nifti_write_extensions()\n" " - only modify offset if it is too small (nifti_set_iname_offset)\n" " - added nifti_type 3 to nifti_makehdrname and nifti_makeimgname\n" " - added function nifti_set_filenames()\n" "\n", "1.1 07 Jan 2005 [rickr]\n" " - in nifti_read_header(), swap if needed\n" "\n", "1.2 07 Feb 2005 [kate fissell c/o rickr] \n" " - nifti1.h: added doxygen comments for main struct and #define groups\n" " - nifti1_io.h: added doxygen comments for file and nifti_image struct\n" " - nifti1_io.h: added doxygen comments for file and some functions\n" " - nifti1_io.c: changed nifti_copy_nim_info to use memcpy\n" "\n", "1.3 09 Feb 2005 [rickr]\n" " - nifti1.h: added doxygen comments for extension structs\n" " - nifti1_io.h: put most #defines in #ifdef _NIFTI1_IO_C_ block\n" " - added a doxygen-style description to every exported function\n" " - added doxygen-style comments within some functions\n" " - re-exported many znzFile functions that I had made static\n" " - re-added nifti_image_open (sorry, Mark)\n" " - every exported function now has 'nifti' in the name (19 functions)\n", " - made sure every alloc() has a failure test\n" " - added nifti_copy_extensions function, for use in nifti_copy_nim_info\n" " - nifti_is_gzfile: added initial strlen test\n" " - nifti_set_filenames: added set_byte_order parameter option\n" " (it seems appropriate to set the BO when new files are associated)\n" " - disp_nifti_1_header: prints to stdout (a.o.t. stderr), with fflush\n" "\n", "1.4 23 Feb 2005 [rickr] - sourceforge merge\n" " - merged into the nifti_io CVS directory structure at sourceforge.net\n" " - merged in 4 changes by Mark, and re-added his const keywords\n" " - cast some pointers to (void *) for -pedantic compile option\n" " - added nifti_free_extensions()\n" "\n", "1.5 02 Mar 2005 [rickr] - started nifti global options\n" " - gni_debug is now g_opts.debug\n" " - added validity check parameter to nifti_read_header\n" " - need_nhdr_swap no longer does test swaps on the stack\n" "\n", "1.6 05 April 2005 [rickr] - validation and collapsed_image_read\n" " - added nifti_read_collapsed_image(), an interface for reading partial\n" " datasets, specifying a subset of array indices\n" " - for read_collapsed_image, added static functions: rci_read_data(),\n" " rci_alloc_mem(), and make_pivot_list()\n", " - added nifti_nim_is_valid() to check for consistency (more to do)\n" " - added nifti_nim_has_valid_dims() to do many dimensions tests\n" "\n", "1.7 08 April 2005 [rickr]\n" " - added nifti_update_dims_from_array() - to update dimensions\n" " - modified nifti_makehdrname() and nifti_makeimgname():\n" " if prefix has a valid extension, use it (else make one up)\n" " - added nifti_get_intlist - for making an array of ints\n" " - fixed init of NBL->bsize in nifti_alloc_NBL_mem() {thanks, Bob}\n" "\n", "1.8 14 April 2005 [rickr]\n" " - added nifti_set_type_from_names(), for nifti_set_filenames()\n" " (only updates type if number of files does not match it)\n" " - added is_valid_nifti_type(), just to be sure\n" " - updated description of nifti_read_collapsed_image() for *data change\n" " (if *data is already set, assume memory exists for results)\n" " - modified rci_alloc_mem() to allocate only if *data is NULL\n" "\n", "1.9 19 April 2005 [rickr]\n" " - added extension codes NIFTI_ECODE_COMMENT and NIFTI_ECODE_XCEDE\n" " - added nifti_type codes NIFTI_MAX_ECODE and NIFTI_MAX_FTYPE\n" " - added nifti_add_extension() {exported}\n" " - added nifti_fill_extension() as a static function\n" " - added nifti_is_valid_ecode() {exported}\n", " - nifti_type values are now NIFTI_FTYPE_* file codes\n" " - in nifti_read_extensions(), decrement 'remain' by extender size, 4\n" " - in nifti_set_iname_offset(), case 1, update if offset differs\n" " - only output '-d writing nifti file' if debug > 1\n" "\n", "1.10 10 May 2005 [rickr]\n" " - files are read using ZLIB only if they end in '.gz'\n" "\n", "1.11 12 August 2005 [kate fissell]\n" " - Kate's 0.2 release packaging, for sourceforge\n" "\n", "1.12 17 August 2005 [rickr] - comment (doxygen) updates\n" " - updated comments for most functions (2 updates from Cinly Ooi)\n" " - added nifti_type_and_names_match()\n" "\n", "1.12a 24 August 2005 [rickr] - remove all tabs from Clibs/*/*.[ch]\n", "1.12b 25 August 2005 [rickr] - changes by Hans Johnson\n", "1.13 25 August 2005 [rickr]\n", " - finished changes by Hans for Insight\n" " - added const in all appropraite parameter locations (30-40)\n" " (any pointer referencing data that will not change)\n" " - shortened all string constants below 509 character limit\n" "1.14 28 October 2005 [HJohnson]\n", " - use nifti_set_filenames() in nifti_convert_nhdr2nim()\n" "1.15 02 November 2005 [rickr]\n", " - added skip_blank_ext to nifti_global_options\n" " - added nifti_set_skip_blank_ext(), to set option\n" " - if skip_blank_ext and no extensions, do not read/write extender\n" "1.16 18 November 2005 [rickr]\n", " - removed any test or access of dim[i], i>dim[0]\n" " - do not set pixdim for collapsed dims to 1.0, leave them as they are\n" " - added magic and dim[i] tests in nifti_hdr_looks_good()\n" " - added 2 size_t casts\n" "1.17 22 November 2005 [rickr]\n", " - in hdr->nim, for i > dim[0], pass 0 or 1, else set to 1\n" "1.18 02 March 2006 [rickr]\n", " - in nifti_alloc_NBL_mem(), fixed nt=0 case from 1.17 change\n" "1.19 23 May 2006 [HJohnson,rickr]\n", " - nifti_write_ascii_image(): free(hstr)\n" " - nifti_copy_extensions(): clear num_ext and ext_list\n" "1.20 27 Jun 2006 [rickr]\n", " - nifti_findhdrname(): fixed assign of efirst to match stated logic\n" " (problem found by Atle Bjørnerud)\n" "1.21 5 Sep 2006 [rickr] update for nifticlib-0.4 release\n", " - was reminded to actually add nifti_set_skip_blank_ext()\n" " - init g_opts.skip_blank_ext to 0\n" "----------------------------------------------------------------------\n" }; static char gni_version[] = "nifti library version 1.21 5 Sep, 2006)"; /*! global nifti options structure */ static nifti_global_options g_opts = { 1, 0 }; /*---------------------------------------------------------------------------*/ /* prototypes for internal functions - not part of exported library */ /* extension routines */ static int nifti_read_extensions( nifti_image *nim, znzFile fp, int remain ); static int nifti_read_next_extension( nifti1_extension * nex, nifti_image *nim, int remain, znzFile fp ); static int nifti_check_extension(nifti_image *nim, int size,int code, int rem); static void update_nifti_image_for_brick_list(nifti_image * nim , int nbricks); static int nifti_add_exten_to_list(nifti1_extension * new_ext, nifti1_extension ** list, int new_length); static int nifti_fill_extension(nifti1_extension * ext, const char * data, int len, int ecode); /* NBL routines */ static int nifti_load_NBL_bricks(nifti_image * nim , int * slist, int * sindex, nifti_brick_list * NBL, znzFile fp ); static int nifti_alloc_NBL_mem( nifti_image * nim, int nbricks, nifti_brick_list * nbl); static int nifti_copynsort(int nbricks, const int *blist, int **slist, int **sindex); /* for nifti_read_collapsed_image: */ static int rci_read_data(nifti_image *nim, int *pivots, int *prods, int nprods, const int dims[], char *data, znzFile fp, int base_offset); static int rci_alloc_mem(void ** data, int prods[8], int nprods, int nbyper ); static int make_pivot_list(nifti_image * nim, const int dims[], int pivots[], int prods[], int * nprods ); /* misc */ static int need_nhdr_swap (short dim0, int hdrsize); static int print_hex_vals (const char * data, int nbytes, FILE * fp); static int unescape_string (char *str); /* string utility functions */ static char *escapize_string (const char *str); /* internal I/O routines */ static znzFile nifti_image_load_prep( nifti_image *nim ); static int has_ascii_header(znzFile fp); /*---------------------------------------------------------------------------*/ /* for calling from some main program */ /*----------------------------------------------------------------------*/ /*! display the nifti library module history (via stdout) *//*--------------------------------------------------------------------*/ void nifti_disp_lib_hist( void ) { int c, len = sizeof(gni_history)/sizeof(char *); for( c = 0; c < len; c++ ) fputs(gni_history[c], stdout); } /*----------------------------------------------------------------------*/ /*! display the nifti library version (via stdout) *//*--------------------------------------------------------------------*/ void nifti_disp_lib_version( void ) { printf("%s, compiled %s\n", gni_version, __DATE__); } /*----------------------------------------------------------------------*/ /*! nifti_image_read_bricks - read nifti data as array of bricks * * 13 Dec 2004 [rickr] * * \param hname - filename of dataset to read (must be valid) * \param nbricks - number of sub-bricks to read * (if blist is valid, nbricks must be > 0) * \param blist - list of sub-bricks to read * (can be NULL; if NULL, read complete dataset) * \param NBL - pointer to empty nifti_brick_list struct * (must be a valid pointer) * * \return *
nim - same as nifti_image_read, but nim->data will be NULL *
NBL - filled with data * * By default, this function will read the nifti dataset and break the data * into a list of nt*nu*nv*nw sub-bricks, each having size nx*ny*nz elements. * That is to say, instead of reading the entire dataset as a single array, * break it up into sub-bricks, each of size nx*ny*nz elements. * * If 'blist' is valid, it is taken to be a list of sub-bricks, of length * 'nbricks'. The data will still be separated into sub-bricks of size * nx*ny*nz elements, but now 'nbricks' sub-bricks will be returned, of the * caller's choosing via 'blist'. * * E.g. consider a dataset with 12 sub-bricks (numbered 0..11), and the * following code: * *
 * { nifti_brick_list   NB_orig, NB_select;
 *   nifti_image      * nim_orig, * nim_select;
 *   int                blist[5] = { 7, 0, 5, 5, 9 };
 *
 *   nim_orig   = nifti_image_read_bricks("myfile.nii", 0, NULL,  &NB_orig);
 *   nim_select = nifti_image_read_bricks("myfile.nii", 5, blist, &NB_select);
 * }
 * 
* * Here, nim_orig gets the entire dataset, where NB_orig.nbricks = 11. But * nim_select has NB_select.nbricks = 5. * * Note that the first case is not quite the same as just calling the * nifti_image_read function, as here the data is separated into sub-bricks. * * Note that valid blist elements are in [0..nt*nu*nv*nw-1], * or written [ 0 .. (dim[4]*dim[5]*dim[6]*dim[7] - 1) ]. * * Note that, as is the case with all of the reading functions, the * data will be allocated, read in, and properly byte-swapped, if * necessary. * * \sa nifti_image_load_bricks, nifti_free_NBL, valid_nifti_brick_list, nifti_image_read *//*----------------------------------------------------------------------*/ nifti_image *nifti_image_read_bricks(const char * hname, int nbricks, const int * blist, nifti_brick_list * NBL) { nifti_image * nim; if( !hname || !NBL ){ fprintf(stderr,"** nifti_image_read_bricks: bad params (%p,%p)\n", hname, (void *)NBL); return NULL; } if( blist && nbricks <= 0 ){ fprintf(stderr,"** nifti_image_read_bricks: bad nbricks, %d\n", nbricks); return NULL; } nim = nifti_image_read(hname, 0); /* read header, but not data */ if( !nim ) return NULL; /* errors were already printed */ /* if we fail, free image and return */ if( nifti_image_load_bricks(nim, nbricks, blist, NBL) <= 0 ){ nifti_image_free(nim); return NULL; } if( blist ) update_nifti_image_for_brick_list(nim, nbricks); return nim; } /*---------------------------------------------------------------------- * update_nifti_image_for_brick_list - update nifti_image * * When loading a specific brick list, the distinction between * nt, nu, nv and nw is lost. So put everything in t, and set * dim[0] = 4. *----------------------------------------------------------------------*/ static void update_nifti_image_for_brick_list( nifti_image * nim , int nbricks ) { int ndim; if( g_opts.debug > 2 ){ fprintf(stderr,"+d updating image dimensions for %d bricks in list\n", nbricks); fprintf(stderr," ndim = %d\n",nim->ndim); fprintf(stderr," nx,ny,nz,nt,nu,nv,nw: (%d,%d,%d,%d,%d,%d,%d)\n", nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw); } nim->nt = nbricks; nim->nu = nim->nv = nim->nw = 1; nim->dim[4] = nbricks; nim->dim[5] = nim->dim[6] = nim->dim[7] = 1; /* compute nvox */ /* do not rely on dimensions above dim[0] 16 Nov 2005 [rickr] */ for( nim->nvox = 1, ndim = 1; ndim <= nim->dim[0]; ndim++ ) nim->nvox *= nim->dim[ndim]; /* update the dimensions to 4 or lower */ for( ndim = 4; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- ) ; if( g_opts.debug > 2 ){ fprintf(stderr,"+d ndim = %d -> %d\n",nim->ndim, ndim); fprintf(stderr," --> (%d,%d,%d,%d,%d,%d,%d)\n", nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw); } nim->dim[0] = nim->ndim = ndim; } /*----------------------------------------------------------------------*/ /*! nifti_update_dims_from_array - update nx, ny, ... from nim->dim[] Fix all the dimension information, based on a new nim->dim[]. Note: we assume that dim[0] will not increase. Check for updates to pixdim[], dx,..., nx,..., nvox, ndim, dim[0]. *//*--------------------------------------------------------------------*/ int nifti_update_dims_from_array( nifti_image * nim ) { int c, ndim; if( !nim ){ fprintf(stderr,"** update_dims: missing nim\n"); return 1; } if( g_opts.debug > 2 ){ fprintf(stderr,"+d updating image dimensions given nim->dim:"); for( c = 0; c < 8; c++ ) fprintf(stderr," %d", nim->dim[c]); fputc('\n',stderr); } /* verify dim[0] first */ if(nim->dim[0] < 1 || nim->dim[0] > 7){ fprintf(stderr,"** invalid dim[0], dim[] = "); for( c = 0; c < 8; c++ ) fprintf(stderr," %d", nim->dim[c]); fputc('\n',stderr); return 1; } /* set nx, ny ..., dx, dy, ..., one by one */ /* less than 1, set to 1, else copy */ if(nim->dim[1] < 1) nim->nx = nim->dim[1] = 1; else nim->nx = nim->dim[1]; nim->dx = nim->pixdim[1]; /* if undefined, or less than 1, set to 1 */ if(nim->dim[0] < 2 || (nim->dim[0] >= 2 && nim->dim[2] < 1)) nim->ny = nim->dim[2] = 1; else nim->ny = nim->dim[2]; /* copy delta values, in any case */ nim->dy = nim->pixdim[2]; if(nim->dim[0] < 3 || (nim->dim[0] >= 3 && nim->dim[3] < 1)) nim->nz = nim->dim[3] = 1; else /* just copy vals from arrays */ nim->nz = nim->dim[3]; nim->dz = nim->pixdim[3]; if(nim->dim[0] < 4 || (nim->dim[0] >= 4 && nim->dim[4] < 1)) nim->nt = nim->dim[4] = 1; else /* just copy vals from arrays */ nim->nt = nim->dim[4]; nim->dt = nim->pixdim[4]; if(nim->dim[0] < 5 || (nim->dim[0] >= 5 && nim->dim[5] < 1)) nim->nu = nim->dim[5] = 1; else /* just copy vals from arrays */ nim->nu = nim->dim[5]; nim->du = nim->pixdim[5]; if(nim->dim[0] < 6 || (nim->dim[0] >= 6 && nim->dim[6] < 1)) nim->nv = nim->dim[6] = 1; else /* just copy vals from arrays */ nim->nv = nim->dim[6]; nim->dv = nim->pixdim[6]; if(nim->dim[0] < 7 || (nim->dim[0] >= 7 && nim->dim[7] < 1)) nim->nw = nim->dim[7] = 1; else /* just copy vals from arrays */ nim->nw = nim->dim[7]; nim->dw = nim->pixdim[7]; for( c = 1, nim->nvox = 1; c <= nim->dim[0]; c++ ) nim->nvox *= nim->dim[c]; /* compute ndim, assuming it can be no larger than the old one */ for( ndim = nim->dim[0]; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- ) ; if( g_opts.debug > 2 ){ fprintf(stderr,"+d ndim = %d -> %d\n",nim->ndim, ndim); fprintf(stderr," --> (%d,%d,%d,%d,%d,%d,%d)\n", nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw); } nim->dim[0] = nim->ndim = ndim; return 0; } /*----------------------------------------------------------------------*/ /*! Load the image data from disk into an already-prepared image struct. * * \param nim - initialized nifti_image, without data * \param nbricks - the length of blist (must be 0 if blist is NULL) * \param blist - an array of xyz volume indices to read (can be NULL) * \param NBL - pointer to struct where resulting data will be stored * * If blist is NULL, read all sub-bricks. * * \return the number of loaded bricks (NBL->nbricks), * 0 on failure, < 0 on error * * NOTE: it is likely that another function will copy the data pointers * out of NBL, in which case the only pointer the calling function * will want to free is NBL->bricks (not each NBL->bricks[i]). *//*--------------------------------------------------------------------*/ int nifti_image_load_bricks( nifti_image * nim , int nbricks, const int * blist, nifti_brick_list * NBL ) { int * slist = NULL, * sindex = NULL, rv; znzFile fp; /* we can have blist == NULL */ if( !nim || !NBL ){ fprintf(stderr,"** nifti_image_load_bricks, bad params (%p,%p)\n", (void *)nim, (void *)NBL); return -1; } if( blist && nbricks <= 0 ){ if( g_opts.debug > 1 ) fprintf(stderr,"-d load_bricks: received blist with nbricks = %d," "ignoring blist\n", nbricks); blist = NULL; /* pretend nothing was passed */ } if( blist && ! valid_nifti_brick_list( nim, nbricks, blist, g_opts.debug>0 ) ) return -1; /* for efficiency, let's read the file in order */ if( blist && nifti_copynsort( nbricks, blist, &slist, &sindex ) != 0 ) return -1; /* open the file and position the FILE pointer */ fp = nifti_image_load_prep( nim ); if( !fp ){ if( g_opts.debug > 0 ) fprintf(stderr,"** nifti_image_load_bricks, failed load_prep\n"); if( blist ){ free(slist); free(sindex); } return -1; } /* this will flag to allocate defaults */ if( !blist ) nbricks = 0; if( nifti_alloc_NBL_mem( nim, nbricks, NBL ) != 0 ){ if( blist ){ free(slist); free(sindex); } znzclose(fp); return -1; } rv = nifti_load_NBL_bricks(nim, slist, sindex, NBL, fp); if( rv != 0 ){ nifti_free_NBL( NBL ); /* failure! */ NBL->nbricks = 0; /* repetative, but clear */ } if( slist ){ free(slist); free(sindex); } znzclose(fp); return NBL->nbricks; } /*----------------------------------------------------------------------*/ /*! nifti_free_NBL - free all pointers and clear structure * * note: this does not presume to free the structure pointer *//*--------------------------------------------------------------------*/ void nifti_free_NBL( nifti_brick_list * NBL ) { int c; if( NBL->bricks ){ for( c = 0; c < NBL->nbricks; c++ ) if( NBL->bricks[c] ) free(NBL->bricks[c]); free(NBL->bricks); NBL->bricks = NULL; } NBL->nbricks = NBL->bsize = 0; } /*---------------------------------------------------------------------- * nifti_load_NBL_bricks - read the file data into the NBL struct * * return 0 on success, -1 on failure *----------------------------------------------------------------------*/ static int nifti_load_NBL_bricks( nifti_image * nim , int * slist, int * sindex, nifti_brick_list * NBL, znzFile fp ) { int c, rv; int oposn, fposn; /* orig and current file positions */ int prev, isrc, idest; /* previous and current sub-brick, and new index */ oposn = znztell(fp); /* store current file position */ fposn = oposn; if( fposn < 0 ){ fprintf(stderr,"** load bricks: ztell failed??\n"); return -1; } /* first, handle the default case, no passed blist */ if( !slist ){ for( c = 0; c < NBL->nbricks; c++ ) { rv = nifti_read_buffer(fp, NBL->bricks[c], NBL->bsize, nim); if( rv != NBL->bsize ){ fprintf(stderr,"** load bricks: cannot read brick %d from '%s'\n", c, nim->iname ? nim->iname : nim->fname); return -1; } } if( g_opts.debug > 1 ) fprintf(stderr,"+d read %d default bricks from file %s\n", NBL->nbricks, nim->iname ? nim->iname : nim->fname ); return 0; } if( !sindex ){ fprintf(stderr,"** load_NBL_bricks: missing index list\n"); return -1; } prev = -1; /* use prev for previous sub-brick */ for( c = 0; c < NBL->nbricks; c++ ){ isrc = slist[c]; /* this is original brick index (c is new one) */ idest = sindex[c]; /* this is the destination index for this data */ /* if this sub-brick is not the previous, we must read from disk */ if( isrc != prev ){ /* if we are not looking at the correct sub-brick, scan forward */ if( fposn != (oposn + isrc*NBL->bsize) ){ fposn = oposn + isrc*NBL->bsize; if( znzseek(fp, fposn, SEEK_SET) < 0 ){ fprintf(stderr,"** failed to locate brick %d in file '%s'\n", isrc, nim->iname ? nim->iname : nim->fname); return -1; } } /* only 10,000 lines later and we're actually reading something! */ rv = nifti_read_buffer(fp, NBL->bricks[idest], NBL->bsize, nim); if( rv != NBL->bsize ){ fprintf(stderr,"** failed to read brick %d from file '%s'\n", isrc, nim->iname ? nim->iname : nim->fname); return -1; } fposn += NBL->bsize; } else { /* we have already read this sub-brick, just copy the previous one */ /* note that this works because they are sorted */ memcpy(NBL->bricks[idest], NBL->bricks[sindex[c-1]], NBL->bsize); } prev = isrc; /* in any case, note the now previous sub-brick */ } return 0; } /*---------------------------------------------------------------------- * nifti_alloc_NBL_mem - allocate memory for bricks * * return 0 on success, -1 on failure *----------------------------------------------------------------------*/ static int nifti_alloc_NBL_mem(nifti_image * nim, int nbricks, nifti_brick_list * nbl) { int c; /* if nbricks is not specified, use the default */ if( nbricks > 0 ) nbl->nbricks = nbricks; else { /* I missed this one with the 1.17 change 02 Mar 2006 [rickr] */ nbl->nbricks = 1; for( c = 4; c <= nim->ndim; c++ ) nbl->nbricks *= nim->dim[c]; } nbl->bsize = nim->nx * nim->ny * nim->nz * nim->nbyper; /* bytes */ nbl->bricks = (void **)malloc(nbl->nbricks * sizeof(void *)); if( ! nbl->bricks ){ fprintf(stderr,"** NANM: failed to alloc %d void ptrs\n",nbricks); return -1; } for( c = 0; c < nbl->nbricks; c++ ){ nbl->bricks[c] = (void *)malloc(nbl->bsize); if( ! nbl->bricks[c] ){ fprintf(stderr,"** NANM: failed to alloc %d bytes for brick %d\n", nbl->bsize, c); /* so free and clear everything before returning */ while( c > 0 ){ c--; free(nbl->bricks[c]); } free(nbl->bricks); nbl->bricks = NULL; nbl->nbricks = nbl->bsize = 0; return -1; } } if( g_opts.debug > 2 ) fprintf(stderr,"+d NANM: alloc'd %d bricks of %d bytes for NBL\n", nbl->nbricks, nbl->bsize); return 0; } /*---------------------------------------------------------------------- * nifti_copynsort - copy int list, and sort with indices * * 1. duplicate the incoming list * 2. create an sindex list, and init with 0..nbricks-1 * 3. do a slow insertion sort on the small slist, along with sindex list * 4. check results, just to be positive * * So slist is sorted, and sindex hold original positions. * * return 0 on success, -1 on failure *----------------------------------------------------------------------*/ static int nifti_copynsort(int nbricks, const int * blist, int ** slist, int ** sindex) { int * stmp, * itmp; /* for ease of typing/reading */ int c1, c2, spos, tmp; *slist = (int *)malloc(nbricks * sizeof(int)); *sindex = (int *)malloc(nbricks * sizeof(int)); if( !*slist || !*sindex ){ fprintf(stderr,"** NCS: failed to alloc %d ints for sorting\n",nbricks); if(*slist) free(*slist); /* maybe one succeeded */ if(*sindex) free(*sindex); return -1; } /* init the lists */ memcpy(*slist, blist, nbricks*sizeof(int)); for( c1 = 0; c1 < nbricks; c1++ ) (*sindex)[c1] = c1; /* now actually sort slist */ stmp = *slist; itmp = *sindex; for( c1 = 0; c1 < nbricks-1; c1++ ) { /* find smallest value, init to current */ spos = c1; for( c2 = c1+1; c2 < nbricks; c2++ ) if( stmp[c2] < stmp[spos] ) spos = c2; if( spos != c1 ) /* swap: fine, don't maintain sub-order, see if I care */ { tmp = stmp[c1]; /* first swap the sorting values */ stmp[c1] = stmp[spos]; stmp[spos] = tmp; tmp = itmp[c1]; /* then swap the index values */ itmp[c1] = itmp[spos]; itmp[spos] = tmp; } } if( g_opts.debug > 2 ){ fprintf(stderr, "+d sorted indexing list:\n"); fprintf(stderr, " orig : "); for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr," %d",blist[c1]); fprintf(stderr,"\n new : "); for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr," %d",stmp[c1]); fprintf(stderr,"\n indices: "); for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr," %d",itmp[c1]); fputc('\n', stderr); } /* check the sort (why not? I've got time...) */ for( c1 = 0; c1 < nbricks-1; c1++ ){ if( (stmp[c1] > stmp[c1+1]) || (blist[itmp[c1]] != stmp[c1]) ){ fprintf(stderr,"** sorting screw-up, way to go, rick!\n"); free(stmp); free(itmp); *slist = NULL; *sindex = NULL; return -1; } } if( g_opts.debug > 2 ) fprintf(stderr,"-d sorting is okay\n"); return 0; } /*----------------------------------------------------------------------*/ /*! valid_nifti_brick_list - check sub-brick list for image * * This function verifies that nbricks and blist are appropriate * for use with this nim, based on the dimensions. * * \param nim nifti_image to check against * \param nbricks number of brick indices in blist * \param blist list of brick indices to check in nim * \param disp_error if this flag is set, report errors to user * * \return 1 if valid, 0 if not *//*--------------------------------------------------------------------*/ int valid_nifti_brick_list(nifti_image * nim , int nbricks, const int * blist, int disp_error) { int c, nsubs; if( !nim ){ if( disp_error || g_opts.debug > 0 ) fprintf(stderr,"** valid_nifti_brick_list: missing nifti image\n"); return 0; } if( nbricks <= 0 || !blist ){ if( disp_error || g_opts.debug > 1 ) fprintf(stderr,"** valid_nifti_brick_list: no brick list to check\n"); return 0; } /* nsubs sub-brick is nt*nu*nv*nw */ for( c = 4, nsubs = 1; c <= nim->dim[0]; c++ ) nsubs *= nim->dim[c]; if( nsubs <= 0 ){ fprintf(stderr,"** VNBL warning: bad dim list (%d,%d,%d,%d)\n", nim->dim[4], nim->dim[5], nim->dim[6], nim->dim[7]); return 0; } for( c = 0; c < nbricks; c++ ) if( (blist[c] < 0) || (blist[c] >= nsubs) ){ if( disp_error || g_opts.debug > 1 ) fprintf(stderr, "-d ** bad sub-brick chooser %d (#%d), valid range is [0,%d]\n", blist[c], c, nsubs-1); return 0; } return 1; /* all is well */ } #if 0 /* set any non-positive values to 1 */ static int int_force_positive( int * list, int nel ) { int c; if( !list || nel < 0 ){ if( g_opts.debug > 0 ) fprintf(stderr,"** int_force_positive: bad params (%p,%d)\n", (void *)list,nel); return -1; } for( c = 0; c < nel; c++ ) if( list[c] <= 0 ) list[c] = 1; return 0; } #endif /* end of new nifti_image_read_bricks() functionality */ /*----------------------------------------------------------------------*/ /*! display the orientation from the quaternian fields * * \param mesg if non-NULL, display this message first * \param mat the matrix to convert to "nearest" orientation * * \return -1 if results cannot be determined, 0 if okay *//*--------------------------------------------------------------------*/ int nifti_disp_matrix_orient( const char * mesg, mat44 mat ) { int i, j, k; if ( mesg ) fputs( mesg, stderr ); /* use stdout? */ nifti_mat44_to_orientation( mat, &i,&j,&k ); if ( i <= 0 || j <= 0 || k <= 0 ) return -1; /* so we have good codes */ fprintf(stderr, " i orientation = '%s'\n" " j orientation = '%s'\n" " k orientation = '%s'\n", nifti_orientation_string(i), nifti_orientation_string(j), nifti_orientation_string(k) ); return 0; } /*----------------------------------------------------------------------*/ /*! duplicate the given string (alloc length+1) * * \return allocated pointer (or NULL on failure) *//*--------------------------------------------------------------------*/ char *nifti_strdup(const char *str) { char *dup= (char *)malloc( strlen(str)+1 ); if (dup) strcpy(dup,str); return dup; } /*---------------------------------------------------------------------------*/ /*! Return a pointer to a string holding the name of a NIFTI datatype. \param dt NIfTI-1 datatype \return pointer to static string holding the datatype name \warning Do not free() or modify this string! It points to static storage. \sa NIFTI1_DATATYPES group in nifti1.h *//*-------------------------------------------------------------------------*/ char *nifti_datatype_string( int dt ) { switch( dt ){ case DT_UNKNOWN: return "UNKNOWN" ; case DT_BINARY: return "BINARY" ; case DT_INT8: return "INT8" ; case DT_UINT8: return "UINT8" ; case DT_INT16: return "INT16" ; case DT_UINT16: return "UINT16" ; case DT_INT32: return "INT32" ; case DT_UINT32: return "UINT32" ; case DT_INT64: return "INT64" ; case DT_UINT64: return "UINT64" ; case DT_FLOAT32: return "FLOAT32" ; case DT_FLOAT64: return "FLOAT64" ; case DT_FLOAT128: return "FLOAT128" ; case DT_COMPLEX64: return "COMPLEX64" ; case DT_COMPLEX128: return "COMPLEX128" ; case DT_COMPLEX256: return "COMPLEX256" ; case DT_RGB24: return "RGB24" ; } return "**ILLEGAL**" ; } /*----------------------------------------------------------------------*/ /*! Determine if the datatype code dt is an integer type (1=YES, 0=NO). \return whether the given NIfTI-1 datatype code is valid \sa NIFTI1_DATATYPES group in nifti1.h *//*--------------------------------------------------------------------*/ int nifti_is_inttype( int dt ) { switch( dt ){ case DT_UNKNOWN: return 0 ; case DT_BINARY: return 0 ; case DT_INT8: return 1 ; case DT_UINT8: return 1 ; case DT_INT16: return 1 ; case DT_UINT16: return 1 ; case DT_INT32: return 1 ; case DT_UINT32: return 1 ; case DT_INT64: return 1 ; case DT_UINT64: return 1 ; case DT_FLOAT32: return 0 ; case DT_FLOAT64: return 0 ; case DT_FLOAT128: return 0 ; case DT_COMPLEX64: return 0 ; case DT_COMPLEX128: return 0 ; case DT_COMPLEX256: return 0 ; case DT_RGB24: return 1 ; } return 0 ; } /*---------------------------------------------------------------------------*/ /*! Return a pointer to a string holding the name of a NIFTI units type. \param uu NIfTI-1 unit code \return pointer to static string for the given unit type \warning Do not free() or modify this string! It points to static storage. \sa NIFTI1_UNITS group in nifti1.h *//*-------------------------------------------------------------------------*/ char *nifti_units_string( int uu ) { switch( uu ){ case NIFTI_UNITS_METER: return "m" ; case NIFTI_UNITS_MM: return "mm" ; case NIFTI_UNITS_MICRON: return "um" ; case NIFTI_UNITS_SEC: return "s" ; case NIFTI_UNITS_MSEC: return "ms" ; case NIFTI_UNITS_USEC: return "us" ; case NIFTI_UNITS_HZ: return "Hz" ; case NIFTI_UNITS_PPM: return "ppm" ; case NIFTI_UNITS_RADS: return "rad/s" ; } return "Unknown" ; } /*---------------------------------------------------------------------------*/ /*! Return a pointer to a string holding the name of a NIFTI transform type. \param xx NIfTI-1 xform code \return pointer to static string describing xform code \warning Do not free() or modify this string! It points to static storage. \sa NIFTI1_XFORM_CODES group in nifti1.h *//*-------------------------------------------------------------------------*/ char *nifti_xform_string( int xx ) { switch( xx ){ case NIFTI_XFORM_SCANNER_ANAT: return "Scanner Anat" ; case NIFTI_XFORM_ALIGNED_ANAT: return "Aligned Anat" ; case NIFTI_XFORM_TALAIRACH: return "Talairach" ; case NIFTI_XFORM_MNI_152: return "MNI_152" ; } return "Unknown" ; } /*---------------------------------------------------------------------------*/ /*! Return a pointer to a string holding the name of a NIFTI intent type. \param ii NIfTI-1 intent code \return pointer to static string describing code \warning Do not free() or modify this string! It points to static storage. \sa NIFTI1_INTENT_CODES group in nifti1.h *//*-------------------------------------------------------------------------*/ char *nifti_intent_string( int ii ) { switch( ii ){ case NIFTI_INTENT_CORREL: return "Correlation statistic" ; case NIFTI_INTENT_TTEST: return "T-statistic" ; case NIFTI_INTENT_FTEST: return "F-statistic" ; case NIFTI_INTENT_ZSCORE: return "Z-score" ; case NIFTI_INTENT_CHISQ: return "Chi-squared distribution" ; case NIFTI_INTENT_BETA: return "Beta distribution" ; case NIFTI_INTENT_BINOM: return "Binomial distribution" ; case NIFTI_INTENT_GAMMA: return "Gamma distribution" ; case NIFTI_INTENT_POISSON: return "Poisson distribution" ; case NIFTI_INTENT_NORMAL: return "Normal distribution" ; case NIFTI_INTENT_FTEST_NONC: return "F-statistic noncentral" ; case NIFTI_INTENT_CHISQ_NONC: return "Chi-squared noncentral" ; case NIFTI_INTENT_LOGISTIC: return "Logistic distribution" ; case NIFTI_INTENT_LAPLACE: return "Laplace distribution" ; case NIFTI_INTENT_UNIFORM: return "Uniform distribition" ; case NIFTI_INTENT_TTEST_NONC: return "T-statistic noncentral" ; case NIFTI_INTENT_WEIBULL: return "Weibull distribution" ; case NIFTI_INTENT_CHI: return "Chi distribution" ; case NIFTI_INTENT_INVGAUSS: return "Inverse Gaussian distribution" ; case NIFTI_INTENT_EXTVAL: return "Extreme Value distribution" ; case NIFTI_INTENT_PVAL: return "P-value" ; case NIFTI_INTENT_LOGPVAL: return "Log P-value" ; case NIFTI_INTENT_LOG10PVAL: return "Log10 P-value" ; case NIFTI_INTENT_ESTIMATE: return "Estimate" ; case NIFTI_INTENT_LABEL: return "Label index" ; case NIFTI_INTENT_NEURONAME: return "NeuroNames index" ; case NIFTI_INTENT_GENMATRIX: return "General matrix" ; case NIFTI_INTENT_SYMMATRIX: return "Symmetric matrix" ; case NIFTI_INTENT_DISPVECT: return "Displacement vector" ; case NIFTI_INTENT_VECTOR: return "Vector" ; case NIFTI_INTENT_POINTSET: return "Pointset" ; case NIFTI_INTENT_TRIANGLE: return "Triangle" ; case NIFTI_INTENT_QUATERNION: return "Quaternion" ; case NIFTI_INTENT_DIMLESS: return "Dimensionless number" ; } return "Unknown" ; } /*---------------------------------------------------------------------------*/ /*! Return a pointer to a string holding the name of a NIFTI slice_code. \param ss NIfTI-1 slice order code \return pointer to static string describing code \warning Do not free() or modify this string! It points to static storage. \sa NIFTI1_SLICE_ORDER group in nifti1.h *//*-------------------------------------------------------------------------*/ char *nifti_slice_string( int ss ) { switch( ss ){ case NIFTI_SLICE_SEQ_INC: return "sequential_increasing" ; case NIFTI_SLICE_SEQ_DEC: return "sequential_decreasing" ; case NIFTI_SLICE_ALT_INC: return "alternating_increasing" ; case NIFTI_SLICE_ALT_DEC: return "alternating_decreasing" ; case NIFTI_SLICE_ALT_INC2: return "alternating_increasing_2" ; case NIFTI_SLICE_ALT_DEC2: return "alternating_decreasing_2" ; } return "Unknown" ; } /*---------------------------------------------------------------------------*/ /*! Return a pointer to a string holding the name of a NIFTI orientation. \param ii orientation code \return pointer to static string holding the orientation information \warning Do not free() or modify the return string! It points to static storage. \sa NIFTI_L2R in nifti1_io.h *//*-------------------------------------------------------------------------*/ char *nifti_orientation_string( int ii ) { switch( ii ){ case NIFTI_L2R: return "Left-to-Right" ; case NIFTI_R2L: return "Right-to-Left" ; case NIFTI_P2A: return "Posterior-to-Anterior" ; case NIFTI_A2P: return "Anterior-to-Posterior" ; case NIFTI_I2S: return "Inferior-to-Superior" ; case NIFTI_S2I: return "Superior-to-Inferior" ; } return "Unknown" ; } /*--------------------------------------------------------------------------*/ /*! Given a datatype code, set number of bytes per voxel and the swapsize. \param datatype nifti1 datatype code \param nbyper pointer to return value: number of bytes per voxel \param swapsize pointer to return value: size of swap blocks \return appropriate values at nbyper and swapsize The swapsize is set to 0 if this datatype doesn't ever need swapping. \sa NIFTI1_DATATYPES in nifti1.h *//*------------------------------------------------------------------------*/ void nifti_datatype_sizes( int datatype , int *nbyper, int *swapsize ) { int nb=0, ss=0 ; switch( datatype ){ case DT_INT8: case DT_UINT8: nb = 1 ; ss = 0 ; break ; case DT_INT16: case DT_UINT16: nb = 2 ; ss = 2 ; break ; case DT_RGB24: nb = 3 ; ss = 0 ; break ; case DT_INT32: case DT_UINT32: case DT_FLOAT32: nb = 4 ; ss = 4 ; break ; case DT_COMPLEX64: nb = 8 ; ss = 4 ; break ; case DT_FLOAT64: case DT_INT64: case DT_UINT64: nb = 8 ; ss = 8 ; break ; case DT_FLOAT128: nb = 16 ; ss = 16 ; break ; case DT_COMPLEX128: nb = 16 ; ss = 8 ; break ; case DT_COMPLEX256: nb = 32 ; ss = 16 ; break ; } ASSIF(nbyper,nb) ; ASSIF(swapsize,ss) ; return ; } /*---------------------------------------------------------------------------*/ /*! Given the quaternion parameters (etc.), compute a transformation matrix. See comments in nifti1.h for details. - qb,qc,qd = quaternion parameters - qx,qy,qz = offset parameters - dx,dy,dz = grid stepsizes (non-negative inputs are set to 1.0) - qfac = sign of dz step (< 0 is negative; >= 0 is positive)
   If qx=qy=qz=0, dx=dy=dz=1, then the output is a rotation matrix.
   For qfac >= 0, the rotation is proper.
   For qfac <  0, the rotation is improper.
   
\see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h \see nifti_mat44_to_quatern, nifti_make_orthog_mat44, nifti_mat44_to_orientation *//*-------------------------------------------------------------------------*/ mat44 nifti_quatern_to_mat44( float qb, float qc, float qd, float qx, float qy, float qz, float dx, float dy, float dz, float qfac ) { mat44 R ; double a,b=qb,c=qc,d=qd , xd,yd,zd ; /* last row is always [ 0 0 0 1 ] */ R.m[3][0]=R.m[3][1]=R.m[3][2] = 0.0 ; R.m[3][3]= 1.0 ; /* compute a parameter from b,c,d */ a = 1.0l - (b*b + c*c + d*d) ; if( a < 1.e-7l ){ /* special case */ a = 1.0l / sqrt(b*b+c*c+d*d) ; b *= a ; c *= a ; d *= a ; /* normalize (b,c,d) vector */ a = 0.0l ; /* a = 0 ==> 180 degree rotation */ } else{ a = sqrt(a) ; /* angle = 2*arccos(a) */ } /* load rotation matrix, including scaling factors for voxel sizes */ xd = (dx > 0.0) ? dx : 1.0l ; /* make sure are positive */ yd = (dy > 0.0) ? dy : 1.0l ; zd = (dz > 0.0) ? dz : 1.0l ; if( qfac < 0.0 ) zd = -zd ; /* left handedness? */ R.m[0][0] = (a*a+b*b-c*c-d*d) * xd ; R.m[0][1] = 2.0l * (b*c-a*d ) * yd ; R.m[0][2] = 2.0l * (b*d+a*c ) * zd ; R.m[1][0] = 2.0l * (b*c+a*d ) * xd ; R.m[1][1] = (a*a+c*c-b*b-d*d) * yd ; R.m[1][2] = 2.0l * (c*d-a*b ) * zd ; R.m[2][0] = 2.0l * (b*d-a*c ) * xd ; R.m[2][1] = 2.0l * (c*d+a*b ) * yd ; R.m[2][2] = (a*a+d*d-c*c-b*b) * zd ; /* load offsets */ R.m[0][3] = qx ; R.m[1][3] = qy ; R.m[2][3] = qz ; return R ; } /*---------------------------------------------------------------------------*/ /*! Given the 3x4 upper corner of the matrix R, compute the quaternion parameters that fit it. - Any NULL pointer on input won't get assigned (e.g., if you don't want dx,dy,dz, just pass NULL in for those pointers). - If the 3 input matrix columns are NOT orthogonal, they will be orthogonalized prior to calculating the parameters, using the polar decomposition to find the orthogonal matrix closest to the column-normalized input matrix. - However, if the 3 input matrix columns are NOT orthogonal, then the matrix produced by nifti_quatern_to_mat44 WILL have orthogonal columns, so it won't be the same as the matrix input here. This "feature" is because the NIFTI 'qform' transform is deliberately not fully general -- it is intended to model a volume with perpendicular axes. - If the 3 input matrix columns are not even linearly independent, you'll just have to take your luck, won't you? \see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h \see nifti_quatern_to_mat44, nifti_make_orthog_mat44, nifti_mat44_to_orientation *//*-------------------------------------------------------------------------*/ void nifti_mat44_to_quatern( mat44 R , float *qb, float *qc, float *qd, float *qx, float *qy, float *qz, float *dx, float *dy, float *dz, float *qfac ) { double r11,r12,r13 , r21,r22,r23 , r31,r32,r33 ; double xd,yd,zd , a,b,c,d ; mat33 P,Q ; /* offset outputs are read write out of input matrix */ ASSIF(qx,R.m[0][3]) ; ASSIF(qy,R.m[1][3]) ; ASSIF(qz,R.m[2][3]) ; /* load 3x3 matrix into local variables */ r11 = R.m[0][0] ; r12 = R.m[0][1] ; r13 = R.m[0][2] ; r21 = R.m[1][0] ; r22 = R.m[1][1] ; r23 = R.m[1][2] ; r31 = R.m[2][0] ; r32 = R.m[2][1] ; r33 = R.m[2][2] ; /* compute lengths of each column; these determine grid spacings */ xd = sqrt( r11*r11 + r21*r21 + r31*r31 ) ; yd = sqrt( r12*r12 + r22*r22 + r32*r32 ) ; zd = sqrt( r13*r13 + r23*r23 + r33*r33 ) ; /* if a column length is zero, patch the trouble */ if( xd == 0.0l ){ r11 = 1.0l ; r21 = r31 = 0.0l ; xd = 1.0l ; } if( yd == 0.0l ){ r22 = 1.0l ; r12 = r32 = 0.0l ; yd = 1.0l ; } if( zd == 0.0l ){ r33 = 1.0l ; r13 = r23 = 0.0l ; zd = 1.0l ; } /* assign the output lengths */ ASSIF(dx,xd) ; ASSIF(dy,yd) ; ASSIF(dz,zd) ; /* normalize the columns */ r11 /= xd ; r21 /= xd ; r31 /= xd ; r12 /= yd ; r22 /= yd ; r32 /= yd ; r13 /= zd ; r23 /= zd ; r33 /= zd ; /* At this point, the matrix has normal columns, but we have to allow for the fact that the hideous user may not have given us a matrix with orthogonal columns. So, now find the orthogonal matrix closest to the current matrix. One reason for using the polar decomposition to get this orthogonal matrix, rather than just directly orthogonalizing the columns, is so that inputting the inverse matrix to R will result in the inverse orthogonal matrix at this point. If we just orthogonalized the columns, this wouldn't necessarily hold. */ Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */ Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ; Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ; P = nifti_mat33_polar(Q) ; /* P is orthog matrix closest to Q */ r11 = P.m[0][0] ; r12 = P.m[0][1] ; r13 = P.m[0][2] ; /* unload */ r21 = P.m[1][0] ; r22 = P.m[1][1] ; r23 = P.m[1][2] ; r31 = P.m[2][0] ; r32 = P.m[2][1] ; r33 = P.m[2][2] ; /* [ r11 r12 r13 ] */ /* at this point, the matrix [ r21 r22 r23 ] is orthogonal */ /* [ r31 r32 r33 ] */ /* compute the determinant to determine if it is proper */ zd = r11*r22*r33-r11*r32*r23-r21*r12*r33 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; /* should be -1 or 1 */ if( zd > 0 ){ /* proper */ ASSIF(qfac,1.0) ; } else { /* improper ==> flip 3rd column */ ASSIF(qfac,-1.0) ; r13 = -r13 ; r23 = -r23 ; r33 = -r33 ; } /* now, compute quaternion parameters */ a = r11 + r22 + r33 + 1.0l ; if( a > 0.5l ){ /* simplest case */ a = 0.5l * sqrt(a) ; b = 0.25l * (r32-r23) / a ; c = 0.25l * (r13-r31) / a ; d = 0.25l * (r21-r12) / a ; } else { /* trickier case */ xd = 1.0 + r11 - (r22+r33) ; /* 4*b*b */ yd = 1.0 + r22 - (r11+r33) ; /* 4*c*c */ zd = 1.0 + r33 - (r11+r22) ; /* 4*d*d */ if( xd > 1.0 ){ b = 0.5l * sqrt(xd) ; c = 0.25l* (r12+r21) / b ; d = 0.25l* (r13+r31) / b ; a = 0.25l* (r32-r23) / b ; } else if( yd > 1.0 ){ c = 0.5l * sqrt(yd) ; b = 0.25l* (r12+r21) / c ; d = 0.25l* (r23+r32) / c ; a = 0.25l* (r13-r31) / c ; } else { d = 0.5l * sqrt(zd) ; b = 0.25l* (r13+r31) / d ; c = 0.25l* (r23+r32) / d ; a = 0.25l* (r21-r12) / d ; } if( a < 0.0l ){ b=-b ; c=-c ; d=-d; a=-a; } } ASSIF(qb,b) ; ASSIF(qc,c) ; ASSIF(qd,d) ; return ; } /*---------------------------------------------------------------------------*/ /*! Compute the inverse of a bordered 4x4 matrix.
   - Some numerical code fragments were generated by Maple 8.
   - If a singular matrix is input, the output matrix will be all zero.
   - You can check for this by examining the [3][3] element, which will
     be 1.0 for the normal case and 0.0 for the bad case.

     The input matrix should have the form:
        [ r11 r12 r13 v1 ]
        [ r21 r22 r23 v2 ]
        [ r31 r32 r33 v3 ]
        [  0   0   0   1 ]
     
*//*-------------------------------------------------------------------------*/ mat44 nifti_mat44_inverse( mat44 R ) { double r11,r12,r13,r21,r22,r23,r31,r32,r33,v1,v2,v3 , deti ; mat44 Q ; /* INPUT MATRIX IS: */ r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2]; /* [ r11 r12 r13 v1 ] */ r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2]; /* [ r21 r22 r23 v2 ] */ r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2]; /* [ r31 r32 r33 v3 ] */ v1 = R.m[0][3]; v2 = R.m[1][3]; v3 = R.m[2][3]; /* [ 0 0 0 1 ] */ deti = r11*r22*r33-r11*r32*r23-r21*r12*r33 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; if( deti != 0.0l ) deti = 1.0l / deti ; Q.m[0][0] = deti*( r22*r33-r32*r23) ; Q.m[0][1] = deti*(-r12*r33+r32*r13) ; Q.m[0][2] = deti*( r12*r23-r22*r13) ; Q.m[0][3] = deti*(-r12*r23*v3+r12*v2*r33+r22*r13*v3 -r22*v1*r33-r32*r13*v2+r32*v1*r23) ; Q.m[1][0] = deti*(-r21*r33+r31*r23) ; Q.m[1][1] = deti*( r11*r33-r31*r13) ; Q.m[1][2] = deti*(-r11*r23+r21*r13) ; Q.m[1][3] = deti*( r11*r23*v3-r11*v2*r33-r21*r13*v3 +r21*v1*r33+r31*r13*v2-r31*v1*r23) ; Q.m[2][0] = deti*( r21*r32-r31*r22) ; Q.m[2][1] = deti*(-r11*r32+r31*r12) ; Q.m[2][2] = deti*( r11*r22-r21*r12) ; Q.m[2][3] = deti*(-r11*r22*v3+r11*r32*v2+r21*r12*v3 -r21*r32*v1-r31*r12*v2+r31*r22*v1) ; Q.m[3][0] = Q.m[3][1] = Q.m[3][2] = 0.0l ; Q.m[3][3] = (deti == 0.0l) ? 0.0l : 1.0l ; /* failure flag if deti == 0 */ return Q ; } /*---------------------------------------------------------------------------*/ /*! Input 9 floats and make an orthgonal mat44 out of them. Each row is normalized, then nifti_mat33_polar() is used to orthogonalize them. If row #3 (r31,r32,r33) is input as zero, then it will be taken to be the cross product of rows #1 and #2. This function can be used to create a rotation matrix for transforming an oblique volume to anatomical coordinates. For this application: - row #1 (r11,r12,r13) is the direction vector along the image i-axis - row #2 (r21,r22,r23) is the direction vector along the image j-axis - row #3 (r31,r32,r33) is the direction vector along the slice direction (if available; otherwise enter it as 0's) The first 2 rows can be taken from the DICOM attribute (0020,0037) "Image Orientation (Patient)". After forming the rotation matrix, the complete affine transformation from (i,j,k) grid indexes to (x,y,z) spatial coordinates can be computed by multiplying each column by the appropriate grid spacing: - column #1 (R.m[0][0],R.m[1][0],R.m[2][0]) by delta-x - column #2 (R.m[0][1],R.m[1][1],R.m[2][1]) by delta-y - column #3 (R.m[0][2],R.m[1][2],R.m[2][2]) by delta-z and by then placing the center (x,y,z) coordinates of voxel (0,0,0) into the column #4 (R.m[0][3],R.m[1][3],R.m[2][3]). \sa nifti_quatern_to_mat44, nifti_mat44_to_quatern, nifti_mat44_to_orientation *//*-------------------------------------------------------------------------*/ mat44 nifti_make_orthog_mat44( float r11, float r12, float r13 , float r21, float r22, float r23 , float r31, float r32, float r33 ) { mat44 R ; mat33 Q , P ; double val ; R.m[3][0] = R.m[3][1] = R.m[3][2] = 0.0l ; R.m[3][3] = 1.0l ; Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */ Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ; Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ; /* normalize row 1 */ val = Q.m[0][0]*Q.m[0][0] + Q.m[0][1]*Q.m[0][1] + Q.m[0][2]*Q.m[0][2] ; if( val > 0.0l ){ val = 1.0l / sqrt(val) ; Q.m[0][0] *= val ; Q.m[0][1] *= val ; Q.m[0][2] *= val ; } else { Q.m[0][0] = 1.0l ; Q.m[0][1] = 0.0l ; Q.m[0][2] = 0.0l ; } /* normalize row 2 */ val = Q.m[1][0]*Q.m[1][0] + Q.m[1][1]*Q.m[1][1] + Q.m[1][2]*Q.m[1][2] ; if( val > 0.0l ){ val = 1.0l / sqrt(val) ; Q.m[1][0] *= val ; Q.m[1][1] *= val ; Q.m[1][2] *= val ; } else { Q.m[1][0] = 0.0l ; Q.m[1][1] = 1.0l ; Q.m[1][2] = 0.0l ; } /* normalize row 3 */ val = Q.m[2][0]*Q.m[2][0] + Q.m[2][1]*Q.m[2][1] + Q.m[2][2]*Q.m[2][2] ; if( val > 0.0l ){ val = 1.0l / sqrt(val) ; Q.m[2][0] *= val ; Q.m[2][1] *= val ; Q.m[2][2] *= val ; } else { Q.m[2][0] = Q.m[0][1]*Q.m[1][2] - Q.m[0][2]*Q.m[1][1] ; /* cross */ Q.m[2][1] = Q.m[0][2]*Q.m[1][0] - Q.m[0][0]*Q.m[1][2] ; /* product */ Q.m[2][2] = Q.m[0][0]*Q.m[1][1] - Q.m[0][1]*Q.m[1][0] ; } P = nifti_mat33_polar(Q) ; /* P is orthog matrix closest to Q */ R.m[0][0] = P.m[0][0] ; R.m[0][1] = P.m[0][1] ; R.m[0][2] = P.m[0][2] ; R.m[1][0] = P.m[1][0] ; R.m[1][1] = P.m[1][1] ; R.m[1][2] = P.m[1][2] ; R.m[2][0] = P.m[2][0] ; R.m[2][1] = P.m[2][1] ; R.m[2][2] = P.m[2][2] ; R.m[0][3] = R.m[1][3] = R.m[2][3] = 0.0 ; return R ; } /*----------------------------------------------------------------------*/ /*! compute the inverse of a 3x3 matrix *//*--------------------------------------------------------------------*/ mat33 nifti_mat33_inverse( mat33 R ) /* inverse of 3x3 matrix */ { double r11,r12,r13,r21,r22,r23,r31,r32,r33 , deti ; mat33 Q ; /* INPUT MATRIX: */ r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2]; /* [ r11 r12 r13 ] */ r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2]; /* [ r21 r22 r23 ] */ r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2]; /* [ r31 r32 r33 ] */ deti = r11*r22*r33-r11*r32*r23-r21*r12*r33 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; if( deti != 0.0l ) deti = 1.0l / deti ; Q.m[0][0] = deti*( r22*r33-r32*r23) ; Q.m[0][1] = deti*(-r12*r33+r32*r13) ; Q.m[0][2] = deti*( r12*r23-r22*r13) ; Q.m[1][0] = deti*(-r21*r33+r31*r23) ; Q.m[1][1] = deti*( r11*r33-r31*r13) ; Q.m[1][2] = deti*(-r11*r23+r21*r13) ; Q.m[2][0] = deti*( r21*r32-r31*r22) ; Q.m[2][1] = deti*(-r11*r32+r31*r12) ; Q.m[2][2] = deti*( r11*r22-r21*r12) ; return Q ; } /*----------------------------------------------------------------------*/ /*! compute the determinant of a 3x3 matrix *//*--------------------------------------------------------------------*/ float nifti_mat33_determ( mat33 R ) /* determinant of 3x3 matrix */ { double r11,r12,r13,r21,r22,r23,r31,r32,r33 ; /* INPUT MATRIX: */ r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2]; /* [ r11 r12 r13 ] */ r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2]; /* [ r21 r22 r23 ] */ r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2]; /* [ r31 r32 r33 ] */ return r11*r22*r33-r11*r32*r23-r21*r12*r33 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; } /*----------------------------------------------------------------------*/ /*! compute the max row norm of a 3x3 matrix *//*--------------------------------------------------------------------*/ float nifti_mat33_rownorm( mat33 A ) /* max row norm of 3x3 matrix */ { float r1,r2,r3 ; r1 = fabs(A.m[0][0])+fabs(A.m[0][1])+fabs(A.m[0][2]) ; r2 = fabs(A.m[1][0])+fabs(A.m[1][1])+fabs(A.m[1][2]) ; r3 = fabs(A.m[2][0])+fabs(A.m[2][1])+fabs(A.m[2][2]) ; if( r1 < r2 ) r1 = r2 ; if( r1 < r3 ) r1 = r3 ; return r1 ; } /*----------------------------------------------------------------------*/ /*! compute the max column norm of a 3x3 matrix *//*--------------------------------------------------------------------*/ float nifti_mat33_colnorm( mat33 A ) /* max column norm of 3x3 matrix */ { float r1,r2,r3 ; r1 = fabs(A.m[0][0])+fabs(A.m[1][0])+fabs(A.m[2][0]) ; r2 = fabs(A.m[0][1])+fabs(A.m[1][1])+fabs(A.m[2][1]) ; r3 = fabs(A.m[0][2])+fabs(A.m[1][2])+fabs(A.m[2][2]) ; if( r1 < r2 ) r1 = r2 ; if( r1 < r3 ) r1 = r3 ; return r1 ; } /*----------------------------------------------------------------------*/ /*! multiply 2 3x3 matrices *//*--------------------------------------------------------------------*/ mat33 nifti_mat33_mul( mat33 A , mat33 B ) /* multiply 2 3x3 matrices */ { mat33 C ; int i,j ; for( i=0 ; i < 3 ; i++ ) for( j=0 ; j < 3 ; j++ ) C.m[i][j] = A.m[i][0] * B.m[0][j] + A.m[i][1] * B.m[1][j] + A.m[i][2] * B.m[2][j] ; return C ; } /*---------------------------------------------------------------------------*/ /*! polar decomposition of a 3x3 matrix This finds the closest orthogonal matrix to input A (in both the Frobenius and L2 norms). Algorithm is that from NJ Higham, SIAM J Sci Stat Comput, 7:1160-1174. *//*-------------------------------------------------------------------------*/ mat33 nifti_mat33_polar( mat33 A ) { mat33 X , Y , Z ; float alp,bet,gam,gmi , dif=1.0 ; int k=0 ; X = A ; /* force matrix to be nonsingular */ gam = nifti_mat33_determ(X) ; while( gam == 0.0 ){ /* perturb matrix */ gam = 0.00001 * ( 0.001 + nifti_mat33_rownorm(X) ) ; X.m[0][0] += gam ; X.m[1][1] += gam ; X.m[2][2] += gam ; gam = nifti_mat33_determ(X) ; } while(1){ Y = nifti_mat33_inverse(X) ; if( dif > 0.3 ){ /* far from convergence */ alp = sqrt( nifti_mat33_rownorm(X) * nifti_mat33_colnorm(X) ) ; bet = sqrt( nifti_mat33_rownorm(Y) * nifti_mat33_colnorm(Y) ) ; gam = sqrt( bet / alp ) ; gmi = 1.0 / gam ; } else { gam = gmi = 1.0 ; /* close to convergence */ } Z.m[0][0] = 0.5 * ( gam*X.m[0][0] + gmi*Y.m[0][0] ) ; Z.m[0][1] = 0.5 * ( gam*X.m[0][1] + gmi*Y.m[1][0] ) ; Z.m[0][2] = 0.5 * ( gam*X.m[0][2] + gmi*Y.m[2][0] ) ; Z.m[1][0] = 0.5 * ( gam*X.m[1][0] + gmi*Y.m[0][1] ) ; Z.m[1][1] = 0.5 * ( gam*X.m[1][1] + gmi*Y.m[1][1] ) ; Z.m[1][2] = 0.5 * ( gam*X.m[1][2] + gmi*Y.m[2][1] ) ; Z.m[2][0] = 0.5 * ( gam*X.m[2][0] + gmi*Y.m[0][2] ) ; Z.m[2][1] = 0.5 * ( gam*X.m[2][1] + gmi*Y.m[1][2] ) ; Z.m[2][2] = 0.5 * ( gam*X.m[2][2] + gmi*Y.m[2][2] ) ; dif = fabs(Z.m[0][0]-X.m[0][0])+fabs(Z.m[0][1]-X.m[0][1]) +fabs(Z.m[0][2]-X.m[0][2])+fabs(Z.m[1][0]-X.m[1][0]) +fabs(Z.m[1][1]-X.m[1][1])+fabs(Z.m[1][2]-X.m[1][2]) +fabs(Z.m[2][0]-X.m[2][0])+fabs(Z.m[2][1]-X.m[2][1]) +fabs(Z.m[2][2]-X.m[2][2]) ; k = k+1 ; if( k > 100 || dif < 3.e-6 ) break ; /* convergence or exhaustion */ X = Z ; } return Z ; } /*---------------------------------------------------------------------------*/ /*! compute the (closest) orientation from a 4x4 ijk->xyz tranformation matrix
   Input:  4x4 matrix that transforms (i,j,k) indexes to (x,y,z) coordinates,
           where +x=Right, +y=Anterior, +z=Superior.
           (Only the upper-left 3x3 corner of R is used herein.)
   Output: 3 orientation codes that correspond to the closest "standard"
           anatomical orientation of the (i,j,k) axes.
   Method: Find which permutation of (x,y,z) has the smallest angle to the
           (i,j,k) axes directions, which are the columns of the R matrix.
   Errors: The codes returned will be zero.

   For example, an axial volume might get return values of
     *icod = NIFTI_R2L   (i axis is mostly Right to Left)
     *jcod = NIFTI_P2A   (j axis is mostly Posterior to Anterior)
     *kcod = NIFTI_I2S   (k axis is mostly Inferior to Superior)
   
\see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h \see nifti_quatern_to_mat44, nifti_mat44_to_quatern, nifti_make_orthog_mat44 *//*-------------------------------------------------------------------------*/ void nifti_mat44_to_orientation( mat44 R , int *icod, int *jcod, int *kcod ) { float xi,xj,xk , yi,yj,yk , zi,zj,zk , val,detQ,detP ; mat33 P , Q , M ; int i,j,k=0,p,q,r , ibest,jbest,kbest,pbest,qbest,rbest ; float vbest ; if( icod == NULL || jcod == NULL || kcod == NULL ) return ; /* bad */ *icod = *jcod = *kcod = 0 ; /* error returns, if sh*t happens */ /* load column vectors for each (i,j,k) direction from matrix */ /*-- i axis --*/ /*-- j axis --*/ /*-- k axis --*/ xi = R.m[0][0] ; xj = R.m[0][1] ; xk = R.m[0][2] ; yi = R.m[1][0] ; yj = R.m[1][1] ; yk = R.m[1][2] ; zi = R.m[2][0] ; zj = R.m[2][1] ; zk = R.m[2][2] ; /* normalize column vectors to get unit vectors along each ijk-axis */ /* normalize i axis */ val = sqrt( xi*xi + yi*yi + zi*zi ) ; if( val == 0.0 ) return ; /* stupid input */ xi /= val ; yi /= val ; zi /= val ; /* normalize j axis */ val = sqrt( xj*xj + yj*yj + zj*zj ) ; if( val == 0.0 ) return ; /* stupid input */ xj /= val ; yj /= val ; zj /= val ; /* orthogonalize j axis to i axis, if needed */ val = xi*xj + yi*yj + zi*zj ; /* dot product between i and j */ if( fabs(val) > 1.e-4 ){ xj -= val*xi ; yj -= val*yi ; zj -= val*zi ; val = sqrt( xj*xj + yj*yj + zj*zj ) ; /* must renormalize */ if( val == 0.0 ) return ; /* j was parallel to i? */ xj /= val ; yj /= val ; zj /= val ; } /* normalize k axis; if it is zero, make it the cross product i x j */ val = sqrt( xk*xk + yk*yk + zk*zk ) ; if( val == 0.0 ){ xk = yi*zj-zi*yj; yk = zi*xj-zj*xi ; zk=xi*yj-yi*xj ; } else { xk /= val ; yk /= val ; zk /= val ; } /* orthogonalize k to i */ val = xi*xk + yi*yk + zi*zk ; /* dot product between i and k */ if( fabs(val) > 1.e-4 ){ xk -= val*xi ; yk -= val*yi ; zk -= val*zi ; val = sqrt( xk*xk + yk*yk + zk*zk ) ; if( val == 0.0 ) return ; /* bad */ xk /= val ; yk /= val ; zk /= val ; } /* orthogonalize k to j */ val = xj*xk + yj*yk + zj*zk ; /* dot product between j and k */ if( fabs(val) > 1.e-4 ){ xk -= val*xj ; yk -= val*yj ; zk -= val*zj ; val = sqrt( xk*xk + yk*yk + zk*zk ) ; if( val == 0.0 ) return ; /* bad */ xk /= val ; yk /= val ; zk /= val ; } Q.m[0][0] = xi ; Q.m[0][1] = xj ; Q.m[0][2] = xk ; Q.m[1][0] = yi ; Q.m[1][1] = yj ; Q.m[1][2] = yk ; Q.m[2][0] = zi ; Q.m[2][1] = zj ; Q.m[2][2] = zk ; /* at this point, Q is the rotation matrix from the (i,j,k) to (x,y,z) axes */ detQ = nifti_mat33_determ( Q ) ; if( detQ == 0.0 ) return ; /* shouldn't happen unless user is a DUFIS */ /* Build and test all possible +1/-1 coordinate permutation matrices P; then find the P such that the rotation matrix M=PQ is closest to the identity, in the sense of M having the smallest total rotation angle. */ /* Despite the formidable looking 6 nested loops, there are only 3*3*3*2*2*2 = 216 passes, which will run very quickly. */ vbest = -666.0 ; ibest=pbest=qbest=rbest=1 ; jbest=2 ; kbest=3 ; for( i=1 ; i <= 3 ; i++ ){ /* i = column number to use for row #1 */ for( j=1 ; j <= 3 ; j++ ){ /* j = column number to use for row #2 */ if( i == j ) continue ; for( k=1 ; k <= 3 ; k++ ){ /* k = column number to use for row #3 */ if( i == k || j == k ) continue ; P.m[0][0] = P.m[0][1] = P.m[0][2] = P.m[1][0] = P.m[1][1] = P.m[1][2] = P.m[2][0] = P.m[2][1] = P.m[2][2] = 0.0 ; for( p=-1 ; p <= 1 ; p+=2 ){ /* p,q,r are -1 or +1 */ for( q=-1 ; q <= 1 ; q+=2 ){ /* and go into rows #1,2,3 */ for( r=-1 ; r <= 1 ; r+=2 ){ P.m[0][i-1] = p ; P.m[1][j-1] = q ; P.m[2][k-1] = r ; detP = nifti_mat33_determ(P) ; /* sign of permutation */ if( detP * detQ <= 0.0 ) continue ; /* doesn't match sign of Q */ M = nifti_mat33_mul(P,Q) ; /* angle of M rotation = 2.0*acos(0.5*sqrt(1.0+trace(M))) */ /* we want largest trace(M) == smallest angle == M nearest to I */ val = M.m[0][0] + M.m[1][1] + M.m[2][2] ; /* trace */ if( val > vbest ){ vbest = val ; ibest = i ; jbest = j ; kbest = k ; pbest = p ; qbest = q ; rbest = r ; } }}}}}} /* At this point ibest is 1 or 2 or 3; pbest is -1 or +1; etc. The matrix P that corresponds is the best permutation approximation to Q-inverse; that is, P (approximately) takes (x,y,z) coordinates to the (i,j,k) axes. For example, the first row of P (which contains pbest in column ibest) determines the way the i axis points relative to the anatomical (x,y,z) axes. If ibest is 2, then the i axis is along the y axis, which is direction P2A (if pbest > 0) or A2P (if pbest < 0). So, using ibest and pbest, we can assign the output code for the i axis. Mutatis mutandis for the j and k axes, of course. */ switch( ibest*pbest ){ case 1: i = NIFTI_L2R ; break ; case -1: i = NIFTI_R2L ; break ; case 2: i = NIFTI_P2A ; break ; case -2: i = NIFTI_A2P ; break ; case 3: i = NIFTI_I2S ; break ; case -3: i = NIFTI_S2I ; break ; } switch( jbest*qbest ){ case 1: j = NIFTI_L2R ; break ; case -1: j = NIFTI_R2L ; break ; case 2: j = NIFTI_P2A ; break ; case -2: j = NIFTI_A2P ; break ; case 3: j = NIFTI_I2S ; break ; case -3: j = NIFTI_S2I ; break ; } switch( kbest*rbest ){ case 1: k = NIFTI_L2R ; break ; case -1: k = NIFTI_R2L ; break ; case 2: k = NIFTI_P2A ; break ; case -2: k = NIFTI_A2P ; break ; case 3: k = NIFTI_I2S ; break ; case -3: k = NIFTI_S2I ; break ; } *icod = i ; *jcod = j ; *kcod = k ; return ; } /*---------------------------------------------------------------------------*/ /* Routines to swap byte arrays in various ways: - 2 at a time: ab -> ba [short] - 4 at a time: abcd -> dcba [int, float] - 8 at a time: abcdDCBA -> ABCDdcba [long long, double] - 16 at a time: abcdefghHGFEDCBA -> ABCDEFGHhgfedcba [long double] -----------------------------------------------------------------------------*/ typedef struct { unsigned char a,b ; } twobytes ; /*----------------------------------------------------------------------*/ /*! swap each byte pair from the given list of n pairs *//*--------------------------------------------------------------------*/ void nifti_swap_2bytes( int n , void *ar ) /* 2 bytes at a time */ { register int ii ; register twobytes *tb = (twobytes *)ar ; register unsigned char tt ; for( ii=0 ; ii < n ; ii++ ){ tt = tb[ii].a ; tb[ii].a = tb[ii].b ; tb[ii].b = tt ; } return ; } /*---------------------------------------------------------------------------*/ typedef struct { unsigned char a,b,c,d ; } fourbytes ; /*----------------------------------------------------------------------*/ /*! swap 4 bytes at a time from the given list of n sets of 4 bytes *//*--------------------------------------------------------------------*/ void nifti_swap_4bytes( int n , void *ar ) /* 4 bytes at a time */ { register int ii ; register fourbytes *tb = (fourbytes *)ar ; register unsigned char tt ; for( ii=0 ; ii < n ; ii++ ){ tt = tb[ii].a ; tb[ii].a = tb[ii].d ; tb[ii].d = tt ; tt = tb[ii].b ; tb[ii].b = tb[ii].c ; tb[ii].c = tt ; } return ; } /*---------------------------------------------------------------------------*/ typedef struct { unsigned char a,b,c,d , D,C,B,A ; } eightbytes ; /*----------------------------------------------------------------------*/ /*! swap 8 bytes at a time from the given list of n sets of 8 bytes *//*--------------------------------------------------------------------*/ void nifti_swap_8bytes( int n , void *ar ) /* 8 bytes at a time */ { register int ii ; register eightbytes *tb = (eightbytes *)ar ; register unsigned char tt ; for( ii=0 ; ii < n ; ii++ ){ tt = tb[ii].a ; tb[ii].a = tb[ii].A ; tb[ii].A = tt ; tt = tb[ii].b ; tb[ii].b = tb[ii].B ; tb[ii].B = tt ; tt = tb[ii].c ; tb[ii].c = tb[ii].C ; tb[ii].C = tt ; tt = tb[ii].d ; tb[ii].d = tb[ii].D ; tb[ii].D = tt ; } return ; } /*---------------------------------------------------------------------------*/ typedef struct { unsigned char a,b,c,d,e,f,g,h , H,G,F,E,D,C,B,A ; } sixteenbytes ; /*----------------------------------------------------------------------*/ /*! swap 16 bytes at a time from the given list of n sets of 16 bytes *//*--------------------------------------------------------------------*/ void nifti_swap_16bytes( int n , void *ar ) /* 16 bytes at a time */ { register int ii ; register sixteenbytes *tb = (sixteenbytes *)ar ; register unsigned char tt ; for( ii=0 ; ii < n ; ii++ ){ tt = tb[ii].a ; tb[ii].a = tb[ii].A ; tb[ii].A = tt ; tt = tb[ii].b ; tb[ii].b = tb[ii].B ; tb[ii].B = tt ; tt = tb[ii].c ; tb[ii].c = tb[ii].C ; tb[ii].C = tt ; tt = tb[ii].d ; tb[ii].d = tb[ii].D ; tb[ii].D = tt ; tt = tb[ii].e ; tb[ii].e = tb[ii].E ; tb[ii].E = tt ; tt = tb[ii].f ; tb[ii].f = tb[ii].F ; tb[ii].F = tt ; tt = tb[ii].g ; tb[ii].g = tb[ii].G ; tb[ii].G = tt ; tt = tb[ii].h ; tb[ii].h = tb[ii].H ; tb[ii].H = tt ; } return ; } /*---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /*! based on siz, call the appropriate nifti_swap_Nbytes() function *//*--------------------------------------------------------------------*/ void nifti_swap_Nbytes( int n , int siz , void *ar ) /* subsuming case */ { switch( siz ){ case 2: nifti_swap_2bytes ( n , ar ) ; break ; case 4: nifti_swap_4bytes ( n , ar ) ; break ; case 8: nifti_swap_8bytes ( n , ar ) ; break ; case 16: nifti_swap_16bytes( n , ar ) ; break ; } return ; } /*-------------------------------------------------------------------------*/ /*! Byte swap NIFTI-1 file header in various places and ways. If is_nifti is nonzero, will also swap the NIFTI-specific components of the header; otherwise, only the components common to NIFTI and ANALYZE will be swapped. *//*---------------------------------------------------------------------- */ void swap_nifti_header( struct nifti_1_header *h , int is_nifti ) { #if 0 /* ANALYZE fields not used by this software */ swap_4(h->sizeof_hdr) ; swap_4(h->extents) ; swap_2(h->session_error) ; swap_4(h->compressed) ; swap_4(h->glmax) ; swap_4(h->glmin) ; #endif /* this stuff is always present, for ANALYZE and NIFTI */ swap_4(h->sizeof_hdr) ; nifti_swap_2bytes( 8 , h->dim ) ; nifti_swap_4bytes( 8 , h->pixdim ) ; swap_2(h->datatype) ; swap_2(h->bitpix) ; swap_4(h->vox_offset); swap_4(h->cal_max); swap_4(h->cal_min); /* this stuff is NIFTI specific */ if( is_nifti ){ swap_4(h->intent_p1); swap_4(h->intent_p2); swap_4(h->intent_p3); swap_2(h->intent_code); swap_2(h->slice_start); swap_2(h->slice_end); swap_4(h->scl_slope); swap_4(h->scl_inter); swap_4(h->slice_duration); swap_4(h->toffset); swap_2(h->qform_code); swap_2(h->sform_code); swap_4(h->quatern_b); swap_4(h->quatern_c); swap_4(h->quatern_d); swap_4(h->qoffset_x); swap_4(h->qoffset_y); swap_4(h->qoffset_z); nifti_swap_4bytes(4,h->srow_x); nifti_swap_4bytes(4,h->srow_y); nifti_swap_4bytes(4,h->srow_z); } return ; } #define USE_STAT #ifdef USE_STAT /*---------------------------------------------------------------------------*/ /* Return the file length (0 if file not found or has no contents). This is a Unix-specific function, since it uses stat(). -----------------------------------------------------------------------------*/ #include #include /*---------------------------------------------------------------------------*/ /*! return the size of a file, in bytes \return size of file on success, -1 on error or no file changed to return int, -1 means no file or error 20 Dec 2004 [rickr] *//*-------------------------------------------------------------------------*/ int nifti_get_filesize( const char *pathname ) { struct stat buf ; int ii ; if( pathname == NULL || *pathname == '\0' ) return -1 ; ii = stat( pathname , &buf ); if( ii != 0 ) return -1 ; return (unsigned int)buf.st_size ; } #else /*---------- non-Unix version of the above, less efficient -----------*/ int nifti_get_filesize( const char *pathname ) { znzFile fp ; int len ; if( pathname == NULL || *pathname == '\0' ) return -1 ; fp = znzopen(pathname,"rb",0); if( znz_isnull(fp) ) return -1 ; znzseek(fp,0L,SEEK_END) ; len = znztell(fp) ; znzclose(fp) ; return len ; } #endif /* USE_STAT */ /*----------------------------------------------------------------------*/ /*! return the total volume size, in bytes This is computed as nvox * nbyper. *//*--------------------------------------------------------------------*/ size_t nifti_get_volsize(const nifti_image *nim) { return (size_t)(nim->nbyper) * (size_t)(nim->nvox) ; /* total bytes */ } /*--------------------------------------------------------------------------*/ /* Support functions for filenames in read and write - allows for gzipped files */ /*----------------------------------------------------------------------*/ /*! simple check for file existence \return 1 on existence, 0 otherwise *//*--------------------------------------------------------------------*/ int nifti_fileexists(const char* fname) { znzFile fp; fp = znzopen( fname , "rb" , 1 ) ; if( !znz_isnull(fp) ) { znzclose(fp); return 1; } return 0; /* fp is NULL */ } /*----------------------------------------------------------------------*/ /*! return whether the filename is valid The name is considered valid if the file basename has length greater than zero, AND one of the valid nifti extensions is provided. fname input | return | =============================== "myimage" | 0 | "myimage.tif" | 0 | "myimage.tif.gz" | 0 | "myimage.nii" | 1 | ".nii" | 0 | ".myhiddenimage" | 0 | ".myhiddenimage.nii" | 1 | *//*--------------------------------------------------------------------*/ int nifti_is_complete_filename(const char* fname) { char * ext; /* check input file(s) for sanity */ if( fname == NULL || *fname == '\0' ){ if ( g_opts.debug > 1 ) fprintf(stderr,"-- empty filename in nifti_validfilename()\n"); return 0; } ext = nifti_find_file_extension(fname); if ( ext == NULL ) { /*Invalid extension given */ if ( g_opts.debug > 0 ) fprintf(stderr,"-- no nifti valid extension for filename '%s'\n", fname); return 0; } if ( ext && ext == fname ) { /* then no filename prefix */ if ( g_opts.debug > 0 ) fprintf(stderr,"-- no prefix for filename '%s'\n", fname); return 0; } return 1; } /*----------------------------------------------------------------------*/ /*! return whether the filename is valid The name is considered valid if its length is positive, excluding any nifti filename extension. fname input | return | result of nifti_makebasename ==================================================================== "myimage" | 1 | "myimage" "myimage.tif" | 1 | "myimage.tif" "myimage.tif.gz" | 1 | "myimage.tif" "myimage.nii" | 1 | "myimage" ".nii" | 0 | ".myhiddenimage" | 1 | ".myhiddenimage" ".myhiddenimage.nii | 1 | ".myhiddenimage" *//*--------------------------------------------------------------------*/ int nifti_validfilename(const char* fname) { char * ext; /* check input file(s) for sanity */ if( fname == NULL || *fname == '\0' ){ if ( g_opts.debug > 1 ) fprintf(stderr,"-- empty filename in nifti_validfilename()\n"); return 0; } ext = nifti_find_file_extension(fname); if ( ext && ext == fname ) { /* then no filename prefix */ if ( g_opts.debug > 0 ) fprintf(stderr,"-- no prefix for filename '%s'\n", fname); return 0; } return 1; } /*----------------------------------------------------------------------*/ /*! check the end of the filename for a valid nifti extension Valid extensions are currently .nii, .hdr, .img, .nia, or any of them followed by .gz. Note that '.' is part of the extension. \return a pointer to the extension (within the filename), or NULL *//*--------------------------------------------------------------------*/ char * nifti_find_file_extension( const char * name ) { char * ext; int len; if ( ! name ) return NULL; len = strlen(name); if ( len < 4 ) return NULL; ext = (char *)name + len - 4; if ( (strcmp(ext, ".hdr") == 0) || (strcmp(ext, ".img") == 0) || (strcmp(ext, ".nia") == 0) || (strcmp(ext, ".nii") == 0) ) return ext; #ifdef HAVE_ZLIB if ( len < 7 ) return NULL; ext = (char *)name + len - 7; if ( (strcmp(ext, ".hdr.gz") == 0) || (strcmp(ext, ".img.gz") == 0) || (strcmp(ext, ".nia.gz") == 0) || (strcmp(ext, ".nii.gz") == 0) ) return ext; #endif if( g_opts.debug > 1 ) fprintf(stderr,"** find_file_ext: failed for name '%s'\n", name); return NULL; } /*----------------------------------------------------------------------*/ /*! return whether the filename ends in ".gz" *//*--------------------------------------------------------------------*/ int nifti_is_gzfile(const char* fname) { /* return true if the filename ends with .gz */ if (fname == NULL) { return 0; } #ifdef HAVE_ZLIB { /* just so len doesn't generate compile warning */ int len; len = strlen(fname); if (len < 3) return 0; /* so we don't search before the name */ if (strcmp(fname + strlen(fname) - 3,".gz")==0) { return 1; } } #endif return 0; } /*----------------------------------------------------------------------*/ /*! duplicate the filename, while clearing any extension This allocates memory for basename which should eventually be freed. *//*--------------------------------------------------------------------*/ char * nifti_makebasename(const char* fname) { char *basename, *ext; basename=nifti_strdup(fname); ext = nifti_find_file_extension(basename); if ( ext ) *ext = '\0'; /* clear out extension */ return basename; /* in either case */ } /*----------------------------------------------------------------------*/ /*! set nifti's global debug level, for status reporting - 0 : quiet, nothing is printed to the terminal, but errors - 1 : normal execution (the default) - 2, 3 : more details *//*--------------------------------------------------------------------*/ void nifti_set_debug_level( int level ) { g_opts.debug = level; } /*----------------------------------------------------------------------*/ /*! set nifti's global skip_blank_ext flag 5 Sep 2006 [rickr] explicitly set to 0 or 1 *//*--------------------------------------------------------------------*/ void nifti_set_skip_blank_ext( int skip ) { g_opts.skip_blank_ext = skip ? 1 : 0; } /*----------------------------------------------------------------------*/ /*! check current directory for existing header file \return filename of header on success and NULL if no appropriate file could be found NB: it allocates memory for hdrname which should be freed when no longer required *//*-------------------------------------------------------------------*/ char * nifti_findhdrname(const char* fname) { char *basename, *hdrname, *ext; char elist[2][5] = { ".hdr", ".nii" }; int efirst; /**- check input file(s) for sanity */ if( !nifti_validfilename(fname) ) return NULL; basename = nifti_makebasename(fname); if( !basename ) return NULL; /* only on string alloc failure */ /**- return filename if it has a valid extension and exists (except if it is an .img file (and maybe .gz)) */ ext = nifti_find_file_extension(fname); if ( ext && nifti_fileexists(fname) ) { if ( strncmp(ext,".img",4) != 0 ){ hdrname = nifti_strdup(fname); free(basename); return hdrname; } } /* So the requested name is a basename, contains .img, or does not exist. */ /* In any case, use basename. */ /**- if .img, look for .hdr, .hdr.gz, .nii, .nii.gz, in that order */ /**- else, look for .nii, .nii.gz, .hdr, .hdr.gz, in that order */ /* if we get more extension choices, this could be a loop */ if ( ext && strncmp(ext,".img",4) == 0 ) efirst = 0; else efirst = 1; hdrname = (char *)calloc(sizeof(char),strlen(basename)+8); if( !hdrname ){ fprintf(stderr,"** nifti_findhdrname: failed to alloc hdrname\n"); free(basename); return NULL; } strcpy(hdrname,basename); strcat(hdrname,elist[efirst]); if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } #ifdef HAVE_ZLIB strcat(hdrname,".gz"); if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } #endif /* okay, try the other possibility */ efirst = 1 - efirst; strcpy(hdrname,basename); strcat(hdrname,elist[efirst]); if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } #ifdef HAVE_ZLIB strcat(hdrname,".gz"); if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } #endif /**- if nothing has been found, return NULL */ free(basename); free(hdrname); return NULL; } /*------------------------------------------------------------------------*/ /*! check current directory for existing image file \param fname filename to check for \nifti_type nifti_type for dataset - this determines whether to first check for ".nii" or ".img" (since both may exist) \return filename of data/img file on success and NULL if no appropriate file could be found NB: it allocates memory for the image filename, which should be freed when no longer required *//*---------------------------------------------------------------------*/ char * nifti_findimgname(const char* fname , int nifti_type) { char *basename, *imgname, ext[2][5] = { ".nii", ".img" }; int first; /* first extension to use */ /* check input file(s) for sanity */ if( !nifti_validfilename(fname) ) return NULL; basename = nifti_makebasename(fname); imgname = (char *)calloc(sizeof(char),strlen(basename)+8); if( !imgname ){ fprintf(stderr,"** nifti_findimgname: failed to alloc imgname\n"); free(basename); return NULL; } /**- test for .nii and .img (don't assume input type from image type) */ /**- if nifti_type = 1, check for .nii first, else .img first */ /* if we get 3 or more extensions, can make a loop here... */ if (nifti_type == NIFTI_FTYPE_NIFTI1_1) first = 0; /* should match .nii */ else first = 1; /* should match .img */ strcpy(imgname,basename); strcat(imgname,ext[first]); if (nifti_fileexists(imgname)) { free(basename); return imgname; } #ifdef HAVE_ZLIB /* then also check for .gz */ strcat(imgname,".gz"); if (nifti_fileexists(imgname)) { free(basename); return imgname; } #endif /* failed to find image file with expected extension, try the other */ strcpy(imgname,basename); strcat(imgname,ext[1-first]); /* can do this with only 2 choices */ if (nifti_fileexists(imgname)) { free(basename); return imgname; } #ifdef HAVE_ZLIB /* then also check for .gz */ strcat(imgname,".gz"); if (nifti_fileexists(imgname)) { free(basename); return imgname; } #endif /**- if nothing has been found, return NULL */ free(basename); free(imgname); return NULL; } /*----------------------------------------------------------------------*/ /*! creates a filename for storing the header, based on nifti_type \param prefix - this will be copied before the suffix is added \param nifti_type - determines the extension, unless one is in prefix \param check - check for existence (fail condition) \param comp - add .gz for compressed name Note that if prefix provides a file suffix, nifti_type is not used. NB: this allocates memory which should be freed \sa nifti_set_filenames *//*-------------------------------------------------------------------*/ char * nifti_makehdrname(const char * prefix, int nifti_type, int check, int comp) { char * iname, * ext; if( !nifti_validfilename(prefix) ) return NULL; /* add space for extension, optional ".gz", and null char */ iname = (char *)calloc(sizeof(char),strlen(prefix)+8); if( !iname ){ fprintf(stderr,"** small malloc failure!\n"); return NULL; } strcpy(iname, prefix); /* use any valid extension */ if( (ext = nifti_find_file_extension(iname)) != NULL ){ if( strncmp(ext,".img",4) == 0 ) memcpy(ext,".hdr",4); /* then convert img name to hdr */ } /* otherwise, make one up an */ else if( nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcat(iname, ".nii"); else if( nifti_type == NIFTI_FTYPE_ASCII ) strcat(iname, ".nia"); else strcat(iname, ".hdr"); #ifdef HAVE_ZLIB /* then also check for .gz */ if( comp && (!ext || !strstr(iname,".gz")) ) strcat(iname,".gz"); #endif /* check for existence failure */ if( check && nifti_fileexists(iname) ){ fprintf(stderr,"** failure: header file '%s' already exists\n",iname); free(iname); return NULL; } if(g_opts.debug > 2) fprintf(stderr,"+d made header filename '%s'\n", iname); return iname; } /*----------------------------------------------------------------------*/ /*! creates a filename for storing the image, based on nifti_type \param prefix - this will be copied before the suffix is added \param nifti_type - determines the extension, unless provided by prefix \param check - check for existence (fail condition) \param comp - add .gz for compressed name Note that if prefix provides a file suffix, nifti_type is not used. NB: it allocates memory which should be freed \sa nifti_set_filenames *//*-------------------------------------------------------------------*/ char * nifti_makeimgname(const char * prefix, int nifti_type, int check, int comp) { char * iname, * ext; if( !nifti_validfilename(prefix) ) return NULL; /* add space for extension, optional ".gz", and null char */ iname = (char *)calloc(sizeof(char),strlen(prefix)+8); if( !iname ){ fprintf(stderr,"** small malloc failure!\n"); return NULL; } strcpy(iname, prefix); /* use any valid extension */ if( (ext = nifti_find_file_extension(iname)) != NULL ){ if( strncmp(ext,".hdr",4) == 0 ) memcpy(ext,".img",4); /* then convert hdr name to img */ } /* otherwise, make one up */ else if( nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcat(iname, ".nii"); else if( nifti_type == NIFTI_FTYPE_ASCII ) strcat(iname, ".nia"); else strcat(iname, ".img"); #ifdef HAVE_ZLIB /* then also check for .gz */ if( comp && (!ext || !strstr(iname,".gz")) ) strcat(iname,".gz"); #endif /* check for existence failure */ if( check && nifti_fileexists(iname) ){ fprintf(stderr,"** failure: image file '%s' already exists\n",iname); free(iname); return NULL; } if( g_opts.debug > 2 ) fprintf(stderr,"+d made image filename '%s'\n",iname); return iname; } /*----------------------------------------------------------------------*/ /*! create and set new filenames, based on prefix and image type \param nim pointer to nifti_image in which to set filenames \param prefix (required) prefix for output filenames \param check check for previous existence of filename (existence is an error condition) \param set_byte_order flag to set nim->byteorder here (this is probably a logical place to do so) \return 0 on successful update \warning this will free() any existing names and create new ones \sa nifti_makeimgname, nifti_makehdrname, nifti_type_and_names_match *//*--------------------------------------------------------------------*/ int nifti_set_filenames( nifti_image * nim, const char * prefix, int check, int set_byte_order ) { int comp = nifti_is_gzfile(prefix); if( !nim || !prefix ){ fprintf(stderr,"** nifti_set_filenames, bad params %p, %p\n", (void *)nim,prefix); return -1; } if( g_opts.debug > 1 ) fprintf(stderr,"+d modifying output filenames using prefix %s\n", prefix); if( nim->fname ) free(nim->fname); if( nim->iname ) free(nim->iname); nim->fname = nifti_makehdrname(prefix, nim->nifti_type, check, comp); nim->iname = nifti_makeimgname(prefix, nim->nifti_type, check, comp); if( !nim->fname || !nim->iname ){ LNI_FERR("nifti_set_filename","failed to set prefix for",prefix); return -1; } if( set_byte_order ) nim->byteorder = nifti_short_order() ; if( nifti_set_type_from_names(nim) < 0 ) return -1; if( g_opts.debug > 2 ) fprintf(stderr,"+d have new filenames %s and %s\n",nim->fname,nim->iname); return 0; } /*--------------------------------------------------------------------------*/ /*! check whether nifti_type matches fname and iname for the nifti_image - if type 0 or 2, expect .hdr/.img pair - if type 1, expect .nii (and names must match) \param nim given nifti_image \param show_warn if set, print a warning message for any mis-match \return - 1 if the values seem to match - 0 if there is a mis-match - -1 if there is not sufficient information to create file(s) \sa NIFTI_FTYPE_* codes in nifti1_io.h \sa nifti_set_type_from_names, is_valid_nifti_type *//*------------------------------------------------------------------------*/ int nifti_type_and_names_match( nifti_image * nim, int show_warn ) { char func[] = "nifti_type_and_names_match"; char * ext_h, * ext_i; /* header and image filename extensions */ int errs = 0; /* error counter */ /* sanity checks */ if( !nim ){ if( show_warn ) fprintf(stderr,"** %s: missing nifti_image\n", func); return -1; } if( !nim->fname ){ if( show_warn ) fprintf(stderr,"** %s: missing header filename\n", func); errs++; } if( !nim->iname ){ if( show_warn ) fprintf(stderr,"** %s: missing image filename\n", func); errs++; } if( !is_valid_nifti_type(nim->nifti_type) ){ if( show_warn ) fprintf(stderr,"** %s: bad nifti_type %d\n", func, nim->nifti_type); errs++; } if( errs ) return -1; /* then do not proceed */ /* get pointers to extensions */ ext_h = nifti_find_file_extension( nim->fname ); ext_i = nifti_find_file_extension( nim->iname ); /* check for filename extensions */ if( !ext_h ){ if( show_warn ) fprintf(stderr,"-d missing NIFTI extension in header filename, %s\n", nim->fname); errs++; } if( !ext_i ){ if( show_warn ) fprintf(stderr,"-d missing NIFTI extension in image filename, %s\n", nim->iname); errs++; } if( errs ) return 0; /* do not proceed, but this is just a mis-match */ /* general tests */ if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ){ /* .nii */ if( strncmp(ext_h,".nii",4) ) { if( show_warn ) fprintf(stderr, "-d NIFTI_FTYPE 1, but no .nii extension in header filename, %s\n", nim->fname); errs++; } if( strncmp(ext_i,".nii",4) ) { if( show_warn ) fprintf(stderr, "-d NIFTI_FTYPE 1, but no .nii extension in image filename, %s\n", nim->iname); errs++; } if( strcmp(nim->fname, nim->iname) != 0 ){ if( show_warn ) fprintf(stderr, "-d NIFTI_FTYPE 1, but header and image filenames differ: %s, %s\n", nim->fname, nim->iname); errs++; } } else if( (nim->nifti_type == NIFTI_FTYPE_NIFTI1_2) || /* .hdr/.img */ (nim->nifti_type == NIFTI_FTYPE_ANALYZE) ) { if( strncmp(ext_h,".hdr",4) != 0 ){ if( show_warn ) fprintf(stderr,"-d no '.hdr' extension, but NIFTI type is %d, %s\n", nim->nifti_type, nim->fname); errs++; } if( strncmp(ext_i,".img",4) != 0 ){ if( show_warn ) fprintf(stderr,"-d no '.img' extension, but NIFTI type is %d, %s\n", nim->nifti_type, nim->iname); errs++; } } /* ignore any other nifti_type */ return 1; } /*--------------------------------------------------------------------------*/ /*! check whether the given type is on the "approved" list The code is valid if it is non-negative, and does not exceed NIFTI_MAX_FTYPE. \return 1 if nifti_type is valid, 0 otherwise \sa NIFTI_FTYPE_* codes in nifti1_io.h *//*------------------------------------------------------------------------*/ int is_valid_nifti_type( int nifti_type ) { if( nifti_type >= NIFTI_FTYPE_ANALYZE && /* smallest type, 0 */ nifti_type <= NIFTI_MAX_FTYPE ) return 1; return 0; } /*--------------------------------------------------------------------------*/ /*! set the nifti_type field based on fname and iname Note that nifti_type is changed only when it does not match the filenames. \return 0 on success, -1 on error \sa is_valid_nifti_type, nifti_type_and_names_match *//*------------------------------------------------------------------------*/ int nifti_set_type_from_names( nifti_image * nim ) { /* error checking first */ if( !nim ){ fprintf(stderr,"** NSTFN: no nifti_image\n"); return -1; } if( !nim->fname || !nim->iname ){ fprintf(stderr,"** NSTFN: missing filename(s) fname @ %p, iname @ %p\n", nim->fname, nim->iname); return -1; } if( ! nifti_validfilename ( nim->fname ) || ! nifti_validfilename ( nim->iname ) || ! nifti_find_file_extension( nim->fname ) || ! nifti_find_file_extension( nim->iname ) ) { fprintf(stderr,"** NSTFN: invalid filename(s) fname='%s', iname='%s'\n", nim->fname, nim->iname); return -1; } if( g_opts.debug > 2 ) fprintf(stderr,"-d verify nifti_type from filenames: %d",nim->nifti_type); /* not too picky here, do what must be done, and then verify */ if( strcmp(nim->fname, nim->iname) == 0 ) /* one file, type 1 */ nim->nifti_type = NIFTI_FTYPE_NIFTI1_1; else if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ) /* cannot be type 1 */ nim->nifti_type = NIFTI_FTYPE_NIFTI1_2; if( g_opts.debug > 2 ) fprintf(stderr," -> %d\n",nim->nifti_type); if( g_opts.debug > 1 ) /* warn user about anything strange */ nifti_type_and_names_match(nim, 1); if( is_valid_nifti_type(nim->nifti_type) ) return 0; /* success! */ fprintf(stderr,"** NSTFN: bad nifti_type %d, for '%s' and '%s'\n", nim->nifti_type, nim->fname, nim->iname); return -1; } /*--------------------------------------------------------------------------*/ /*! Determine if this is a NIFTI-formatted file.
   \return  0 if file looks like ANALYZE 7.5 [checks sizeof_hdr field == 348]
            1 if file marked as NIFTI (header+data in 1 file)
            2 if file marked as NIFTI (header+data in 2 files)
           -1 if it can't tell, file doesn't exist, etc.
   
*//*------------------------------------------------------------------------*/ int is_nifti_file( const char *hname ) { struct nifti_1_header nhdr ; znzFile fp ; int ii ; char *tmpname; /* bad input name? */ if( !nifti_validfilename(hname) ) return -1 ; /* open file */ tmpname = nifti_findhdrname(hname); if( tmpname == NULL ){ if( g_opts.debug > 0 ) fprintf(stderr,"** no header file found for '%s'\n",hname); return -1; } fp = znzopen( tmpname , "rb" , nifti_is_gzfile(tmpname) ) ; free(tmpname); if (znz_isnull(fp)) return -1 ; /* bad open? */ /* read header, close file */ ii = znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ; znzclose( fp ) ; if( ii < (int) sizeof(nhdr) ) return -1 ; /* bad read? */ /* check for NIFTI-ness */ if( NIFTI_VERSION(nhdr) != 0 ){ return ( NIFTI_ONEFILE(nhdr) ) ? 1 : 2 ; } /* check for ANALYZE-ness (sizeof_hdr field == 348) */ ii = nhdr.sizeof_hdr ; if( ii == (int)sizeof(nhdr) ) return 0 ; /* matches */ /* try byte-swapping header */ swap_4(ii) ; if( ii == (int)sizeof(nhdr) ) return 0 ; /* matches */ return -1 ; /* not good */ } static int print_hex_vals( const char * data, int nbytes, FILE * fp ) { int c; if ( !data || nbytes < 1 || !fp ) return -1; fputs("0x", fp); for ( c = 0; c < nbytes; c++ ) fprintf(fp, " %x", data[c]); return 0; } /*----------------------------------------------------------------------*/ /*! display the contents of the nifti_1_header (send to stdout) \param info if non-NULL, print this character string \param hp pointer to nifti_1_header *//*--------------------------------------------------------------------*/ int disp_nifti_1_header( const char * info, const nifti_1_header * hp ) { int c; fputs( "-------------------------------------------------------\n", stdout ); if ( info ) fputs( info, stdout ); if ( !hp ){ fputs(" ** no nifti_1_header to display!\n",stdout); return 1; } fprintf(stdout," nifti_1_header :\n" " sizeof_hdr = %d\n" " data_type[10] = ", hp->sizeof_hdr); print_hex_vals(hp->data_type, 10, stdout); fprintf(stdout, "\n" " db_name[18] = "); print_hex_vals(hp->db_name, 18, stdout); fprintf(stdout, "\n" " extents = %d\n" " session_error = %d\n" " regular = 0x%x\n" " dim_info = 0x%x\n", hp->extents, hp->session_error, hp->regular, hp->dim_info ); fprintf(stdout, " dim[8] ="); for ( c = 0; c < 8; c++ ) fprintf(stdout," %d", hp->dim[c]); fprintf(stdout, "\n" " intent_p1 = %f\n" " intent_p2 = %f\n" " intent_p3 = %f\n" " intent_code = %d\n" " datatype = %d\n" " bitpix = %d\n" " slice_start = %d\n" " pixdim[8] =", hp->intent_p1, hp->intent_p2, hp->intent_p3, hp->intent_code, hp->datatype, hp->bitpix, hp->slice_start); /* break pixdim over 2 lines */ for ( c = 0; c < 4; c++ ) fprintf(stdout," %f", hp->pixdim[c]); fprintf(stdout, "\n "); for ( c = 4; c < 8; c++ ) fprintf(stdout," %f", hp->pixdim[c]); fprintf(stdout, "\n" " vox_offset = %f\n" " scl_slope = %f\n" " scl_inter = %f\n" " slice_end = %d\n" " slice_code = %d\n" " xyzt_units = 0x%x\n" " cal_max = %f\n" " cal_min = %f\n" " slice_duration = %f\n" " toffset = %f\n" " glmax = %d\n" " glmin = %d\n", hp->vox_offset, hp->scl_slope, hp->scl_inter, hp->slice_end, hp->slice_code, hp->xyzt_units, hp->cal_max, hp->cal_min, hp->slice_duration, hp->toffset, hp->glmax, hp->glmin); fprintf(stdout, " descrip = '%.80s'\n" " aux_file = '%.24s'\n" " qform_code = %d\n" " sform_code = %d\n" " quatern_b = %f\n" " quatern_c = %f\n" " quatern_d = %f\n" " qoffset_x = %f\n" " qoffset_y = %f\n" " qoffset_z = %f\n" " srow_x[4] = %f, %f, %f, %f\n" " srow_y[4] = %f, %f, %f, %f\n" " srow_z[4] = %f, %f, %f, %f\n" " intent_name = '%-.16s'\n" " magic = '%-.4s'\n", hp->descrip, hp->aux_file, hp->qform_code, hp->sform_code, hp->quatern_b, hp->quatern_c, hp->quatern_d, hp->qoffset_x, hp->qoffset_y, hp->qoffset_z, hp->srow_x[0], hp->srow_x[1], hp->srow_x[2], hp->srow_x[3], hp->srow_y[0], hp->srow_y[1], hp->srow_y[2], hp->srow_y[3], hp->srow_z[0], hp->srow_z[1], hp->srow_z[2], hp->srow_z[3], hp->intent_name, hp->magic); fputs( "-------------------------------------------------------\n", stdout ); fflush(stdout); return 0; } #undef ERREX #define ERREX(msg) \ do{ fprintf(stderr,"** ERROR: nifti_convert_nhdr2nim: %s\n", (msg) ) ; \ return NULL ; } while(0) /*----------------------------------------------------------------------*/ /*! convert a nifti_1_header into a nift1_image \return an allocated nifti_image, or NULL on failure *//*--------------------------------------------------------------------*/ nifti_image* nifti_convert_nhdr2nim(struct nifti_1_header nhdr, const char * fname) { int ii , doswap , ioff ; int is_nifti , is_onefile ; nifti_image *nim; nim = (nifti_image *) calloc( 1 , sizeof(nifti_image) ) ; if( !nim ) ERREX("failed to allocate nifti image"); /* be explicit with pointers */ nim->fname = NULL; nim->iname = NULL; nim->data = NULL; /**- check if we must swap bytes */ doswap = need_nhdr_swap(nhdr.dim[0], nhdr.sizeof_hdr); /* swap data flag */ if( doswap < 0 ){ if( doswap == -1 ) ERREX("bad dim[0]") ; ERREX("bad sizeof_hdr") ; /* else */ } /**- determine if this is a NIFTI-1 compliant header */ is_nifti = NIFTI_VERSION(nhdr) ; if( doswap ) { if ( g_opts.debug > 3 ) disp_nifti_1_header("-d ni1 pre-swap: ", &nhdr); swap_nifti_header( &nhdr , is_nifti ) ; } if ( g_opts.debug > 2 ) disp_nifti_1_header("-d nhdr2nim : ", &nhdr); if( nhdr.datatype == DT_BINARY || nhdr.datatype == DT_UNKNOWN ) ERREX("bad datatype") ; if( nhdr.dim[1] <= 0 ) ERREX("bad dim[1]") ; /* fix bad dim[] values in the defined dimension range */ for( ii=2 ; ii <= nhdr.dim[0] ; ii++ ) if( nhdr.dim[ii] <= 0 ) nhdr.dim[ii] = 1 ; /* fix any remaining bad dim[] values, so garbage does not propagate */ /* (only values 0 or 1 seem rational, otherwise set to arbirary 1) */ for( ii=nhdr.dim[0]+1 ; ii <= 7 ; ii++ ) if( nhdr.dim[ii] != 1 && nhdr.dim[ii] != 0) nhdr.dim[ii] = 1 ; #if 0 /* rely on dim[0], do not attempt to modify it 16 Nov 2005 [rickr] */ /**- get number of dimensions (ignoring dim[0] now) */ for( ii=7 ; ii >= 2 ; ii-- ) /* loop backwards until we */ if( nhdr.dim[ii] > 1 ) break ; /* find a dim bigger than 1 */ ndim = ii ; #endif /**- set bad grid spacings to 1.0 */ for( ii=1 ; ii <= nhdr.dim[0] ; ii++ ){ if( nhdr.pixdim[ii] == 0.0 || !IS_GOOD_FLOAT(nhdr.pixdim[ii]) ) nhdr.pixdim[ii] = 1.0 ; } is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ; if( is_nifti ) nim->nifti_type = (is_onefile) ? NIFTI_FTYPE_NIFTI1_1 : NIFTI_FTYPE_NIFTI1_2 ; else nim->nifti_type = NIFTI_FTYPE_ANALYZE ; ii = nifti_short_order() ; if( doswap ) nim->byteorder = REVERSE_ORDER(ii) ; else nim->byteorder = ii ; /**- set dimensions of data array */ nim->ndim = nim->dim[0] = nhdr.dim[0]; nim->nx = nim->dim[1] = nhdr.dim[1]; nim->ny = nim->dim[2] = nhdr.dim[2]; nim->nz = nim->dim[3] = nhdr.dim[3]; nim->nt = nim->dim[4] = nhdr.dim[4]; nim->nu = nim->dim[5] = nhdr.dim[5]; nim->nv = nim->dim[6] = nhdr.dim[6]; nim->nw = nim->dim[7] = nhdr.dim[7]; for( ii=1, nim->nvox=1; ii <= nhdr.dim[0]; ii++ ) nim->nvox *= nhdr.dim[ii]; /**- set the type of data in voxels and how many bytes per voxel */ nim->datatype = nhdr.datatype ; nifti_datatype_sizes( nim->datatype , &(nim->nbyper) , &(nim->swapsize) ) ; if( nim->nbyper == 0 ){ free(nim); ERREX("bad datatype"); } /**- set the grid spacings */ nim->dx = nim->pixdim[1] = nhdr.pixdim[1] ; nim->dy = nim->pixdim[2] = nhdr.pixdim[2] ; nim->dz = nim->pixdim[3] = nhdr.pixdim[3] ; nim->dt = nim->pixdim[4] = nhdr.pixdim[4] ; nim->du = nim->pixdim[5] = nhdr.pixdim[5] ; nim->dv = nim->pixdim[6] = nhdr.pixdim[6] ; nim->dw = nim->pixdim[7] = nhdr.pixdim[7] ; /**- compute qto_xyz transformation from pixel indexes (i,j,k) to (x,y,z) */ if( !is_nifti || nhdr.qform_code <= 0 ){ /**- if not nifti or qform_code <= 0, use grid spacing for qto_xyz */ nim->qto_xyz.m[0][0] = nim->dx ; /* grid spacings */ nim->qto_xyz.m[1][1] = nim->dy ; /* along diagonal */ nim->qto_xyz.m[2][2] = nim->dz ; /* off diagonal is zero */ nim->qto_xyz.m[0][1]=nim->qto_xyz.m[0][2]=nim->qto_xyz.m[0][3] = 0.0; nim->qto_xyz.m[1][0]=nim->qto_xyz.m[1][2]=nim->qto_xyz.m[1][3] = 0.0; nim->qto_xyz.m[2][0]=nim->qto_xyz.m[2][1]=nim->qto_xyz.m[2][3] = 0.0; /* last row is always [ 0 0 0 1 ] */ nim->qto_xyz.m[3][0]=nim->qto_xyz.m[3][1]=nim->qto_xyz.m[3][2] = 0.0; nim->qto_xyz.m[3][3]= 1.0 ; nim->qform_code = NIFTI_XFORM_UNKNOWN ; if( g_opts.debug > 1 ) fprintf(stderr,"-d no qform provided\n"); } else { /**- else NIFTI: use the quaternion-specified transformation */ nim->quatern_b = FIXED_FLOAT( nhdr.quatern_b ) ; nim->quatern_c = FIXED_FLOAT( nhdr.quatern_c ) ; nim->quatern_d = FIXED_FLOAT( nhdr.quatern_d ) ; nim->qoffset_x = FIXED_FLOAT(nhdr.qoffset_x) ; nim->qoffset_y = FIXED_FLOAT(nhdr.qoffset_y) ; nim->qoffset_z = FIXED_FLOAT(nhdr.qoffset_z) ; nim->qfac = (nhdr.pixdim[0] < 0.0) ? -1.0 : 1.0 ; /* left-handedness? */ nim->qto_xyz = nifti_quatern_to_mat44( nim->quatern_b, nim->quatern_c, nim->quatern_d, nim->qoffset_x, nim->qoffset_y, nim->qoffset_z, nim->dx , nim->dy , nim->dz , nim->qfac ) ; nim->qform_code = nhdr.qform_code ; if( g_opts.debug > 1 ) nifti_disp_matrix_orient("-d qform orientations:\n", nim->qto_xyz); } /**- load inverse transformation (x,y,z) -> (i,j,k) */ nim->qto_ijk = nifti_mat44_inverse( nim->qto_xyz ) ; /**- load sto_xyz affine transformation, if present */ if( !is_nifti || nhdr.sform_code <= 0 ){ /**- if not nifti or sform_code <= 0, then no sto transformation */ nim->sform_code = NIFTI_XFORM_UNKNOWN ; if( g_opts.debug > 1 ) fprintf(stderr,"-d no sform provided\n"); } else { /**- else set the sto transformation from srow_*[] */ nim->sto_xyz.m[0][0] = nhdr.srow_x[0] ; nim->sto_xyz.m[0][1] = nhdr.srow_x[1] ; nim->sto_xyz.m[0][2] = nhdr.srow_x[2] ; nim->sto_xyz.m[0][3] = nhdr.srow_x[3] ; nim->sto_xyz.m[1][0] = nhdr.srow_y[0] ; nim->sto_xyz.m[1][1] = nhdr.srow_y[1] ; nim->sto_xyz.m[1][2] = nhdr.srow_y[2] ; nim->sto_xyz.m[1][3] = nhdr.srow_y[3] ; nim->sto_xyz.m[2][0] = nhdr.srow_z[0] ; nim->sto_xyz.m[2][1] = nhdr.srow_z[1] ; nim->sto_xyz.m[2][2] = nhdr.srow_z[2] ; nim->sto_xyz.m[2][3] = nhdr.srow_z[3] ; /* last row is always [ 0 0 0 1 ] */ nim->sto_xyz.m[3][0]=nim->sto_xyz.m[3][1]=nim->sto_xyz.m[3][2] = 0.0; nim->sto_xyz.m[3][3]= 1.0 ; nim->sto_ijk = nifti_mat44_inverse( nim->sto_xyz ) ; nim->sform_code = nhdr.sform_code ; if( g_opts.debug > 1 ) nifti_disp_matrix_orient("-d sform orientations:\n", nim->sto_xyz); } /**- set miscellaneous NIFTI stuff */ if( is_nifti ){ nim->scl_slope = FIXED_FLOAT( nhdr.scl_slope ) ; nim->scl_inter = FIXED_FLOAT( nhdr.scl_inter ) ; nim->intent_code = nhdr.intent_code ; nim->intent_p1 = FIXED_FLOAT( nhdr.intent_p1 ) ; nim->intent_p2 = FIXED_FLOAT( nhdr.intent_p2 ) ; nim->intent_p3 = FIXED_FLOAT( nhdr.intent_p3 ) ; nim->toffset = FIXED_FLOAT( nhdr.toffset ) ; memcpy(nim->intent_name,nhdr.intent_name,15); nim->intent_name[15] = '\0'; nim->xyz_units = XYZT_TO_SPACE(nhdr.xyzt_units) ; nim->time_units = XYZT_TO_TIME (nhdr.xyzt_units) ; nim->freq_dim = DIM_INFO_TO_FREQ_DIM ( nhdr.dim_info ) ; nim->phase_dim = DIM_INFO_TO_PHASE_DIM( nhdr.dim_info ) ; nim->slice_dim = DIM_INFO_TO_SLICE_DIM( nhdr.dim_info ) ; nim->slice_code = nhdr.slice_code ; nim->slice_start = nhdr.slice_start ; nim->slice_end = nhdr.slice_end ; nim->slice_duration = FIXED_FLOAT(nhdr.slice_duration) ; } /**- set Miscellaneous ANALYZE stuff */ nim->cal_min = FIXED_FLOAT(nhdr.cal_min) ; nim->cal_max = FIXED_FLOAT(nhdr.cal_max) ; memcpy(nim->descrip ,nhdr.descrip ,79) ; nim->descrip [79] = '\0' ; memcpy(nim->aux_file,nhdr.aux_file,23) ; nim->aux_file[23] = '\0' ; /**- set ioff from vox_offset (but at least sizeof(header)) */ is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ; if( is_onefile ){ ioff = (int)nhdr.vox_offset ; if( ioff < (int) sizeof(nhdr) ) ioff = (int) sizeof(nhdr) ; } else { ioff = (int)nhdr.vox_offset ; } nim->iname_offset = ioff ; /**- deal with file names if set */ if (fname!=NULL) { nifti_set_filenames(nim,fname,0,0); if (nim->iname==NULL) { ERREX("bad filename"); } } else { nim->fname = NULL; nim->iname = NULL; } /* clear extension fields */ nim->num_ext = 0; nim->ext_list = NULL; return nim; } #undef ERREX #define ERREX(msg) \ do{ fprintf(stderr,"** ERROR: nifti_image_open(%s): %s\n", \ (hname != NULL) ? hname : "(null)" , (msg) ) ; \ return fptr ; } while(0) /*************************************************************** * nifti_image_open ***************************************************************/ /*! znzFile nifti_image_open( char *hname, char *opts , nifti_image **nim) \brief Read in NIFTI-1 or ANALYZE-7.5 file (pair) header information into a nifti_image struct. - The image data is not read from disk (it may be read later using nifti_image_load(), for example). - The image data will be stored in whatever data format the input data is; no scaling will be applied. - DT_BINARY data is not supported. - nifti_image_free() can be used to delete the returned struct, when you are done with it. \param hname filename of dataset .hdr or .nii file \param opts options string for opening the header file \param nim pointer to pointer to nifti_image struct (this routine allocates the nifti_image struct) \return file pointer (gzippable) to the file with the image data, ready for reading.
NULL if something fails badly. \sa nifti_image_load, nifti_image_free */ znzFile nifti_image_open(const char * hname, char * opts, nifti_image ** nim) { znzFile fptr=NULL; /* open the hdr and reading it in, but do not load the data */ *nim = nifti_image_read(hname,0); /* open the image file, ready for reading (compressed works for all reads) */ if( ((*nim) == NULL) || ((*nim)->iname == NULL) || ((*nim)->nbyper <= 0) || ((*nim)->nvox <= 0) ) ERREX("bad header info") ; /* open image data file */ fptr = znzopen( (*nim)->iname, opts, nifti_is_gzfile((*nim)->iname) ); if( znz_isnull(fptr) ) ERREX("Can't open data file") ; return fptr; } /*----------------------------------------------------------------------*/ /*! return an allocated and filled nifti_1_header struct Read the binary header from disk, and swap bytes if necessary. \return an allocated nifti_1_header struct, or NULL on failure \param hname name of file containing header \param swapped if not NULL, return whether header bytes were swapped \param check flag to check for invalid nifti_1_header \warning ASCII header type is not supported \sa nifti_image_read, nifti_image_free, nifti_image_read_bricks *//*--------------------------------------------------------------------*/ nifti_1_header * nifti_read_header(const char * hname, int * swapped, int check) { nifti_1_header nhdr, * hptr; znzFile fp; int bytes, lswap; char * hfile; char fname[] = { "nifti_read_header" }; /* determine file name to use for header */ hfile = nifti_findhdrname(hname); if( hfile == NULL ){ if( g_opts.debug > 0 ) LNI_FERR(fname,"failed to find header file for", hname); return NULL; } else if( g_opts.debug > 1 ) fprintf(stderr,"-d %s: found header filename '%s'\n",fname,hfile); fp = znzopen( hfile, "rb", nifti_is_gzfile(hfile) ); if( znz_isnull(fp) ){ if( g_opts.debug > 0 ) LNI_FERR(fname,"failed to open header file",hfile); free(hfile); return NULL; } free(hfile); /* done with filename */ if( has_ascii_header(fp) == 1 ){ znzclose( fp ); if( g_opts.debug > 0 ) LNI_FERR(fname,"ASCII header type not supported",hname); return NULL; } /* read the binary header */ bytes = znzread( &nhdr, 1, sizeof(nhdr), fp ); znzclose( fp ); /* we are done with the file now */ if( bytes < (int)sizeof(nhdr) ){ if( g_opts.debug > 0 ){ LNI_FERR(fname,"bad binary header read for file", hname); fprintf(stderr," - read %d of %d bytes\n",bytes, (int)sizeof(nhdr)); } return NULL; } /* now just decide on byte swapping */ lswap = need_nhdr_swap(nhdr.dim[0], nhdr.sizeof_hdr); /* swap data flag */ if( check && lswap < 0 ){ LNI_FERR(fname,"bad nifti_1_header for file", hname); return NULL; } if( lswap ) { if ( g_opts.debug > 3 ) disp_nifti_1_header("-d nhdr pre-swap: ", &nhdr); swap_nifti_header( &nhdr , NIFTI_VERSION(nhdr) ) ; } if ( g_opts.debug > 2 ) disp_nifti_1_header("-d nhdr post-swap: ", &nhdr); if ( check && ! nifti_hdr_looks_good(&nhdr) ){ LNI_FERR(fname,"nifti_1_header looks bad for file", hname); return NULL; } /* all looks good, so allocate memory for and return the header */ hptr = (nifti_1_header *)malloc(sizeof(nifti_1_header)); if( ! hptr ){ fprintf(stderr,"** nifti_read_hdr: failed to alloc nifti_1_header\n"); return NULL; } if( swapped ) *swapped = lswap; /* only if they care */ memcpy(hptr, &nhdr, sizeof(nifti_1_header)); return hptr; } /*----------------------------------------------------------------------*/ /*! decide if this nifti_1_header structure looks reasonable Check dim[0], dim[1], sizeof_hdr, and datatype. Check magic string for "n+1". Maybe more tests will follow. \return 1 if the header seems valid, 0 otherwise \sa nifti_nim_is_valid, valid_nifti_extensions *//*--------------------------------------------------------------------*/ int nifti_hdr_looks_good(const nifti_1_header * hdr) { int nbyper, swapsize; int c, errs = 0; /* check dim[0] and sizeof_hdr */ if( need_nhdr_swap(hdr->dim[0], hdr->sizeof_hdr) < 0 ){ if( g_opts.debug > 0 ) fprintf(stderr,"** bad nhdr fields: dim0, sizeof_hdr = %d, %d\n", hdr->dim[0], hdr->sizeof_hdr); errs++; } /* check the valid dimension sizes (maybe dim[0] is bad) */ for( c = 1; c <= hdr->dim[0] && c <= 7; c++ ) if( hdr->dim[c] <= 0 ){ if( g_opts.debug > 0 ) fprintf(stderr,"** bad nhdr field: dim[%d] = %d\n",c,hdr->dim[c]); errs++; } /* check the magic string */ if( (hdr->magic[0] != 'n') || (hdr->magic[1] != 'i' && hdr->magic[1] != '+') || (hdr->magic[2] != '1') || (hdr->magic[3] != '\0') ) { if( g_opts.debug > 0 ) fprintf(stderr, "** bad nhdr field: magic = '%.4s', should be \"n+1\" or \"ni1\"\n" " (in hex) magic = 0x%02x%02x%02x%02x\n" " should be = 0x6e2b3100 or 0x6e693100\n", hdr->magic, hdr->magic[0], hdr->magic[1], hdr->magic[2], hdr->magic[3]); errs++; } /* check the datatype */ if( hdr->datatype == DT_BINARY || hdr->datatype == DT_UNKNOWN ){ if( g_opts.debug > 0 ) fprintf(stderr,"** bad nhdr field: datatype = %d\n",hdr->datatype); errs++; } nifti_datatype_sizes(hdr->datatype, &nbyper, &swapsize); if( nbyper == 0 ){ if( g_opts.debug > 0 ) fprintf(stderr,"** bad nhdr field: datatype = %d\n",hdr->datatype); errs++; } if( errs ) return 0; /* problems */ if( g_opts.debug > 2 ) fprintf(stderr,"-d nifti header looks good\n"); return 1; /* looks good */ } /*---------------------------------------------------------------------- * check whether byte swapping is needed * * dim[0] should be in [0,7], and sizeof_hdr should be accurate * * \returns > 0 : needs swap * 0 : does not need swap * < 0 : error condition *----------------------------------------------------------------------*/ static int need_nhdr_swap( short dim0, int hdrsize ) { short d0 = dim0; /* so we won't have to swap them on the stack */ int hsize = hdrsize; if( d0 != 0 ){ /* then use it for the check */ if( d0 > 0 && d0 <= 7 ) return 0; nifti_swap_2bytes(1, &d0); /* swap? */ if( d0 > 0 && d0 <= 7 ) return 1; if( g_opts.debug > 1 ){ fprintf(stderr,"** bad swapped d0 = %d, unswapped = ", d0); nifti_swap_2bytes(1, &d0); /* swap? */ fprintf(stderr,"%d\n", d0); } return -1; /* bad, naughty d0 */ } /* dim[0] == 0 should not happen, but could, so try hdrsize */ if( hsize == sizeof(nifti_1_header) ) return 0; nifti_swap_4bytes(1, &hsize); /* swap? */ if( hsize == sizeof(nifti_1_header) ) return 1; if( g_opts.debug > 1 ){ fprintf(stderr,"** bad swapped hsize = %d, unswapped = ", hsize); nifti_swap_4bytes(1, &hsize); /* swap? */ fprintf(stderr,"%d\n", hsize); } return -2; /* bad, naughty hsize */ } /* use macro LNI_FILE_ERROR instead of ERREX() #undef ERREX #define ERREX(msg) \ do{ fprintf(stderr,"** ERROR: nifti_image_read(%s): %s\n", \ (hname != NULL) ? hname : "(null)" , (msg) ) ; \ return NULL ; } while(0) */ /*************************************************************** * nifti_image_read ***************************************************************/ /*! \brief Read a nifti header and optionally the data, creating a nifti_image. - The data buffer will be byteswapped if necessary. - The data buffer will not be scaled. - The data buffer is allocated with calloc(). \param hname filename of the nifti dataset \param read_data Flag, true=read data blob, false=don't read blob. \return A pointer to the nifti_image data structure. \sa nifti_image_free, nifti_free_extensions, nifti_image_read_bricks */ nifti_image *nifti_image_read( const char *hname , int read_data ) { struct nifti_1_header nhdr ; nifti_image *nim ; znzFile fp ; int rv, ii , filesize, remaining; char fname[] = { "nifti_image_read" }; char *hfile=NULL; if( g_opts.debug > 1 ){ fprintf(stderr,"-d image_read from '%s', read_data = %d",hname,read_data); #ifdef HAVE_ZLIB fprintf(stderr,", HAVE_ZLIB = 1\n"); #else fprintf(stderr,", HAVE_ZLIB = 0\n"); #endif } /**- determine filename to use for header */ hfile = nifti_findhdrname(hname); if( hfile == NULL ){ if(g_opts.debug > 0) LNI_FERR(fname,"failed to find header file for", hname); return NULL; /* check return */ } else if( g_opts.debug > 1 ) fprintf(stderr,"-d %s: found header filename '%s'\n",fname,hfile); if( nifti_is_gzfile(hfile) ) filesize = -1; /* unknown */ else filesize = nifti_get_filesize(hfile); fp = znzopen(hfile, "rb", nifti_is_gzfile(hfile)); if( znz_isnull(fp) ){ if( g_opts.debug > 0 ) LNI_FERR(fname,"failed to open header file",hfile); free(hfile); return NULL; } rv = has_ascii_header( fp ); if( rv < 0 ){ if( g_opts.debug > 0 ) LNI_FERR(fname,"short header read",hfile); znzclose( fp ); free(hfile); return NULL; } else if ( rv == 1 ) /* process special file type */ return nifti_read_ascii_image( fp, hfile, filesize, read_data ); /* else, just process normally */ /**- read binary header */ ii = znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ; /* read the thing */ /* keep file open so we can check for exts. after nifti_convert_nhdr2nim() */ if( ii < sizeof(nhdr) ){ if( g_opts.debug > 0 ){ LNI_FERR(fname,"bad binary header read for file", hfile); fprintf(stderr," - read %d of %d bytes\n",ii, (int)sizeof(nhdr)); } znzclose(fp) ; free(hfile); return NULL; } /* create output image struct and set it up */ /**- convert all nhdr fields to nifti_image fields */ nim = nifti_convert_nhdr2nim(nhdr,hfile); if( nim == NULL ){ znzclose( fp ) ; /* close the file */ if( g_opts.debug > 0 ) LNI_FERR(fname,"cannot create nifti image from header",hfile); free(hfile); /* had to save this for debug message */ return NULL; } if( g_opts.debug > 3 ){ fprintf(stderr,"+d nifti_image_read(), have nifti image:\n"); if( g_opts.debug > 2 ) nifti_image_infodump(nim); } /**- check for extensions (any errors here means no extensions) */ if( NIFTI_ONEFILE(nhdr) ) remaining = nim->iname_offset - sizeof(nhdr); else remaining = filesize - sizeof(nhdr); (void)nifti_read_extensions(nim, fp, remaining); znzclose( fp ) ; /* close the file */ free(hfile); /**- read the data if desired, then bug out */ if( read_data ){ if( nifti_image_load( nim ) < 0 ){ nifti_image_free(nim); /* take ball, go home. */ return NULL; } } else nim->data = NULL ; return nim ; } /*---------------------------------------------------------------------- * has_ascii_header - see if the NIFTI header is an ASCII format * * If the file starts with the ASCII string " 1 ) fprintf(stderr,"-d %s: have ASCII NIFTI file of size %d\n",fname,slen); if( slen > 65530 ) slen = 65530 ; sbuf = (char *)calloc(sizeof(char),slen+1) ; if( !sbuf ){ fprintf(stderr,"** %s: failed to alloc %d bytes for sbuf",lfunc,65530); free(fname); znzclose(fp); return NULL; } znzread( sbuf , 1 , slen , fp ) ; nim = nifti_image_from_ascii( sbuf, &txt_size ) ; free( sbuf ) ; if( nim == NULL ){ LNI_FERR(lfunc,"failed nifti_image_from_ascii()",fname); free(fname); znzclose(fp); return NULL; } nim->nifti_type = NIFTI_FTYPE_ASCII ; /* compute remaining space for extensions */ remain = flen - txt_size - (int)nifti_get_volsize(nim); if( remain > 4 ){ /* read extensions (reposition file pointer, first) */ znzseek(fp, txt_size, SEEK_SET); (void) nifti_read_extensions(nim, fp, remain); } free(fname); znzclose( fp ) ; nim->iname_offset = -1 ; /* check from the end of the file */ if( read_data ) rv = nifti_image_load( nim ) ; else nim->data = NULL ; /* check for nifti_image_load() failure, maybe bail out */ if( read_data && rv != 0 ){ if( g_opts.debug > 1 ) fprintf(stderr,"-d failed image_load, free nifti image struct\n"); free(nim); return NULL; } return nim ; } /*---------------------------------------------------------------------- * Read the extensions into the nifti_image struct 08 Dec 2004 [rickr] * * This function is called just after the header struct is read in, and * it is assumed the file pointer has not moved. The value in remain * is assumed to be accurate, reflecting the bytes of space for potential * extensions. * * return the number of extensions read in, or < 0 on error *----------------------------------------------------------------------*/ static int nifti_read_extensions( nifti_image *nim, znzFile fp, int remain ) { nifti1_extender extdr; /* defines extension existence */ nifti1_extension extn; /* single extension to process */ nifti1_extension * Elist; /* list of processed extensions */ int posn, count; if( !nim || znz_isnull(fp) ) { if( g_opts.debug > 0 ) fprintf(stderr,"** nifti_read_extensions: bad inputs (%p,%p)\n", (void *)nim, (void *)fp); return -1; } posn = znztell(fp); if( (posn != sizeof(nifti_1_header)) && (nim->nifti_type != NIFTI_FTYPE_ASCII) ) fprintf(stderr,"** WARNING: posn not header size (%d, %d)\n", posn, (int)sizeof(nifti_1_header)); if( g_opts.debug > 2 ) fprintf(stderr,"-d nre: posn = %d, offset = %d, type = %d, remain = %d\n", posn, nim->iname_offset, nim->nifti_type, remain); if( remain < 16 ){ if( g_opts.debug > 2 ){ if( g_opts.skip_blank_ext ) fprintf(stderr,"-d no extender in '%s' is okay, as " "skip_blank_ext is set\n",nim->fname); else fprintf(stderr,"-d no space for extensions\n"); } return 0; } count = znzread( extdr.extension, 1, 4, fp ); /* get extender */ if( count < 4 ){ if( g_opts.debug > 1 ) fprintf(stderr,"-d file '%s' is too short for an extender\n", nim->fname); return 0; } if( extdr.extension[0] != 1 ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d extender[0] (%d) shows no extensions for '%s'\n", extdr.extension[0], nim->fname); return 0; } remain -= 4; if( g_opts.debug > 2 ) fprintf(stderr,"-d found valid 4-byte extender, remain = %d\n", remain); /* so we expect extensions, but have no idea of how many there may be */ count = 0; Elist = NULL; while (nifti_read_next_extension(&extn, nim, remain, fp) > 0) { if( nifti_add_exten_to_list(&extn, &Elist, count+1) < 0 ){ if( g_opts.debug > 0 ) fprintf(stderr,"** failed adding ext %d to list\n", count); return -1; } /* we have a new extension */ if( g_opts.debug > 1 ){ fprintf(stderr,"+d found extension #%d, code = 0x%x, size = %d\n", count, extn.ecode, extn.esize); if( extn.ecode == NIFTI_ECODE_AFNI && g_opts.debug > 2 ) /* ~XML */ fprintf(stderr," AFNI extension: %.*s\n", extn.esize-8,extn.edata); else if( extn.ecode == NIFTI_ECODE_COMMENT && g_opts.debug > 2 ) fprintf(stderr," COMMENT extension: %.*s\n", /* TEXT */ extn.esize-8,extn.edata); } remain -= extn.esize; count++; } if( g_opts.debug > 2 ) fprintf(stderr,"+d found %d extension(s)\n", count); nim->num_ext = count; nim->ext_list = Elist; return count; } /*----------------------------------------------------------------------*/ /*! nifti_add_extension - add an extension, with a copy of the data Add an extension to the nim->ext_list array. Fill this extension with a copy of the data, noting the length and extension code. \param nim - nifti_image to add extension to \param data - raw extension data \param length - length of raw extension data \param ecode - extension code \sa extension codes NIFTI_ECODE_* in nifti1_io.h \sa nifti_free_extensions, valid_nifti_extensions, nifti_copy_extensions \return 0 on success, -1 on error (and free the entire list) *//*--------------------------------------------------------------------*/ int nifti_add_extension(nifti_image *nim, const char * data, int len, int ecode) { nifti1_extension ext; /* error are printed in functions */ if( nifti_fill_extension(&ext, data, len, ecode) ) return -1; if( nifti_add_exten_to_list(&ext, &nim->ext_list, nim->num_ext+1)) return -1; nim->num_ext++; /* success, so increment */ return 0; } /*----------------------------------------------------------------------*/ /* nifti_add_exten_to_list - add a new nifti1_extension to the list We will append via "malloc, copy and free", because on an error, the old data pointers must all be released (sorry realloc(), only quality dolphins get to become part of St@rk!st brand tunafish). return 0 on success, -1 on error (and free the entire list) *//*--------------------------------------------------------------------*/ static int nifti_add_exten_to_list( nifti1_extension * new_ext, nifti1_extension ** list, int new_length ) { nifti1_extension * tmplist; int count; tmplist = *list; *list = (nifti1_extension *)malloc(new_length * sizeof(nifti1_extension)); /* check for failure first */ if( ! *list ){ fprintf(stderr,"** failed to alloc %d extension structs (%d bytes)\n", new_length, new_length*(int)sizeof(nifti1_extension)); if( !tmplist ) return -1; /* no old list to lose */ for ( count = 0; count < new_length-1; count++ ) if( tmplist[count].edata ) free(tmplist[count].edata); free(tmplist); return -1; } /* we have memory, so copy the old and insert the new */ memcpy(*list, tmplist, (new_length-1)*sizeof(nifti1_extension)); /* for some reason, I just don't like struct copy... */ (*list)[new_length-1].esize = new_ext->esize; (*list)[new_length-1].ecode = new_ext->ecode; (*list)[new_length-1].edata = new_ext->edata; if( g_opts.debug > 2 ) fprintf(stderr,"+d allocated and appended extension #%d to list\n", new_length); return 0; } /*----------------------------------------------------------------------*/ /* nifti_fill_extension - given data and length, fill an extension struct Allocate memory for data, copy data, set the size and code. return 0 on success, -1 on error (and free the entire list) *//*--------------------------------------------------------------------*/ static int nifti_fill_extension( nifti1_extension *ext, const char * data, int len, int ecode) { int esize; if( !ext || !data || len < 0 ){ fprintf(stderr,"** fill_ext: bad params (%p,%p,%d)\n", (void *)ext, data, len); return -1; } else if( ! nifti_is_valid_ecode(ecode) ){ fprintf(stderr,"** fill_ext: invalid ecode %d\n", ecode); return -1; } /* compute esize, first : len+8, and take ceiling up to a mult of 16 */ esize = len+8; if( esize & 0xf ) esize = (esize + 0xf) & ~0xf; ext->esize = esize; /* allocate esize-8 (maybe more than len), using calloc for fill */ ext->edata = (char *)calloc(esize-8, sizeof(char)); if( !ext->edata ){ fprintf(stderr,"** NFE: failed to alloc %d bytes for extension\n",len); return -1; } memcpy(ext->edata, data, len); /* copy the data, using len */ ext->ecode = ecode; /* set the ecode */ if( g_opts.debug > 2 ) fprintf(stderr,"+d alloc %d bytes for ext len %d, ecode %d, esize %d\n", esize-8, len, ecode, esize); return 0; } /*---------------------------------------------------------------------- * nifti_read_next_extension - read a single extension from the file * * return (>= 0 is okay): * * success : esize * no extension : 0 * error : -1 *----------------------------------------------------------------------*/ static int nifti_read_next_extension( nifti1_extension * nex, nifti_image *nim, int remain, znzFile fp ) { int swap = nim->byteorder != nifti_short_order(); int count, size, code; /* first clear nex */ nex->esize = nex->ecode = 0; nex->edata = NULL; if( remain < 16 ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d only %d bytes remain, so no extension\n", remain); return 0; } /* must start with 4-byte size and code */ count = znzread( &size, 4, 1, fp ); if( count == 1 ) count += znzread( &code, 4, 1, fp ); if( count != 2 ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d current extension read failed\n"); znzseek(fp, -4*count, SEEK_CUR); /* back up past any read */ return 0; /* no extension, no error condition */ } if( swap ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d pre-swap exts: code %d, size %d\n", code, size); nifti_swap_4bytes(1, &size); nifti_swap_4bytes(1, &code); } if( g_opts.debug > 2 ) fprintf(stderr,"-d potential extension: code %d, size %d\n", code, size); if( !nifti_check_extension(nim, size, code, remain) ){ if( znzseek(fp, -8, SEEK_CUR) < 0 ){ /* back up past any read */ fprintf(stderr,"** failure to back out of extension read!\n"); return -1; } return 0; } /* now get the actual data */ nex->esize = size; nex->ecode = code; size -= 8; /* subtract space for size and code in extension */ nex->edata = (char *)malloc(size * sizeof(char)); if( !nex->edata ){ fprintf(stderr,"** failed to allocate %d bytes for extension\n",size); return -1; } count = znzread(nex->edata, 1, size, fp); if( count < size ){ if( g_opts.debug > 0 ) fprintf(stderr,"-d read only %d (of %d) bytes for extension\n", count, size); free(nex->edata); nex->edata = NULL; return -1; } /* success! */ if( g_opts.debug > 2 ) fprintf(stderr,"+d successfully read extension, code %d, size %d\n", nex->ecode, nex->esize); return nex->esize; } /*----------------------------------------------------------------------*/ /*! for each extension, check code, size and data pointer *//*--------------------------------------------------------------------*/ int valid_nifti_extensions(const nifti_image * nim) { nifti1_extension * ext; int c, errs; if( nim->num_ext <= 0 || nim->ext_list == NULL ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d empty extension list\n"); return 0; } /* for each extension, check code, size and data pointer */ ext = nim->ext_list; errs = 0; for ( c = 0; c < nim->num_ext; c++ ){ if( ! nifti_is_valid_ecode(ext->ecode) ) { if( g_opts.debug > 1 ) fprintf(stderr,"-d ext %d, invalid code %d\n", c, ext->ecode); errs++; } if( ext->esize <= 0 ){ if( g_opts.debug > 1 ) fprintf(stderr,"-d ext %d, bad size = %d\n", c, ext->esize); errs++; } else if( ext->esize & 0xf ){ if( g_opts.debug > 1 ) fprintf(stderr,"-d ext %d, size %d not multiple of 16\n", c, ext->esize); errs++; } if( ext->edata == NULL ){ if( g_opts.debug > 1 ) fprintf(stderr,"-d ext %d, missing data\n", c); errs++; } ext++; } if( errs > 0 ){ if( g_opts.debug > 0 ) fprintf(stderr,"-d had %d extension errors, none will be written\n", errs); return 0; } /* if we're here, we're good */ return 1; } /*----------------------------------------------------------------------*/ /*! check whether the extension code is valid \return 1 if valid, 0 otherwise *//*--------------------------------------------------------------------*/ int nifti_is_valid_ecode( int ecode ) { if( ecode < NIFTI_ECODE_IGNORE || /* minimum code number (0) */ ecode > NIFTI_MAX_ECODE || /* maximum code number */ ecode & 1 ) /* cannot be odd */ return 0; return 1; } /*---------------------------------------------------------------------- * check for valid size and code, as well as can be done *----------------------------------------------------------------------*/ static int nifti_check_extension(nifti_image *nim, int size, int code, int rem) { /* check for bad code before bad size */ if( ! nifti_is_valid_ecode(code) ) { if( g_opts.debug > 2 ) fprintf(stderr,"-d invalid extension code %d\n",code); return 0; } if( size < 16 ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d ext size %d, no extension\n",size); return 0; } if( size > rem ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d ext size %d, space %d, no extension\n", size, rem); return 0; } if( size & 0xf ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d nifti extension size %d not multiple of 16\n",size); return 0; } if( nim->nifti_type == NIFTI_FTYPE_ASCII && size > LNI_MAX_NIA_EXT_LEN ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d NVE, bad nifti_type 3 size %d\n", size); return 0; } return 1; } /*---------------------------------------------------------------------- * nifti_image_load_prep - prepare to read data * * Check nifti_image fields, open the file and seek to the appropriate * offset for reading. * * return NULL on failure *----------------------------------------------------------------------*/ static znzFile nifti_image_load_prep( nifti_image *nim ) { /* set up data space, open data file and seek, then call nifti_read_buffer */ size_t ntot , ii , ioff; znzFile fp; char fname[] = { "nifti_image_load_prep" }; /**- perform sanity checks */ if( nim == NULL || nim->iname == NULL || nim->nbyper <= 0 || nim->nvox <= 0 ) { if ( g_opts.debug > 0 ){ if( !nim ) fprintf(stderr,"** ERROR: N_image_load: no nifti image\n"); else fprintf(stderr,"** ERROR: N_image_load: bad params (%p,%d,%d)\n", nim->iname, nim->nbyper, nim->nvox); } return NULL; } ntot = nifti_get_volsize(nim) ; /* total bytes to read */ /**- open image data file */ fp = znzopen(nim->iname, "rb", nifti_is_gzfile(nim->iname)); if( znz_isnull(fp) ){ if( g_opts.debug > 0 ) LNI_FERR(fname,"cannot open data file",nim->iname); return NULL; } /**- get image offset: a negative offset means to figure from end of file */ if( nim->iname_offset < 0 ){ if( nifti_is_gzfile(nim->iname) ){ if( g_opts.debug > 0 ) LNI_FERR(fname,"negative offset for compressed file",nim->iname); znzclose(fp); return NULL; } ii = nifti_get_filesize( nim->iname ) ; if( ii <= 0 ){ if( g_opts.debug > 0 ) LNI_FERR(fname,"empty data file",nim->iname); znzclose(fp); return NULL; } ioff = (ii > ntot) ? ii-ntot : 0 ; } else { /* non-negative offset */ ioff = nim->iname_offset ; /* means use it directly */ } /**- seek to the appropriate read position */ if( znzseek(fp , ioff , SEEK_SET) < 0 ){ fprintf(stderr,"** could not seek to offset %d in file '%s'\n", (int)ioff, nim->iname); znzclose(fp); return NULL; } /**- and return the File pointer */ return fp; } /*---------------------------------------------------------------------- * nifti_image_load *----------------------------------------------------------------------*/ /*! \fn int nifti_image_load( nifti_image *nim ) \brief Load the image blob into a previously initialized nifti_image. - If not yet set, the data buffer is allocated with calloc(). - The data buffer will be byteswapped if necessary. - The data buffer will not be scaled. This function is used to read the image from disk. It should be used after a function such as nifti_image_read(), so that the nifti_image structure is already initialized. \param nim pointer to a nifti_image (previously initialized) \return 0 on success, -1 on failure \sa nifti_image_read, nifti_image_free, nifti_image_unload */ int nifti_image_load( nifti_image *nim ) { /* set up data space, open data file and seek, then call nifti_read_buffer */ size_t ntot , ii ; znzFile fp ; /**- open the file and position the FILE pointer */ fp = nifti_image_load_prep( nim ); if( fp == NULL ){ if( g_opts.debug > 0 ) fprintf(stderr,"** nifti_image_load, failed load_prep\n"); return -1; } ntot = nifti_get_volsize(nim); /**- if the data pointer is not yet set, get memory space for the image */ if( nim->data == NULL ) { nim->data = (void *)calloc(1,ntot) ; /* create image memory */ if( nim->data == NULL ){ if( g_opts.debug > 0 ) fprintf(stderr,"** failed to alloc %d bytes for image data\n", (int)ntot); znzclose(fp); return -1; } } /**- now that everything is set up, do the reading */ ii = nifti_read_buffer(fp,nim->data,ntot,nim); if( ii < ntot ){ znzclose(fp) ; free(nim->data) ; nim->data = NULL ; return -1 ; /* errors were printed in nifti_read_buffer() */ } /**- close the file */ znzclose( fp ) ; return 0 ; } /* 30 Nov 2004 [rickr] #undef ERREX #define ERREX(msg) \ do{ fprintf(stderr,"** ERROR: nifti_read_buffer: %s\n",(msg)) ; \ return 0; } while(0) */ /*----------------------------------------------------------------------*/ /*! read ntot bytes of data from an open file and byte swaps if necessary note that nifti_image is required for information on datatype, bsize (for any needed byte swapping), etc. This function does not allocate memory, so dataptr must be valid. *//*--------------------------------------------------------------------*/ size_t nifti_read_buffer(znzFile fp, void* dataptr, size_t ntot, nifti_image *nim) { size_t ii; if( dataptr == NULL ){ if( g_opts.debug > 0 ) fprintf(stderr,"** ERROR: nifti_read_buffer: NULL dataptr\n"); return -1; } ii = znzread( dataptr , 1 , ntot , fp ) ; /* data input */ /* if read was short, fail */ if( ii < ntot ){ if( g_opts.debug > 0 ) fprintf(stderr,"++ WARNING: nifti_read_buffer(%s):\n" " data bytes needed = %u\n" " data bytes input = %u\n" " number missing = %u (set to 0)\n", nim->iname , (unsigned int)ntot , (unsigned int)ii , (unsigned int)(ntot-ii) ) ; /* memset( (char *)(dataptr)+ii , 0 , ntot-ii ) ; now failure [rickr] */ return -1 ; } /* byte swap array if needed */ if( nim->swapsize > 1 && nim->byteorder != nifti_short_order() ) nifti_swap_Nbytes( ntot / nim->swapsize , nim->swapsize , dataptr ) ; #ifdef isfinite { /* check input float arrays for goodness, and fix bad floats */ int fix_count = 0 ; switch( nim->datatype ){ case NIFTI_TYPE_FLOAT32: case NIFTI_TYPE_COMPLEX64:{ register float *far = (float *)dataptr ; register int jj,nj ; nj = ntot / sizeof(float) ; for( jj=0 ; jj < nj ; jj++ ) /* count fixes 30 Nov 2004 [rickr] */ if( !IS_GOOD_FLOAT(far[jj]) ){ far[jj] = 0 ; fix_count++ ; } } break ; case NIFTI_TYPE_FLOAT64: case NIFTI_TYPE_COMPLEX128:{ register double *far = (double *)dataptr ; register int jj,nj ; nj = ntot / sizeof(double) ; for( jj=0 ; jj < nj ; jj++ ) /* count fixes 30 Nov 2004 [rickr] */ if( !IS_GOOD_FLOAT(far[jj]) ){ far[jj] = 0 ; fix_count++ ; } } break ; } if( g_opts.debug > 1 ) fprintf(stderr,"+d in image, %d bad floats were set to 0\n", fix_count); } #endif return ii; } /*--------------------------------------------------------------------------*/ /*! Unload the data in a nifti_image struct, but keep the metadata. *//*------------------------------------------------------------------------*/ void nifti_image_unload( nifti_image *nim ) { if( nim != NULL && nim->data != NULL ){ free(nim->data) ; nim->data = NULL ; } return ; } /*--------------------------------------------------------------------------*/ /*! free 'everything' about a nifti_image struct (including the passed struct) free (only fields which are not NULL): - fname and iname - data - any ext_list[i].edata - ext_list - nim *//*------------------------------------------------------------------------*/ void nifti_image_free( nifti_image *nim ) { if( nim == NULL ) return ; if( nim->fname != NULL ) free(nim->fname) ; if( nim->iname != NULL ) free(nim->iname) ; if( nim->data != NULL ) free(nim->data ) ; (void)nifti_free_extensions( nim ) ; free(nim) ; return ; } /*--------------------------------------------------------------------------*/ /*! free the nifti extensions - If any edata pointer is set in the extension list, free() it. - Free ext_list, if it is set. - Clear num_ext and ext_list from nim. \return 0 on success, -1 on error \sa nifti_add_extension, nifti_copy_extensions *//*------------------------------------------------------------------------*/ int nifti_free_extensions( nifti_image *nim ) { int c ; if( nim == NULL ) return -1; if( nim->num_ext > 0 && nim->ext_list ){ for( c = 0; c < nim->num_ext; c++ ) if ( nim->ext_list[c].edata ) free(nim->ext_list[c].edata); free(nim->ext_list); } /* or if it is inconsistent, warn the user (if we are not in quiet mode) */ else if ( (nim->num_ext > 0 || nim->ext_list != NULL) && (g_opts.debug > 0) ) fprintf(stderr,"** warning: nifti extension num/ptr mismatch (%d,%p)\n", nim->num_ext, (void *)nim->ext_list); if( g_opts.debug > 2 ) fprintf(stderr,"+d free'd %d extension(s)\n", nim->num_ext); nim->num_ext = 0; nim->ext_list = NULL; return 0; } /*--------------------------------------------------------------------------*/ /*! Print to stdout some info about a nifti_image struct. *//*------------------------------------------------------------------------*/ void nifti_image_infodump( const nifti_image *nim ) { char *str = nifti_image_to_ascii( nim ) ; /* stdout -> stderr 2 Dec 2004 [rickr] */ if( str != NULL ){ fputs(str,stderr) ; free(str) ; } return ; } /*-------------------------------------------------------------------------- * nifti_write_buffer just check for a null znzFile and call znzwrite *--------------------------------------------------------------------------*/ /*! \fn size_t nifti_write_buffer(znzFile fp, void *buffer, size_t numbytes) \brief write numbytes of buffer to file, fp \param fp File pointer (from znzopen) to gzippable nifti datafile \param buffer data buffer to be written \param numbytes number of bytes in buffer to write \return number of bytes successfully written */ size_t nifti_write_buffer(znzFile fp, const void *buffer, size_t numbytes) { /* Write all the image data at once (no swapping here) */ size_t ss; if (znz_isnull(fp)){ fprintf(stderr,"** ERROR: nifti_write_buffer: null file pointer\n"); return 0; } ss = znzwrite( (void*)buffer , 1 , numbytes , fp ) ; return ss; } /*----------------------------------------------------------------------*/ /*! write the nifti_image data to file (from nim->data or from NBL) If NBL is not NULL, write the data from that structure. Otherwise, write it out from nim->data. No swapping is done here. \param fp : File pointer \param nim : nifti_image corresponding to the data \param NBL : optional source of write data (if NULL use nim->data) \return 0 on success, -1 on failure Note: the nifti_image byte_order is set as that of the current CPU. This is because such a conversion was made to the data upon reading, while byte_order was not set (so the programs would know what format the data was on disk). Effectively, since byte_order should match what is on disk, it should bet set to that of the current CPU whenever new filenames are assigned. *//*--------------------------------------------------------------------*/ int nifti_write_all_data(znzFile fp, nifti_image * nim, const nifti_brick_list * NBL) { size_t ss; int bnum; if( !NBL ){ /* just write one buffer and get out of here */ if( nim->data == NULL ){ fprintf(stderr,"** NWAD: no image data to write\n"); return -1; } ss = nifti_write_buffer(fp,nim->data,nim->nbyper * nim->nvox); if (ss < (size_t)(nim->nbyper * nim->nvox)){ fprintf(stderr, "** ERROR: NWAD: wrote only %d of %d bytes to file\n", (int)ss, nim->nbyper * nim->nvox); return -1; } if( g_opts.debug > 1 ) fprintf(stderr,"+d wrote single image of %d bytes\n",(int)ss); } else { if( ! NBL->bricks || NBL->nbricks <= 0 || NBL->bsize <= 0 ){ fprintf(stderr,"** NWAD: no brick data to write (%p,%d,%d)\n", (void *)NBL->bricks, NBL->nbricks, NBL->bsize); return -1; } for( bnum = 0; bnum < NBL->nbricks; bnum++ ){ ss = nifti_write_buffer(fp, NBL->bricks[bnum], NBL->bsize); if( ss < (size_t)NBL->bsize ){ fprintf(stderr, "** NWAD ERROR: wrote %d of %d bytes of brick %d of %d to file", (int)ss, NBL->bsize, bnum+1, NBL->nbricks); return -1; } } if( g_opts.debug > 1 ) fprintf(stderr,"+d wrote image of %d brick(s), each of %d bytes\n", NBL->nbricks, NBL->bsize); } /* mark as being in this CPU byte order */ nim->byteorder = nifti_short_order() ; return 0; } /* return number of extensions written, or -1 on error */ static int nifti_write_extensions(znzFile fp, nifti_image *nim) { nifti1_extension * list; char extdr[4] = { 0, 0, 0, 0 }; int c, size, ok = 1; if( znz_isnull(fp) || !nim || nim->num_ext < 0 ){ if( g_opts.debug > 0 ) fprintf(stderr,"** nifti_write_extensions, bad params\n"); return -1; } /* if no extensions and user requests it, skip extender */ if( g_opts.skip_blank_ext && (nim->num_ext == 0 || ! nim->ext_list ) ){ if( g_opts.debug > 1 ) fprintf(stderr,"-d no exts and skip_blank_ext set, " "so skipping 4-byte extender\n"); return 0; } /* if invalid extension list, clear num_ext */ if( ! valid_nifti_extensions(nim) ) nim->num_ext = 0; /* write out extender block */ if( nim->num_ext > 0 ) extdr[0] = 1; if( nifti_write_buffer(fp, extdr, 4) != 4 ){ fprintf(stderr,"** failed to write extender\n"); return -1; } list = nim->ext_list; for ( c = 0; c < nim->num_ext; c++ ){ size = nifti_write_buffer(fp, &list->esize, sizeof(int)); ok = (size == (int)sizeof(int)); if( ok ){ size = nifti_write_buffer(fp, &list->ecode, sizeof(int)); ok = (size == (int)sizeof(int)); } if( ok ){ size = nifti_write_buffer(fp, list->edata, list->esize - 8); ok = (size == list->esize - 8); } if( !ok ){ fprintf(stderr,"** failed while writing extension #%d\n",c); return -1; } list++; } if( g_opts.debug > 1 ) fprintf(stderr,"+d wrote out %d extension(s)\n", nim->num_ext); return nim->num_ext; } /*----------------------------------------------------------------------*/ /*! basic initialization of a nifti_image struct (to a 1x1x1 image) *//*--------------------------------------------------------------------*/ nifti_image* nifti_simple_init_nim(void) { nifti_image *nim; struct nifti_1_header nhdr; int nbyper, swapsize; memset(&nhdr,0,sizeof(nhdr)) ; /* zero out header, to be safe */ nhdr.sizeof_hdr = sizeof(nhdr) ; nhdr.regular = 'r' ; /* for some stupid reason */ nhdr.dim[0] = 3 ; nhdr.dim[1] = 1 ; nhdr.dim[2] = 1 ; nhdr.dim[3] = 1 ; nhdr.dim[4] = 0 ; nhdr.pixdim[0] = 0.0 ; nhdr.pixdim[1] = 1.0 ; nhdr.pixdim[2] = 1.0 ; nhdr.pixdim[3] = 1.0 ; nhdr.datatype = DT_FLOAT32 ; nifti_datatype_sizes( nhdr.datatype , &nbyper, &swapsize ); nhdr.bitpix = 8 * nbyper ; nim = nifti_convert_nhdr2nim(nhdr,NULL); nim->fname = NULL; nim->iname = NULL; return nim; } /*----------------------------------------------------------------------*/ /*! convert a nifti_image structure to a nifti_1_header struct No allocation is done, this should be used via structure copy. As in:
    nifti_1_header my_header;
    my_header = nifti_convert_nim2nhdr(my_nim_pointer);
    
*//*--------------------------------------------------------------------*/ struct nifti_1_header nifti_convert_nim2nhdr(const nifti_image * nim) { struct nifti_1_header nhdr; memset(&nhdr,0,sizeof(nhdr)) ; /* zero out header, to be safe */ /**- load the ANALYZE-7.5 generic parts of the header struct */ nhdr.sizeof_hdr = sizeof(nhdr) ; nhdr.regular = 'r' ; /* for some stupid reason */ nhdr.dim[0] = nim->ndim ; nhdr.dim[1] = nim->nx ; nhdr.dim[2] = nim->ny ; nhdr.dim[3] = nim->nz ; nhdr.dim[4] = nim->nt ; nhdr.dim[5] = nim->nu ; nhdr.dim[6] = nim->nv ; nhdr.dim[7] = nim->nw ; nhdr.pixdim[0] = 0.0 ; nhdr.pixdim[1] = nim->dx ; nhdr.pixdim[2] = nim->dy ; nhdr.pixdim[3] = nim->dz ; nhdr.pixdim[4] = nim->dt ; nhdr.pixdim[5] = nim->du ; nhdr.pixdim[6] = nim->dv ; nhdr.pixdim[7] = nim->dw ; nhdr.datatype = nim->datatype ; nhdr.bitpix = 8 * nim->nbyper ; if( nim->cal_max > nim->cal_min ){ nhdr.cal_max = nim->cal_max ; nhdr.cal_min = nim->cal_min ; } if( nim->scl_slope != 0.0 ){ nhdr.scl_slope = nim->scl_slope ; nhdr.scl_inter = nim->scl_inter ; } if( nim->descrip[0] != '\0' ){ memcpy(nhdr.descrip ,nim->descrip ,79) ; nhdr.descrip[79] = '\0' ; } if( nim->aux_file[0] != '\0' ){ memcpy(nhdr.aux_file ,nim->aux_file ,23) ; nhdr.aux_file[23] = '\0' ; } /**- Load NIFTI specific stuff into the header */ if( nim->nifti_type > NIFTI_FTYPE_ANALYZE ){ /* then not ANALYZE */ if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcpy(nhdr.magic,"n+1") ; else strcpy(nhdr.magic,"ni1") ; nhdr.pixdim[1] = fabs(nhdr.pixdim[1]) ; nhdr.pixdim[2] = fabs(nhdr.pixdim[2]) ; nhdr.pixdim[3] = fabs(nhdr.pixdim[3]) ; nhdr.pixdim[4] = fabs(nhdr.pixdim[4]) ; nhdr.pixdim[5] = fabs(nhdr.pixdim[5]) ; nhdr.pixdim[6] = fabs(nhdr.pixdim[6]) ; nhdr.pixdim[7] = fabs(nhdr.pixdim[7]) ; nhdr.intent_code = nim->intent_code ; nhdr.intent_p1 = nim->intent_p1 ; nhdr.intent_p2 = nim->intent_p2 ; nhdr.intent_p3 = nim->intent_p3 ; if( nim->intent_name[0] != '\0' ){ memcpy(nhdr.intent_name,nim->intent_name,15) ; nhdr.intent_name[15] = '\0' ; } nhdr.vox_offset = (float) nim->iname_offset ; nhdr.xyzt_units = SPACE_TIME_TO_XYZT( nim->xyz_units, nim->time_units ) ; nhdr.toffset = nim->toffset ; if( nim->qform_code > 0 ){ nhdr.qform_code = nim->qform_code ; nhdr.quatern_b = nim->quatern_b ; nhdr.quatern_c = nim->quatern_c ; nhdr.quatern_d = nim->quatern_d ; nhdr.qoffset_x = nim->qoffset_x ; nhdr.qoffset_y = nim->qoffset_y ; nhdr.qoffset_z = nim->qoffset_z ; nhdr.pixdim[0] = (nim->qfac >= 0.0) ? 1.0 : -1.0 ; } if( nim->sform_code > 0 ){ nhdr.sform_code = nim->sform_code ; nhdr.srow_x[0] = nim->sto_xyz.m[0][0] ; nhdr.srow_x[1] = nim->sto_xyz.m[0][1] ; nhdr.srow_x[2] = nim->sto_xyz.m[0][2] ; nhdr.srow_x[3] = nim->sto_xyz.m[0][3] ; nhdr.srow_y[0] = nim->sto_xyz.m[1][0] ; nhdr.srow_y[1] = nim->sto_xyz.m[1][1] ; nhdr.srow_y[2] = nim->sto_xyz.m[1][2] ; nhdr.srow_y[3] = nim->sto_xyz.m[1][3] ; nhdr.srow_z[0] = nim->sto_xyz.m[2][0] ; nhdr.srow_z[1] = nim->sto_xyz.m[2][1] ; nhdr.srow_z[2] = nim->sto_xyz.m[2][2] ; nhdr.srow_z[3] = nim->sto_xyz.m[2][3] ; } nhdr.dim_info = FPS_INTO_DIM_INFO( nim->freq_dim , nim->phase_dim , nim->slice_dim ) ; nhdr.slice_code = nim->slice_code ; nhdr.slice_start = nim->slice_start ; nhdr.slice_end = nim->slice_end ; nhdr.slice_duration = nim->slice_duration ; } return nhdr; } /*----------------------------------------------------------------------*/ /*! \fn int nifti_copy_extensions(nifti_image * nim_dest, nifti_image * nim_src) \brief copy the nifti1_extension list from src to dest Duplicate the list of nifti1_extensions. The dest structure must be clear of extensions. \return 0 on success, -1 on failure \sa nifti_add_extension, nifti_free_extensions */ int nifti_copy_extensions(nifti_image * nim_dest, const nifti_image * nim_src) { char * data; size_t bytes; int c, size, old_size; if( nim_dest->num_ext > 0 || nim_dest->ext_list != NULL ){ fprintf(stderr,"** will not copy extensions over existing ones\n"); return -1; } if( g_opts.debug > 1 ) fprintf(stderr,"+d duplicating %d extension(s)\n", nim_src->num_ext); if( nim_src->num_ext <= 0 ) return 0; bytes = nim_src->num_ext * sizeof(nifti1_extension); /* I'm lazy */ nim_dest->ext_list = (nifti1_extension *)malloc(bytes); if( !nim_dest->ext_list ){ fprintf(stderr,"** failed to allocate %d nifti1_extension structs\n", nim_src->num_ext); return -1; } /* copy the extension data */ nim_dest->num_ext = 0; for( c = 0; c < nim_src->num_ext; c++ ){ size = old_size = nim_src->ext_list[c].esize; if( size & 0xf ) size = (size + 0xf) & ~0xf; /* make multiple of 16 */ if( g_opts.debug > 2 ) fprintf(stderr,"+d dup'ing ext #%d of size %d (from size %d)\n", c, size, old_size); data = (char *)calloc(size,sizeof(char)); /* calloc, maybe size > old */ if( !data ){ fprintf(stderr,"** failed to alloc %d bytes for extention\n", size); if( c == 0 ) { free(nim_dest->ext_list); nim_dest->ext_list = NULL; } /* otherwise, keep what we have (a.o.t. deleting them all) */ return -1; } /* finally, fill the new structure */ nim_dest->ext_list[c].esize = size; nim_dest->ext_list[c].ecode = nim_src->ext_list[c].ecode; nim_dest->ext_list[c].edata = data; memcpy(data, nim_src->ext_list[c].edata, old_size); nim_dest->num_ext++; } return 0; } /*----------------------------------------------------------------------*/ /*! compute the total size of all extensions \return the total of all esize fields Note that each esize includes 4 bytes for ecode, 4 bytes for esize, and the bytes used for the data. Each esize also needs to be a multiple of 16, so it may be greater than the sum of its 3 parts. *//*--------------------------------------------------------------------*/ int nifti_extension_size(nifti_image *nim) { int c, size = 0; if( !nim || nim->num_ext <= 0 ) return 0; if( g_opts.debug > 2 ) fprintf(stderr,"-d ext sizes:"); for ( c = 0; c < nim->num_ext; c++ ){ size += nim->ext_list[c].esize; if( g_opts.debug > 2 ) fprintf(stderr," %d",nim->ext_list[c].esize); } if( g_opts.debug > 2 ) fprintf(stderr," (total = %d)\n",size); return size; } /*----------------------------------------------------------------------*/ /*! set the nifti_image iname_offset field, based on nifti_type - if writing to 2 files, set offset to 0 - if writing to a single NIFTI-1 file, set the offset to 352 + total extension size, then align to 16-byte boundary - if writing an ASCII header, set offset to -1 *//*--------------------------------------------------------------------*/ void nifti_set_iname_offset(nifti_image *nim) { int offset; switch( nim->nifti_type ){ default: /* writing into 2 files */ /* we only write files with 0 offset in the 2 file format */ nim->iname_offset = 0 ; break ; /* NIFTI-1 single binary file - always update */ case NIFTI_FTYPE_NIFTI1_1: offset = nifti_extension_size(nim)+sizeof(struct nifti_1_header)+4; /* be sure offset is aligned to a 16 byte boundary */ if ( ( offset % 16 ) != 0 ) offset = ((offset + 0xf) & ~0xf); if( nim->iname_offset != offset ){ if( g_opts.debug > 1 ) fprintf(stderr,"+d changing offset from %d to %d\n", nim->iname_offset, offset); nim->iname_offset = offset; } break ; /* non-standard case: NIFTI-1 ASCII header + binary data (single file) */ case NIFTI_FTYPE_ASCII: nim->iname_offset = -1 ; /* compute offset from filesize */ break ; } } /*----------------------------------------------------------------------*/ /*! write the nifti_image dataset to disk, optionally including data This is just a front-end for nifti_image_write_hdr_img2. \param nim nifti_image to write to disk \param write_data write options (see nifti_image_write_hdr_img2) \param opts file open options ("wb" from nifti_image_write) \sa nifti_image_write, nifti_image_write_hdr_img2, nifti_image_free, nifti_set_filenames *//*--------------------------------------------------------------------*/ znzFile nifti_image_write_hdr_img( nifti_image *nim , int write_data , const char* opts ) { return nifti_image_write_hdr_img2(nim,write_data,opts,NULL,NULL); } #undef ERREX #define ERREX(msg) \ do{ fprintf(stderr,"** ERROR: nifti_image_write_hdr_img: %s\n",(msg)) ; \ return fp ; } while(0) /* ----------------------------------------------------------------------*/ /*! This writes the header (and optionally the image data) to file * * If the image data file is left open it returns a valid znzFile handle. * It also uses imgfile as the open image file is not null, and modifies * it inside. * * \param nim nifti_image to write to disk * \param write_opts flags whether to write data and/or close file (see below) * \param opts file-open options, probably "wb" from nifti_image_write() * \param imgfile optional open znzFile struct, for writing image data (may be NULL) * \param NBL optional nifti_brick_list, containing the image data (may be NULL) * * Values for write_opts mode are based on two binary flags * ( 0/1 for no-write/write data, and 0/2 for close/leave-open files ) : * - 0 = do not write data and close (do not open data file) * - 1 = write data and close * - 2 = do not write data and leave data file open * - 3 = write data and leave data file open * * \sa nifti_image_write, nifti_image_write_hdr_img, nifti_image_free, * nifti_set_filenames *//*---------------------------------------------------------------------*/ znzFile nifti_image_write_hdr_img2(nifti_image *nim, int write_opts, const char * opts, znzFile imgfile, const nifti_brick_list * NBL) { struct nifti_1_header nhdr ; znzFile fp=NULL; size_t ss ; int write_data, leave_open; char func[] = { "nifti_image_write_hdr_img2" }; write_data = write_opts & 1; /* just separate the bits now */ leave_open = write_opts & 2; if( ! nim ) ERREX("NULL input") ; if( ! nifti_validfilename(nim->fname) ) ERREX("bad fname input") ; if( write_data && ! nim->data && ! NBL ) ERREX("no image data") ; nifti_set_iname_offset(nim); if( g_opts.debug > 1 ){ fprintf(stderr,"-d writing nifti file '%s'...\n", nim->fname); if( g_opts.debug > 2 ) fprintf(stderr,"-d nifti type %d, offset %d\n", nim->nifti_type, nim->iname_offset); } if( nim->nifti_type == NIFTI_FTYPE_ASCII ) /* non-standard case */ return nifti_write_ascii_image(nim,NBL,opts,write_data,leave_open); nhdr = nifti_convert_nim2nhdr(nim); /* create the nifti1_header struct */ /* if writing to 2 files, make sure iname is set and different from fname */ if( nim->nifti_type != NIFTI_FTYPE_NIFTI1_1 ){ if( nim->iname && strcmp(nim->iname,nim->fname) == 0 ){ free(nim->iname) ; nim->iname = NULL ; } if( nim->iname == NULL ){ /* then make a new one */ nim->iname = nifti_makeimgname(nim->fname,nim->nifti_type,0,0); if( nim->iname == NULL ) return NULL; } } /* if we have an imgfile and will write the header there, use it */ if( ! znz_isnull(imgfile) && nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ){ if( g_opts.debug > 2 ) fprintf(stderr,"+d using passed file for hdr\n"); fp = imgfile; } else { if( g_opts.debug > 2 ) fprintf(stderr,"+d opening output file '%s'\n",nim->fname); fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ; if( znz_isnull(fp) ){ LNI_FERR(func,"cannot open output file",nim->fname); return fp; } } /* write the header and extensions */ ss = znzwrite(&nhdr , 1 , sizeof(nhdr) , fp); /* write header */ if( ss < sizeof(nhdr) ){ LNI_FERR(func,"bad header write to output file",nim->fname); znzclose(fp); return fp; } /* partial file exists, and errors have been printed, so ignore return */ if( nim->nifti_type != NIFTI_FTYPE_ANALYZE ) (void)nifti_write_extensions(fp,nim); /* if the header is all we want, we are done */ if( ! write_data && ! leave_open ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d header is all we want: done\n"); znzclose(fp); return(fp); } if( nim->nifti_type != NIFTI_FTYPE_NIFTI1_1 ){ /* get a new file pointer */ znzclose(fp); /* first, close header file */ if( ! znz_isnull(imgfile) ){ if(g_opts.debug > 2) fprintf(stderr,"+d using passed file for img\n"); fp = imgfile; } else { if( g_opts.debug > 2 ) fprintf(stderr,"+d opening img file '%s'\n", nim->iname); fp = znzopen( nim->iname , opts , nifti_is_gzfile(nim->iname) ) ; if( znz_isnull(fp) ) ERREX("cannot open image file") ; } } znzseek(fp, nim->iname_offset, SEEK_SET); /* in any case, seek to offset */ if( write_data ) nifti_write_all_data(fp,nim,NBL); if( ! leave_open ) znzclose(fp); return fp; } /*----------------------------------------------------------------------*/ /*! write a nifti_image to disk in ASCII format *//*--------------------------------------------------------------------*/ znzFile nifti_write_ascii_image(nifti_image *nim, const nifti_brick_list * NBL, const char *opts, int write_data, int leave_open) { znzFile fp; char * hstr; hstr = nifti_image_to_ascii( nim ) ; /* get header in ASCII form */ if( ! hstr ){ fprintf(stderr,"** failed image_to_ascii()\n"); return NULL; } fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ; if( znz_isnull(fp) ){ free(hstr); fprintf(stderr,"** failed to open '%s' for ascii write\n",nim->fname); return fp; } znzputs(hstr,fp); /* header */ nifti_write_extensions(fp,nim); /* extensions */ if ( write_data ) { nifti_write_all_data(fp,nim,NBL); } /* data */ if ( ! leave_open ) { znzclose(fp); } free(hstr); return fp; /* returned but may be closed */ } /*--------------------------------------------------------------------------*/ /*! Write a nifti_image to disk. Since data is properly byte-swapped upon reading, it is assumed to be in the byte-order of the current CPU at write time. Thus, nim->byte_order should match that of the current CPU. Note that the nifti_set_filenames() function takes the flag, set_byte_order. The following fields of nim affect how the output appears: - nifti_type = 0 ==> ANALYZE-7.5 format file pair will be written - nifti_type = 1 ==> NIFTI-1 format single file will be written (data offset will be 352+extensions) - nifti_type = 2 ==> NIFTI_1 format file pair will be written - nifti_type = 3 ==> NIFTI_1 ASCII single file will be written - fname is the name of the output file (header or header+data) - if a file pair is being written, iname is the name of the data file - existing files WILL be overwritten with extreme prejudice - if qform_code > 0, the quatern_*, qoffset_*, and qfac fields determine the qform output, NOT the qto_xyz matrix; if you want to compute these fields from the qto_xyz matrix, you can use the utility function nifti_mat44_to_quatern() \sa nifti_image_write_bricks, nifti_image_free, nifti_set_filenames, nifti_image_write_hdr_img *//*------------------------------------------------------------------------*/ void nifti_image_write( nifti_image *nim ) { znzFile fp = nifti_image_write_hdr_img(nim,1,"wb"); if( fp ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d niw: done with znzFile\n"); free(fp); } if( g_opts.debug > 1 ) fprintf(stderr,"-d nifti_image_write: done\n"); } /*----------------------------------------------------------------------*/ /*! similar to nifti_image_write, but data is in NBL struct, not nim->data \sa nifti_image_write, nifti_image_free, nifti_set_filenames, nifti_free_NBL *//*--------------------------------------------------------------------*/ void nifti_image_write_bricks( nifti_image *nim, const nifti_brick_list * NBL ) { znzFile fp = nifti_image_write_hdr_img2(nim,1,"wb",NULL,NBL); if( fp ){ if( g_opts.debug > 2 ) fprintf(stderr,"-d niwb: done with znzFile\n"); free(fp); } if( g_opts.debug > 1 ) fprintf(stderr,"-d niwb: done writing bricks\n"); } /*----------------------------------------------------------------------*/ /*! copy the nifti_image structure, without data Duplicate the structure, including fname, iname and extensions. Leave the data pointer as NULL. *//*--------------------------------------------------------------------*/ nifti_image * nifti_copy_nim_info(const nifti_image * src) { nifti_image *dest; dest = (nifti_image *)calloc(1,sizeof(nifti_image)); if( !dest ){ fprintf(stderr,"** NCNI: failed to alloc nifti_image\n"); return NULL; } memcpy(dest, src, sizeof(nifti_image)); if( src->fname ) dest->fname = nifti_strdup(src->fname); if( src->iname ) dest->iname = nifti_strdup(src->iname); dest->num_ext = 0; dest->ext_list = NULL; /* errors will be printed in NCE(), continue in either case */ (void)nifti_copy_extensions(dest, src); dest->data = NULL; return dest; } /*------------------------------------------------------------------------*/ /* Un-escape a C string in place -- that is, convert XML escape sequences back into their characters. (This can be done in place since the replacement is always smaller than the input.) Escapes recognized are: - < -> < - > -> > - " -> " - ' -> ' - & -> & Also replace CR LF pair (Microsoft), or CR alone (Macintosh) with LF (Unix), per the XML standard. Return value is number of replacements made (if you care). --------------------------------------------------------------------------*/ #undef CR #undef LF #define CR 0x0D #define LF 0x0A static int unescape_string( char *str ) { int ii,jj , nn,ll ; if( str == NULL ) return 0 ; /* no string? */ ll = strlen(str) ; if( ll == 0 ) return 0 ; /* scan for escapes: &something; */ for( ii=jj=nn=0 ; ii': lout += 4 ; break ; /* replace '<' with "<" */ case '"' : case '\'': lout += 6 ; break ; /* replace '"' with """ */ case CR: case LF: lout += 6 ; break ; /* replace CR with " " LF with " " */ default: lout++ ; break ; /* copy all other chars */ } } out = (char *)calloc(1,lout) ; /* allocate output string */ if( !out ){ fprintf(stderr,"** escapize_string: failed to alloc %d bytes\n",lout); return NULL; } out[0] = '\'' ; /* opening quote mark */ for( ii=0,jj=1 ; ii < lstr ; ii++ ){ switch( str[ii] ){ default: out[jj++] = str[ii] ; break ; /* normal characters */ case '&': memcpy(out+jj,"&",5) ; jj+=5 ; break ; case '<': memcpy(out+jj,"<",4) ; jj+=4 ; break ; case '>': memcpy(out+jj,">",4) ; jj+=4 ; break ; case '"' : memcpy(out+jj,""",6) ; jj+=6 ; break ; case '\'': memcpy(out+jj,"'",6) ; jj+=6 ; break ; case CR: memcpy(out+jj," ",6) ; jj+=6 ; break ; case LF: memcpy(out+jj," ",6) ; jj+=6 ; break ; } } out[jj++] = '\'' ; /* closing quote mark */ out[jj] = '\0' ; /* terminate the string */ return out ; } /*---------------------------------------------------------------------------*/ /*! Dump the information in a NIFTI image header to an XML-ish ASCII string that can later be converted back into a NIFTI header in nifti_image_from_ascii(). The resulting string can be free()-ed when you are done with it. *//*-------------------------------------------------------------------------*/ char *nifti_image_to_ascii( const nifti_image *nim ) { char *buf , *ebuf ; int nbuf ; if( nim == NULL ) return NULL ; /* stupid caller */ buf = (char *)calloc(1,65534); nbuf = 0; /* longer than needed, to be safe */ if( !buf ){ fprintf(stderr,"** NITA: failed to alloc %d bytes\n",65534); return NULL; } sprintf( buf , "nifti_type == NIFTI_FTYPE_NIFTI1_1) ? "NIFTI-1+" :(nim->nifti_type == NIFTI_FTYPE_NIFTI1_2) ? "NIFTI-1" :(nim->nifti_type == NIFTI_FTYPE_ASCII ) ? "NIFTI-1A" : "ANALYZE-7.5" ) ; /** Strings that we don't control (filenames, etc.) that might contain "weird" characters (like quotes) are "escaped": - A few special characters are replaced by XML-style escapes, using the function escapize_string(). - On input, function unescape_string() reverses this process. - The result is that the NIFTI ASCII-format header is XML-compliant. */ ebuf = escapize_string(nim->fname) ; sprintf( buf+strlen(buf) , " header_filename = %s\n",ebuf); free(ebuf); ebuf = escapize_string(nim->iname) ; sprintf( buf+strlen(buf) , " image_filename = %s\n", ebuf); free(ebuf); sprintf( buf+strlen(buf) , " image_offset = '%d'\n" , nim->iname_offset ); sprintf( buf+strlen(buf), " ndim = '%d'\n", nim->ndim); sprintf( buf+strlen(buf), " nx = '%d'\n", nim->nx ); if( nim->ndim > 1 ) sprintf( buf+strlen(buf), " ny = '%d'\n", nim->ny ); if( nim->ndim > 2 ) sprintf( buf+strlen(buf), " nz = '%d'\n", nim->nz ); if( nim->ndim > 3 ) sprintf( buf+strlen(buf), " nt = '%d'\n", nim->nt ); if( nim->ndim > 4 ) sprintf( buf+strlen(buf), " nu = '%d'\n", nim->nu ); if( nim->ndim > 5 ) sprintf( buf+strlen(buf), " nv = '%d'\n", nim->nv ); if( nim->ndim > 6 ) sprintf( buf+strlen(buf), " nw = '%d'\n", nim->nw ); sprintf( buf+strlen(buf), " dx = '%g'\n", nim->dx ); if( nim->ndim > 1 ) sprintf( buf+strlen(buf), " dy = '%g'\n", nim->dy ); if( nim->ndim > 2 ) sprintf( buf+strlen(buf), " dz = '%g'\n", nim->dz ); if( nim->ndim > 3 ) sprintf( buf+strlen(buf), " dt = '%g'\n", nim->dt ); if( nim->ndim > 4 ) sprintf( buf+strlen(buf), " du = '%g'\n", nim->du ); if( nim->ndim > 5 ) sprintf( buf+strlen(buf), " dv = '%g'\n", nim->dv ); if( nim->ndim > 6 ) sprintf( buf+strlen(buf), " dw = '%g'\n", nim->dw ); sprintf( buf+strlen(buf) , " datatype = '%d'\n" , nim->datatype ) ; sprintf( buf+strlen(buf) , " datatype_name = '%s'\n" , nifti_datatype_string(nim->datatype) ) ; sprintf( buf+strlen(buf) , " nvox = '%d'\n" , nim->nvox ) ; sprintf( buf+strlen(buf) , " nbyper = '%d'\n" , nim->nbyper ) ; sprintf( buf+strlen(buf) , " byteorder = '%s'\n" , (nim->byteorder==MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" ) ; if( nim->cal_min < nim->cal_max ){ sprintf( buf+strlen(buf) , " cal_min = '%g'\n", nim->cal_min ) ; sprintf( buf+strlen(buf) , " cal_max = '%g'\n", nim->cal_max ) ; } if( nim->scl_slope != 0.0 ){ sprintf( buf+strlen(buf) , " scl_slope = '%g'\n" , nim->scl_slope ) ; sprintf( buf+strlen(buf) , " scl_inter = '%g'\n" , nim->scl_inter ) ; } if( nim->intent_code > 0 ){ sprintf( buf+strlen(buf) , " intent_code = '%d'\n", nim->intent_code ) ; sprintf( buf+strlen(buf) , " intent_code_name = '%s'\n" , nifti_intent_string(nim->intent_code) ) ; sprintf( buf+strlen(buf) , " intent_p1 = '%g'\n" , nim->intent_p1 ) ; sprintf( buf+strlen(buf) , " intent_p2 = '%g'\n" , nim->intent_p2 ) ; sprintf( buf+strlen(buf) , " intent_p3 = '%g'\n" , nim->intent_p3 ) ; if( nim->intent_name[0] != '\0' ){ ebuf = escapize_string(nim->intent_name) ; sprintf( buf+strlen(buf) , " intent_name = %s\n",ebuf) ; free(ebuf) ; } } if( nim->toffset != 0.0 ) sprintf( buf+strlen(buf) , " toffset = '%g'\n",nim->toffset ) ; if( nim->xyz_units > 0 ) sprintf( buf+strlen(buf) , " xyz_units = '%d'\n" " xyz_units_name = '%s'\n" , nim->xyz_units , nifti_units_string(nim->xyz_units) ) ; if( nim->time_units > 0 ) sprintf( buf+strlen(buf) , " time_units = '%d'\n" " time_units_name = '%s'\n" , nim->time_units , nifti_units_string(nim->time_units) ) ; if( nim->freq_dim > 0 ) sprintf( buf+strlen(buf) , " freq_dim = '%d'\n",nim->freq_dim ) ; if( nim->phase_dim > 0 ) sprintf( buf+strlen(buf) , " phase_dim = '%d'\n",nim->phase_dim ) ; if( nim->slice_dim > 0 ) sprintf( buf+strlen(buf) , " slice_dim = '%d'\n",nim->slice_dim ) ; if( nim->slice_code > 0 ) sprintf( buf+strlen(buf) , " slice_code = '%d'\n" " slice_code_name = '%s'\n" , nim->slice_code , nifti_slice_string(nim->slice_code) ) ; if( nim->slice_start >= 0 && nim->slice_end > nim->slice_start ) sprintf( buf+strlen(buf) , " slice_start = '%d'\n" " slice_end = '%d'\n" , nim->slice_start , nim->slice_end ) ; if( nim->slice_duration != 0.0 ) sprintf( buf+strlen(buf) , " slice_duration = '%g'\n", nim->slice_duration ) ; if( nim->descrip[0] != '\0' ){ ebuf = escapize_string(nim->descrip) ; sprintf( buf+strlen(buf) , " descrip = %s\n",ebuf) ; free(ebuf) ; } if( nim->aux_file[0] != '\0' ){ ebuf = escapize_string(nim->aux_file) ; sprintf( buf+strlen(buf) , " aux_file = %s\n",ebuf) ; free(ebuf) ; } if( nim->qform_code > 0 ){ int i,j,k ; sprintf( buf+strlen(buf) , " qform_code = '%d'\n" " qform_code_name = '%s'\n" " qto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , nim->qform_code , nifti_xform_string(nim->qform_code) , nim->qto_xyz.m[0][0] , nim->qto_xyz.m[0][1] , nim->qto_xyz.m[0][2] , nim->qto_xyz.m[0][3] , nim->qto_xyz.m[1][0] , nim->qto_xyz.m[1][1] , nim->qto_xyz.m[1][2] , nim->qto_xyz.m[1][3] , nim->qto_xyz.m[2][0] , nim->qto_xyz.m[2][1] , nim->qto_xyz.m[2][2] , nim->qto_xyz.m[2][3] , nim->qto_xyz.m[3][0] , nim->qto_xyz.m[3][1] , nim->qto_xyz.m[3][2] , nim->qto_xyz.m[3][3] ) ; sprintf( buf+strlen(buf) , " qto_ijk_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , nim->qto_ijk.m[0][0] , nim->qto_ijk.m[0][1] , nim->qto_ijk.m[0][2] , nim->qto_ijk.m[0][3] , nim->qto_ijk.m[1][0] , nim->qto_ijk.m[1][1] , nim->qto_ijk.m[1][2] , nim->qto_ijk.m[1][3] , nim->qto_ijk.m[2][0] , nim->qto_ijk.m[2][1] , nim->qto_ijk.m[2][2] , nim->qto_ijk.m[2][3] , nim->qto_ijk.m[3][0] , nim->qto_ijk.m[3][1] , nim->qto_ijk.m[3][2] , nim->qto_ijk.m[3][3] ) ; sprintf( buf+strlen(buf) , " quatern_b = '%g'\n" " quatern_c = '%g'\n" " quatern_d = '%g'\n" " qoffset_x = '%g'\n" " qoffset_y = '%g'\n" " qoffset_z = '%g'\n" " qfac = '%g'\n" , nim->quatern_b , nim->quatern_c , nim->quatern_d , nim->qoffset_x , nim->qoffset_y , nim->qoffset_z , nim->qfac ) ; nifti_mat44_to_orientation( nim->qto_xyz , &i,&j,&k ) ; if( i > 0 && j > 0 && k > 0 ) sprintf( buf+strlen(buf) , " qform_i_orientation = '%s'\n" " qform_j_orientation = '%s'\n" " qform_k_orientation = '%s'\n" , nifti_orientation_string(i) , nifti_orientation_string(j) , nifti_orientation_string(k) ) ; } if( nim->sform_code > 0 ){ int i,j,k ; sprintf( buf+strlen(buf) , " sform_code = '%d'\n" " sform_code_name = '%s'\n" " sto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , nim->sform_code , nifti_xform_string(nim->sform_code) , nim->sto_xyz.m[0][0] , nim->sto_xyz.m[0][1] , nim->sto_xyz.m[0][2] , nim->sto_xyz.m[0][3] , nim->sto_xyz.m[1][0] , nim->sto_xyz.m[1][1] , nim->sto_xyz.m[1][2] , nim->sto_xyz.m[1][3] , nim->sto_xyz.m[2][0] , nim->sto_xyz.m[2][1] , nim->sto_xyz.m[2][2] , nim->sto_xyz.m[2][3] , nim->sto_xyz.m[3][0] , nim->sto_xyz.m[3][1] , nim->sto_xyz.m[3][2] , nim->sto_xyz.m[3][3] ) ; sprintf( buf+strlen(buf) , " sto_ijk matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , nim->sto_ijk.m[0][0] , nim->sto_ijk.m[0][1] , nim->sto_ijk.m[0][2] , nim->sto_ijk.m[0][3] , nim->sto_ijk.m[1][0] , nim->sto_ijk.m[1][1] , nim->sto_ijk.m[1][2] , nim->sto_ijk.m[1][3] , nim->sto_ijk.m[2][0] , nim->sto_ijk.m[2][1] , nim->sto_ijk.m[2][2] , nim->sto_ijk.m[2][3] , nim->sto_ijk.m[3][0] , nim->sto_ijk.m[3][1] , nim->sto_ijk.m[3][2] , nim->sto_ijk.m[3][3] ) ; nifti_mat44_to_orientation( nim->sto_xyz , &i,&j,&k ) ; if( i > 0 && j > 0 && k > 0 ) sprintf( buf+strlen(buf) , " sform_i_orientation = '%s'\n" " sform_j_orientation = '%s'\n" " sform_k_orientation = '%s'\n" , nifti_orientation_string(i) , nifti_orientation_string(j) , nifti_orientation_string(k) ) ; } sprintf( buf+strlen(buf) , " num_ext = '%d'\n", nim->num_ext ) ; sprintf( buf+strlen(buf) , "/>\n" ) ; /* XML-ish closer */ nbuf = strlen(buf) ; buf = (char *)realloc((void *)buf, nbuf+1); /* cut back to proper length */ if( !buf ) fprintf(stderr,"** NITA: failed to realloc %d bytes\n",nbuf+1); return buf ; } /*---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /*! get the byte order for this CPU - LSB_FIRST means least significant byte, first (little endian) - MSB_FIRST means most significant byte, first (big endian) *//*--------------------------------------------------------------------*/ int nifti_short_order(void) /* determine this CPU's byte order */ { union { unsigned char bb[2] ; short ss ; } fred ; fred.bb[0] = 1 ; fred.bb[1] = 0 ; return (fred.ss == 1) ? LSB_FIRST : MSB_FIRST ; } /*---------------------------------------------------------------------------*/ #undef QQNUM #undef QNUM #undef QSTR /* macro to check lhs string against "n1"; if it matches, interpret rhs string as a number, and put it into nim->"n2" */ #define QQNUM(n1,n2) if( strcmp(lhs,#n1)==0 ) nim->n2=strtod(rhs,NULL) /* same, but where "n1" == "n2" */ #define QNUM(nam) QQNUM(nam,nam) /* macro to check lhs string against "nam"; if it matches, put rhs string into nim->"nam" string, with max length = "ml" */ #define QSTR(nam,ml) if( strcmp(lhs,#nam) == 0 ) \ strncpy(nim->nam,rhs,ml), nim->nam[ml]='\0' /*---------------------------------------------------------------------------*/ /*! Take an XML-ish ASCII string and create a NIFTI image header to match. NULL is returned if enough information isn't present in the input string. - The image data can later be loaded with nifti_image_load(). - The struct returned here can be liberated with nifti_image_free(). - Not a lot of error checking is done here to make sure that the input values are reasonable! *//*-------------------------------------------------------------------------*/ nifti_image *nifti_image_from_ascii( const char *str, int * bytes_read ) { char lhs[1024] , rhs[1024] ; int ii , spos, nn , slen ; nifti_image *nim ; /* will be output */ if( str == NULL || *str == '\0' ) return NULL ; /* bad input!? */ /* scan for opening string */ spos = 0 ; slen = strlen(str) ; ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ; if( ii == 0 || strcmp(lhs,"nx = nim->ny = nim->nz = nim->nt = nim->nu = nim->nv = nim->nw = 1 ; nim->dx = nim->dy = nim->dz = nim->dt = nim->du = nim->dv = nim->dw = nim->qfac = 1.0 ; nim->byteorder = nifti_short_order() ; /* starting at str[spos], scan for "equations" of the form lhs = 'rhs' and assign rhs values into the struct component named by lhs */ while(1){ while( isspace(str[spos]) ) spos++ ; /* skip whitespace */ if( str[spos] == '\0' ) break ; /* end of string? */ /* get lhs string */ ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ; if( ii == 0 || strcmp(lhs,"/>") == 0 ) break ; /* end of input? */ /* skip whitespace and the '=' marker */ while( isspace(str[spos]) || str[spos] == '=' ) spos++ ; if( str[spos] == '\0' ) break ; /* end of string? */ /* if next character is a quote ', copy everything up to next ' otherwise, copy everything up to next nonblank */ if( str[spos] == '\'' ){ ii = spos+1 ; while( str[ii] != '\0' && str[ii] != '\'' ) ii++ ; nn = ii-spos-1 ; if( nn > 1023 ) nn = 1023 ; memcpy(rhs,str+spos+1,nn) ; rhs[nn] = '\0' ; spos = (str[ii] == '\'') ? ii+1 : ii ; } else { ii = sscanf( str+spos , "%1023s%n" , rhs , &nn ) ; spos += nn ; if( ii == 0 ) break ; /* nothing found? */ } unescape_string(rhs) ; /* remove any XML escape sequences */ /* Now can do the assignment, based on lhs string. Start with special cases that don't fit the QNUM/QSTR macros. */ if( strcmp(lhs,"nifti_type") == 0 ){ if( strcmp(rhs,"ANALYZE-7.5") == 0 ) nim->nifti_type = NIFTI_FTYPE_ANALYZE ; else if( strcmp(rhs,"NIFTI-1+") == 0 ) nim->nifti_type = NIFTI_FTYPE_NIFTI1_1 ; else if( strcmp(rhs,"NIFTI-1") == 0 ) nim->nifti_type = NIFTI_FTYPE_NIFTI1_2 ; else if( strcmp(rhs,"NIFTI-1A") == 0 ) nim->nifti_type = NIFTI_FTYPE_ASCII ; } else if( strcmp(lhs,"header_filename") == 0 ){ nim->fname = nifti_strdup(rhs) ; } else if( strcmp(lhs,"image_filename") == 0 ){ nim->iname = nifti_strdup(rhs) ; } else if( strcmp(lhs,"sto_xyz_matrix") == 0 ){ sscanf( rhs , "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f" , &(nim->sto_xyz.m[0][0]) , &(nim->sto_xyz.m[0][1]) , &(nim->sto_xyz.m[0][2]) , &(nim->sto_xyz.m[0][3]) , &(nim->sto_xyz.m[1][0]) , &(nim->sto_xyz.m[1][1]) , &(nim->sto_xyz.m[1][2]) , &(nim->sto_xyz.m[1][3]) , &(nim->sto_xyz.m[2][0]) , &(nim->sto_xyz.m[2][1]) , &(nim->sto_xyz.m[2][2]) , &(nim->sto_xyz.m[2][3]) , &(nim->sto_xyz.m[3][0]) , &(nim->sto_xyz.m[3][1]) , &(nim->sto_xyz.m[3][2]) , &(nim->sto_xyz.m[3][3]) ) ; } else if( strcmp(lhs,"byteorder") == 0 ){ if( strcmp(rhs,"MSB_FIRST") == 0 ) nim->byteorder = MSB_FIRST ; if( strcmp(rhs,"LSB_FIRST") == 0 ) nim->byteorder = LSB_FIRST ; } else QQNUM(image_offset,iname_offset) ; else QNUM(datatype) ; else QNUM(ndim) ; else QNUM(nx) ; else QNUM(ny) ; else QNUM(nz) ; else QNUM(nt) ; else QNUM(nu) ; else QNUM(nv) ; else QNUM(nw) ; else QNUM(dx) ; else QNUM(dy) ; else QNUM(dz) ; else QNUM(dt) ; else QNUM(du) ; else QNUM(dv) ; else QNUM(dw) ; else QNUM(cal_min) ; else QNUM(cal_max) ; else QNUM(scl_slope) ; else QNUM(scl_inter) ; else QNUM(intent_code) ; else QNUM(intent_p1) ; else QNUM(intent_p2) ; else QNUM(intent_p3) ; else QSTR(intent_name,15) ; else QNUM(toffset) ; else QNUM(xyz_units) ; else QNUM(time_units) ; else QSTR(descrip,79) ; else QSTR(aux_file,23) ; else QNUM(qform_code) ; else QNUM(quatern_b) ; else QNUM(quatern_c) ; else QNUM(quatern_d) ; else QNUM(qoffset_x) ; else QNUM(qoffset_y) ; else QNUM(qoffset_z) ; else QNUM(qfac) ; else QNUM(sform_code) ; else QNUM(freq_dim) ; else QNUM(phase_dim) ; else QNUM(slice_dim) ; else QNUM(slice_code) ; else QNUM(slice_start) ; else QNUM(slice_end) ; else QNUM(slice_duration) ; else QNUM(num_ext) ; } /* end of while loop */ if( bytes_read ) *bytes_read = spos+1; /* "process" last '\n' */ /* do miscellaneous checking and cleanup */ if( nim->ndim <= 0 ){ nifti_image_free(nim); return NULL; } /* bad! */ nifti_datatype_sizes( nim->datatype, &(nim->nbyper), &(nim->swapsize) ); if( nim->nbyper == 0 ){ nifti_image_free(nim); return NULL; } /* bad! */ nim->dim[0] = nim->ndim ; nim->dim[1] = nim->nx ; nim->pixdim[1] = nim->dx ; nim->dim[2] = nim->ny ; nim->pixdim[2] = nim->dy ; nim->dim[3] = nim->nz ; nim->pixdim[3] = nim->dz ; nim->dim[4] = nim->nt ; nim->pixdim[4] = nim->dt ; nim->dim[5] = nim->nu ; nim->pixdim[5] = nim->du ; nim->dim[6] = nim->nv ; nim->pixdim[6] = nim->dv ; nim->dim[7] = nim->nw ; nim->pixdim[7] = nim->dw ; nim->nvox = nim->nx * nim->ny * nim->nz * nim->nt * nim->nu * nim->nv * nim->nw ; if( nim->qform_code > 0 ) nim->qto_xyz = nifti_quatern_to_mat44( nim->quatern_b, nim->quatern_c, nim->quatern_d, nim->qoffset_x, nim->qoffset_y, nim->qoffset_z, nim->dx , nim->dy , nim->dz , nim->qfac ) ; else nim->qto_xyz = nifti_quatern_to_mat44( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , nim->dx , nim->dy , nim->dz , 0.0 ) ; nim->qto_ijk = nifti_mat44_inverse( nim->qto_xyz ) ; if( nim->sform_code > 0 ) nim->sto_ijk = nifti_mat44_inverse( nim->sto_xyz ) ; return nim ; } /*---------------------------------------------------------------------------*/ /*! validate the nifti_image \return 1 if the structure seems valid, otherwise 0 \sa nifti_nim_has_valid_dims, nifti_hdr_looks_good *//*-------------------------------------------------------------------------*/ int nifti_nim_is_valid(nifti_image * nim, int complain) { int errs = 0; if( !nim ){ fprintf(stderr,"** is_valid_nim: nim is NULL\n"); return 0; } if( g_opts.debug > 2 ) fprintf(stderr,"-d nim_is_valid check...\n"); /**- check that dim[] matches the individual values ndim, nx, ny, ... */ if( ! nifti_nim_has_valid_dims(nim,complain) ){ if( !complain ) return 0; errs++; } /* might check nbyper, pixdim, q/sforms, swapsize, nifti_type, ... */ /**- be explicit in return of 0 or 1 */ if( errs > 0 ) return 0; else return 1; } /*---------------------------------------------------------------------------*/ /*! validate nifti dimensions \return 1 if valid, 0 if not \sa nifti_nim_is_valid, nifti_hdr_looks_good rely on dim[] as the master *//*-------------------------------------------------------------------------*/ int nifti_nim_has_valid_dims(nifti_image * nim, int complain) { int c, prod, errs = 0; /**- start with dim[0]: failure here is considered terminal */ if( nim->dim[0] <= 0 || nim->dim[0] > 7 ){ errs++; if( complain ) fprintf(stderr,"** NVd: dim[0] (%d) out of range [1,7]\n",nim->dim[0]); return 0; } /**- check whether ndim equals dim[0] */ if( nim->ndim != nim->dim[0] ){ errs++; if( ! complain ) return 0; fprintf(stderr,"** NVd: ndim != dim[0] (%d,%d)\n",nim->ndim,nim->dim[0]); } /**- compare each dim[i] to the proper nx, ny, ... */ if( ( (nim->dim[0] >= 1) && (nim->dim[1] != nim->nx) ) || ( (nim->dim[0] >= 2) && (nim->dim[2] != nim->ny) ) || ( (nim->dim[0] >= 3) && (nim->dim[3] != nim->nz) ) || ( (nim->dim[0] >= 4) && (nim->dim[4] != nim->nt) ) || ( (nim->dim[0] >= 5) && (nim->dim[5] != nim->nu) ) || ( (nim->dim[0] >= 6) && (nim->dim[6] != nim->nv) ) || ( (nim->dim[0] >= 7) && (nim->dim[7] != nim->nw) ) ){ errs++; if( !complain ) return 0; fprintf(stderr,"** NVd mismatch: dims = %d,%d,%d,%d,%d,%d,%d\n" " nxyz... = %d,%d,%d,%d,%d,%d,%d\n", nim->dim[1], nim->dim[2], nim->dim[3], nim->dim[4], nim->dim[5], nim->dim[6], nim->dim[7], nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw ); } /**- check the dimensions, and that their product matches nvox */ prod = 1; for( c = 1; c <= nim->dim[0]; c++ ){ if( nim->dim[c] > 0) prod *= nim->dim[c]; else if( nim->dim[c] <= 0 ){ if( !complain ) return 0; fprintf(stderr,"** NVd: dim[%d] (=%d) <= 0\n",c, nim->dim[c]); errs++; } } if( prod != nim->nvox ){ if( ! complain ) return 0; fprintf(stderr,"** NVd: nvox does not match dimension product (%d, %d)\n", nim->nvox, prod); errs++; } /**- if debug, warn about any remaining dim that is neither 0, nor 1 */ /* (values in dims above dim[0] are undefined, as reminded by Cinly Ooi and Alle Meije Wink) 16 Nov 2005 [rickr] */ if( g_opts.debug > 1 ) for( c = nim->dim[0]+1; c <= 7; c++ ) if( nim->dim[c] != 0 && nim->dim[c] != 1 ) fprintf(stderr,"** NVd warning: dim[%d] = %d, but ndim = %d\n", c, nim->dim[c], nim->dim[0]); if( g_opts.debug > 2 ) fprintf(stderr,"-d nim_has_valid_dims check, errs = %d\n", errs); /**- return invalid or valid */ if( errs > 0 ) return 0; else return 1; } /*---------------------------------------------------------------------------*/ /*! read a nifti image, collapsed across dimensions according to dims[8]

    This function may be used to read parts of a nifti dataset, such as
    the time series for a single voxel, or perhaps a slice.  It is similar
    to nifti_image_load(), though the passed 'data' parameter is used for
    returning the image, not nim->data.

    \param nim  given nifti_image struct, corresponding to the data file
    \param dims given list of dimensions (see below)
    \param data pointer to data pointer (if *data is NULL, data will be
                allocated, otherwise not)

    Here, dims is an array of 8 ints, similar to nim->dim[8].  While dims[0]
    is unused at this point, the other indices specify which dimensions to
    collapse (and at which index), and which not to collapse.  If dims[i] is
    set to -1, then that entire dimension will be read in, from index 0 to
    index (nim->dim[i] - 1).  If dims[i] >= 0, then only that index will be
    read in (so dims[i] must also be < nim->dim[i]).

    Example: given  nim->dim[8] = { 4, 64, 64, 21, 80, 1, 1, 1 } (4-D dataset)

      if dims[8] = { 0,  5,  4, 17, -1, -1, -1, -1 }
         -> read time series for voxel i,j,k = 5,4,17

      if dims[8] = { 0, -1, -1, -1, 17, -1, -1, -1 }
         -> read single volume at time point 17

    Example: given  nim->dim[8] = { 6, 64, 64, 21, 80, 4, 3, 1 } (6-D dataset)

      if dims[8] = { 0, 5, 4, 17, -1, 2, 1, 0 }
         -> read time series for the voxel i,j,k = 5,4,17, and dim 5,6 = 2,1

      if dims[8] = { 0, 5, 4, -1, -1, 0, 0, 0 }
         -> read time series for slice at i,j = 5,4, and dim 5,6,7 = 0,0,0
            (note that dims[7] is not relevant, but must be 0 or -1)

    If *data is NULL, then *data will be set as a pointer to new memory,
    allocated here for the resulting collapsed image data.

      e.g. { int    dims[8] = { 0,  5,  4, 17, -1, -1, -1, -1 };
             void * data    = NULL;
             ret_val = nifti_read_collapsed_image(nim, dims, &data);
             if( ret_val > 0 ){
                process_time_series(data);
                if( data != NULL ) free(data);
             }
           }

    NOTE: If *data is not NULL, then it will be assumed that it points to
          valid memory, sufficient to hold the results.  This is done for
          speed and possibly repeated calls to this function.

      e.g. { int    dims[8] = { 0,  -1, -1, -1, -1, -1, -1, -1 };
             void * data    = NULL;
             for( zslice = 0; zslice < nzslices; zslice++ ){
                dims[3] = zslice;
                ret_val = nifti_read_collapsed_image(nim, dims, &data);
                if( ret_val > 0 ) process_slice(zslice, data);
             }
             if( data != NULL ) free(data);
           }

    \return
        -  the total number of bytes read, or < 0 on failure
        -  the read and byte-swapped data, in 'data'            
\sa nifti_image_read, nifti_image_free, nifti_image_read_bricks nifti_image_load *//*-------------------------------------------------------------------------*/ int nifti_read_collapsed_image( nifti_image * nim, const int dims [8], void ** data ) { znzFile fp; int pivots[8], prods[8], nprods; /* sizes are bounded by dims[], so 8 */ int c, bytes; /** - check pointers for sanity */ if( !nim || !dims || !data ){ fprintf(stderr,"** nifti_RCI: bad params %p, %p, %p\n", (void *)nim, (void *)dims, (void *)data); return -1; } if( g_opts.debug > 2 ){ fprintf(stderr,"-d read_collapsed_image:\n dims ="); for(c = 0; c < 8; c++) fprintf(stderr," %3d", dims[c]); fprintf(stderr,"\n nim->dims ="); for(c = 0; c < 8; c++) fprintf(stderr," %3d", nim->dim[c]); fputc('\n', stderr); } /** - verify that dim[] makes sense */ if( ! nifti_nim_is_valid(nim, g_opts.debug > 0) ){ fprintf(stderr,"** invalid nim (file is '%s')\n", nim->fname ); return -1; } /** - verify that dims[] makes sense for this dataset */ for( c = 1; c <= nim->dim[0]; c++ ){ if( dims[c] >= nim->dim[c] ){ fprintf(stderr,"** nifti_RCI: dims[%d] >= nim->dim[%d] (%d,%d)\n", c, c, dims[c], nim->dim[c]); return -1; } } /** - prepare pivot list - pivots are fixed indices */ if( make_pivot_list(nim, dims, pivots, prods, &nprods) < 0 ) return -1; bytes = rci_alloc_mem(data, prods, nprods, nim->nbyper); if( bytes < 0 ) return -1; /** - open the image file for reading at the appropriate offset */ fp = nifti_image_load_prep( nim ); if( ! fp ){ free(*data); *data = NULL; return -1; } /* failure */ /** - call the recursive reading function, passing nim, the pivot info, location to store memory, and file pointer and position */ c = rci_read_data(nim, pivots,prods,nprods,dims, (char *)*data, fp, znztell(fp)); znzclose(fp); /* in any case, close the file */ if( c < 0 ){ free(*data); *data = NULL; return -1; } /* failure */ if( g_opts.debug > 1 ) fprintf(stderr,"+d read %d bytes of collapsed image from %s\n", bytes, nim->fname); return bytes; } /* read the data from the file pointed to by fp - this a recursive function, so start with the base case - data is now (char *) for easy incrementing return 0 on success, < 0 on failure */ static int rci_read_data(nifti_image * nim, int * pivots, int * prods, int nprods, const int dims[], char * data, znzFile fp, int base_offset) { int c, sublen, offset, read_size; /* bad check first - base_offset may not have been checked */ if( base_offset < 0 || nprods <= 0 ){ fprintf(stderr,"** rci_read_data, bad params, %d,%d\n", nprods, base_offset); return -1; } /* base case: actually read the data */ if( nprods == 1 ){ int nread, bytes; /* make sure things look good here */ if( *pivots != 0 ){ fprintf(stderr,"** rciRD: final pivot == %d!\n", *pivots); return -1; } /* so just seek and read (prods[0] * nbyper) bytes from the file */ znzseek(fp, base_offset, SEEK_SET); bytes = prods[0] * nim->nbyper; nread = nifti_read_buffer(fp, data, bytes, nim); if( nread != bytes ){ fprintf(stderr,"** rciRD: read only %d of %d bytes from '%s'\n", nread, bytes, nim->fname); return -1; } else if( g_opts.debug > 3 ) fprintf(stderr,"+d successful read of %d bytes at offset %d\n", bytes, base_offset); return 0; /* done with base case - return success */ } /* not the base case, so do a set of reduced reads */ /* compute size of sub-brick: all dimensions below pivot */ for( c = 1, sublen = 1; c < *pivots; c++ ) sublen *= nim->dim[c]; /* compute number of values to read, i.e. remaining prods */ for( c = 1, read_size = 1; c < nprods; c++ ) read_size *= prods[c]; read_size *= nim->nbyper; /* and multiply by bytes per voxel */ /* now repeatedly compute offsets, and recursively read */ for( c = 0; c < prods[0]; c++ ){ /* offset is (c * sub-block size (including pivot dim)) */ /* + (dims[] index into pivot sub-block) */ /* the unneeded multiplication is to make this more clear */ offset = c * sublen * nim->dim[*pivots] + sublen * dims[*pivots]; offset *= nim->nbyper; if( g_opts.debug > 3 ) fprintf(stderr,"-d reading %d bytes, foff %d + %d, doff %d\n", read_size, base_offset, offset, c*read_size); /* now read the next level down, adding this offset */ if( rci_read_data(nim, pivots+1, prods+1, nprods-1, dims, data + c * read_size, fp, base_offset + offset) < 0 ) return -1; } return 0; } /* allocate memory for all collapsed image data If *data is already set, do not allocate, but still calculate size for debug report. return total size on success, and < 0 on failure */ static int rci_alloc_mem(void ** data, int prods[8], int nprods, int nbyper ) { int size, index; if( nbyper < 0 || nprods < 1 || nprods > 8 ){ fprintf(stderr,"** rci_am: bad params, %d, %d\n", nbyper, nprods); return -1; } for( index = 0, size = 1; index < nprods; index++ ) size *= prods[index]; size *= nbyper; if( ! *data ){ /* then allocate what is needed */ if( g_opts.debug > 1 ) fprintf(stderr,"+d alloc %d (= %d x %d) bytes for collapsed image\n", size, size/nbyper, nbyper); *data = malloc(size); /* actually allocate the memory */ if( ! *data ){ fprintf(stderr,"** rci_am: failed to alloc %d bytes for data\n", size); return -1; } } else if( g_opts.debug > 1 ) fprintf(stderr,"-d rci_am: *data already set, need %d (%d x %d) bytes\n", size, size/nbyper, nbyper); return size; } /* prepare a pivot list for reading The pivot points are the indices into dims where the calling function wants to collapse a dimension. The last pivot should always be zero (note that we have space for that in the lists). */ static int make_pivot_list(nifti_image * nim, const int dims[], int pivots[], int prods[], int * nprods ) { int len, index; len = 0; index = nim->dim[0]; while( index > 0 ){ prods[len] = 1; while( index > 0 && (nim->dim[index] == 1 || dims[index] == -1) ){ prods[len] *= nim->dim[index]; index--; } pivots[len] = index; len++; index--; /* fine, let it drop out at -1 */ } /* make sure to include 0 as a pivot (instead of just 1, if it is) */ if( pivots[len-1] != 0 ){ pivots[len] = 0; prods[len] = 1; len++; } *nprods = len; if( g_opts.debug > 2 ){ fprintf(stderr,"+d pivot list created, pivots :"); for(index = 0; index < len; index++) fprintf(stderr," %d", pivots[index]); fprintf(stderr,", prods :"); for(index = 0; index < len; index++) fprintf(stderr," %d", prods[index]); fputc('\n',stderr); } return 0; } #undef ISEND #define ISEND(c) ( (c)==']' || (c)=='}' || (c)=='\0' ) /*---------------------------------------------------------------------*/ /*! Get an integer list in the range 0..(nvals-1), from the character string str. If we call the output pointer fred, then fred[0] = number of integers in the list (> 0), and fred[i] = i-th integer in the list for i=1..fred[0]. If on return, fred == NULL or fred[0] == 0, then something is wrong, and the caller must deal with that. Syntax of input string: - initial '{' or '[' is skipped, if present - ends when '}' or ']' or end of string is found - contains entries separated by commas - entries have one of these forms: - a single number - a dollar sign '$', which means nvals-1 - a sequence of consecutive numbers in the form "a..b" or "a-b", where "a" and "b" are single numbers (or '$') - a sequence of evenly spaced numbers in the form "a..b(c)" or "a-b(c)", where "c" encodes the step - Example: "[2,7..4,3..9(2)]" decodes to the list 2 7 6 5 4 3 5 7 9 - entries should be in the range 0..nvals-1 (borrowed, with permission, from thd_intlist.c) *//*-------------------------------------------------------------------*/ int * nifti_get_intlist( int nvals , const char * str ) { int *subv = NULL ; int ii , ipos , nout , slen ; int ibot,itop,istep , nused ; char *cpt ; /* Meaningless input? */ if( nvals < 1 ) return NULL ; /* No selection list? */ if( str == NULL || str[0] == '\0' ) return NULL ; /* skip initial '[' or '{' */ subv = (int *) malloc( sizeof(int) * 2 ) ; subv[0] = nout = 0 ; ipos = 0 ; if( str[ipos] == '[' || str[ipos] == '{' ) ipos++ ; if( g_opts.debug > 1 ) fprintf(stderr,"-d making int_list (vals = %d) from '%s'\n", nvals, str); /**- for each sub-selector until end of input... */ slen = strlen(str) ; while( ipos < slen && !ISEND(str[ipos]) ){ while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */ if( ISEND(str[ipos]) ) break ; /* done */ /**- get starting value */ if( str[ipos] == '$' ){ /* special case */ ibot = nvals-1 ; ipos++ ; } else { /* decode an integer */ ibot = strtol( str+ipos , &cpt , 10 ) ; if( ibot < 0 ){ fprintf(stderr,"** ERROR: list index %d is out of range 0..%d\n", ibot,nvals-1) ; free(subv) ; return NULL ; } if( ibot >= nvals ){ fprintf(stderr,"** ERROR: list index %d is out of range 0..%d\n", ibot,nvals-1) ; free(subv) ; return NULL ; } nused = (cpt-(str+ipos)) ; if( ibot == 0 && nused == 0 ){ fprintf(stderr,"** ERROR: list syntax error '%s'\n",str+ipos) ; free(subv) ; return NULL ; } ipos += nused ; } while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */ /**- if that's it for this sub-selector, add one value to list */ if( str[ipos] == ',' || ISEND(str[ipos]) ){ nout++ ; subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ; subv[0] = nout ; subv[nout] = ibot ; if( ISEND(str[ipos]) ) break ; /* done */ ipos++ ; continue ; /* re-start loop at next sub-selector */ } /**- otherwise, must have '..' or '-' as next inputs */ if( str[ipos] == '-' ){ ipos++ ; } else if( str[ipos] == '.' && str[ipos+1] == '.' ){ ipos++ ; ipos++ ; } else { fprintf(stderr,"** ERROR: index list syntax is bad: '%s'\n", str+ipos) ; free(subv) ; return NULL ; } /**- get ending value for loop now */ if( str[ipos] == '$' ){ /* special case */ itop = nvals-1 ; ipos++ ; } else { /* decode an integer */ itop = strtol( str+ipos , &cpt , 10 ) ; if( itop < 0 ){ fprintf(stderr,"** ERROR: index %d is out of range 0..%d\n", itop,nvals-1) ; free(subv) ; return NULL ; } if( itop >= nvals ){ fprintf(stderr,"** ERROR: index %d is out of range 0..%d\n", itop,nvals-1) ; free(subv) ; return NULL ; } nused = (cpt-(str+ipos)) ; if( itop == 0 && nused == 0 ){ fprintf(stderr,"** ERROR: index list syntax error '%s'\n",str+ipos) ; free(subv) ; return NULL ; } ipos += nused ; } /**- set default loop step */ istep = (ibot <= itop) ? 1 : -1 ; while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */ /**- check if we have a non-default loop step */ if( str[ipos] == '(' ){ /* decode an integer */ ipos++ ; istep = strtol( str+ipos , &cpt , 10 ) ; if( istep == 0 ){ fprintf(stderr,"** ERROR: index loop step is 0!\n") ; free(subv) ; return NULL ; } nused = (cpt-(str+ipos)) ; ipos += nused ; if( str[ipos] == ')' ) ipos++ ; if( (ibot-itop)*istep > 0 ){ fprintf(stderr,"** WARNING: index list '%d..%d(%d)' means nothing\n", ibot,itop,istep ) ; } } /**- add values to output */ for( ii=ibot ; (ii-itop)*istep <= 0 ; ii += istep ){ nout++ ; subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ; subv[0] = nout ; subv[nout] = ii ; } /**- check if we have a comma to skip over */ while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */ if( str[ipos] == ',' ) ipos++ ; /* skip commas */ } /* end of loop through selector string */ if( g_opts.debug > 1 ) { fprintf(stderr,"+d int_list (vals = %d): ", subv[0]); for( ii = 1; ii <= subv[0]; ii++ ) fprintf(stderr,"%d ", subv[ii]); fputc('\n',stderr); } if( subv[0] == 0 ){ free(subv); subv = NULL; } return subv ; } minc-2.2.00/conversion/nifti1/znzlib.c0000644000265600003100000001477412027132661014507 00000000000000/** \file znzlib.c \brief Low level i/o interface to compressed and noncompressed files. Written by Mark Jenkinson, FMRIB This library provides an interface to both compressed (gzip/zlib) and uncompressed (normal) file IO. The functions are written to have the same interface as the standard file IO functions. To use this library instead of normal file IO, the following changes are required: - replace all instances of FILE* with znzFile - change the name of all function calls, replacing the initial character f with the znz (e.g. fseek becomes znzseek) one exception is rewind() -> znzrewind() - add a third parameter to all calls to znzopen (previously fopen) that specifies whether to use compression (1) or not (0) - use znz_isnull rather than any (pointer == NULL) comparisons in the code for znzfile types (normally done after a return from znzopen) NB: seeks for writable files with compression are quite restricted */ #include "znzlib.h" /* znzlib.c (zipped or non-zipped library) ***** This code is released to the public domain. ***** ***** Author: Mark Jenkinson, FMRIB Centre, University of Oxford ***** ***** Date: September 2004 ***** ***** Neither the FMRIB Centre, the University of Oxford, nor any of ***** ***** its employees imply any warranty of usefulness of this software ***** ***** for any purpose, and do not assume any liability for damages, ***** ***** incidental or otherwise, caused by any use of this document. ***** */ /* Note extra argument (use_compression) where use_compression==0 is no compression use_compression!=0 uses zlib (gzip) compression */ znzFile znzopen(const char *path, const char *mode, int use_compression) { znzFile file; file = (znzFile) calloc(1,sizeof(struct znzptr)); if( file == NULL ){ fprintf(stderr,"** ERROR: znzopen failed to alloc znzptr\n"); return NULL; } file->nzfptr = NULL; #ifdef HAVE_ZLIB file->zfptr = NULL; if (use_compression) { file->withz = 1; if((file->zfptr = gzopen(path,mode)) == NULL) { free(file); file = NULL; } } else { #endif file->withz = 0; if((file->nzfptr = fopen(path,mode)) == NULL) { free(file); file = NULL; } #ifdef HAVE_ZLIB } #endif return file; } znzFile znzdopen(int fd, const char *mode, int use_compression) { znzFile file; file = (znzFile) calloc(1,sizeof(struct znzptr)); if( file == NULL ){ fprintf(stderr,"** ERROR: znzdopen failed to alloc znzptr\n"); return NULL; } #ifdef HAVE_ZLIB if (use_compression) { file->withz = 1; file->zfptr = gzdopen(fd,mode); file->nzfptr = NULL; } else { #endif file->withz = 0; #ifdef HAVE_FDOPEN file->nzfptr = fdopen(fd,mode); #endif #ifdef HAVE_ZLIB file->zfptr = NULL; }; #endif return file; } int Xznzclose(znzFile * file) { int retval = 0; if (*file!=NULL) { #ifdef HAVE_ZLIB if ((*file)->zfptr!=NULL) { retval = gzclose((*file)->zfptr); } #endif if ((*file)->nzfptr!=NULL) { retval = fclose((*file)->nzfptr); } free(*file); *file = NULL; } return retval; } size_t znzread(void* buf, size_t size, size_t nmemb, znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return (size_t) (gzread(file->zfptr,buf,((int) size)*((int) nmemb)) / size); #endif return fread(buf,size,nmemb,file->nzfptr); } size_t znzwrite(const void* buf, size_t size, size_t nmemb, znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) { /* NOTE: We must typecast const away from the buffer because gzwrite does not have complete const specification */ return (size_t) ( gzwrite(file->zfptr,(void *)buf,size*nmemb) / size ); } #endif return fwrite(buf,size,nmemb,file->nzfptr); } long znzseek(znzFile file, long offset, int whence) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return (long) gzseek(file->zfptr,offset,whence); #endif return fseek(file->nzfptr,offset,whence); } int znzrewind(znzFile stream) { if (stream==NULL) { return 0; } #ifdef HAVE_ZLIB /* On some systems, gzrewind() fails for uncompressed files. Use gzseek(), instead. 10, May 2005 [rickr] if (stream->zfptr!=NULL) return gzrewind(stream->zfptr); */ if (stream->zfptr!=NULL) return (int)gzseek(stream->zfptr, 0L, SEEK_SET); #endif rewind(stream->nzfptr); return 0; } long znztell(znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return (long) gztell(file->zfptr); #endif return ftell(file->nzfptr); } int znzputs(const char * str, znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return gzputs(file->zfptr,str); #endif return fputs(str,file->nzfptr); } char * znzgets(char* str, int size, znzFile file) { if (file==NULL) { return NULL; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return gzgets(file->zfptr,str,size); #endif return fgets(str,size,file->nzfptr); } int znzflush(znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return gzflush(file->zfptr,Z_SYNC_FLUSH); #endif return fflush(file->nzfptr); } int znzeof(znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return gzeof(file->zfptr); #endif return feof(file->nzfptr); } int znzputc(int c, znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return gzputc(file->zfptr,c); #endif return fputc(c,file->nzfptr); } int znzgetc(znzFile file) { if (file==NULL) { return 0; } #ifdef HAVE_ZLIB if (file->zfptr!=NULL) return gzgetc(file->zfptr); #endif return fgetc(file->nzfptr); } #if !defined (WIN32) int znzprintf(znzFile stream, const char *format, ...) { char *tmpstr; int retval=0; va_list va; if (stream==NULL) { return 0; } va_start(va, format); #ifdef HAVE_ZLIB if (stream->zfptr!=NULL) { int size; /* local to HAVE_ZLIB block */ size = strlen(format) + 1000000; /* overkill I hope */ tmpstr = (char *)calloc(1, size); if( tmpstr == NULL ){ fprintf(stderr,"** ERROR: znzprintf failed to alloc %d bytes\n", size); return retval; } vsprintf(tmpstr,format,va); retval=gzprintf(stream->zfptr,"%s",tmpstr); free(tmpstr); } else #endif { retval=vfprintf(stream->nzfptr,format,va); } va_end(va); return retval; } #endif minc-2.2.00/conversion/nifti1/nii2mnc.c0000644000265600003100000005602312027132661014527 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #undef X /* These are used in nifti1_io */ #undef Y #undef Z #include #include "nifti1_io.h" #include "analyze75.h" #include "nifti1_local.h" void test_xform(mat44 m, int i, int j, int k) { double x, y, z; x = m.m[DIM_X][DIM_I] * i + m.m[DIM_X][DIM_J] * j + m.m[DIM_X][DIM_K] * k + m.m[DIM_X][3]; y = m.m[DIM_Y][DIM_I] * i + m.m[DIM_Y][DIM_J] * j + m.m[DIM_Y][DIM_K] * k + m.m[DIM_Y][3]; z = m.m[DIM_Z][DIM_I] * i + m.m[DIM_Z][DIM_J] * j + m.m[DIM_Z][DIM_K] * k + m.m[DIM_Z][3]; printf("%d %d %d => ", i, j, k); printf("%f %f %f\n", x, y, z); } static int usage(void) { static const char msg[] = { "nii2mnc: Convert NIfTI-1 files to MINC format\n" "usage: nii2mnc [options] filename.nii [filename.mnc]\n" }; fprintf(stderr, "%s", msg); return (-1); } static void find_data_range(int datatype, long nvox, void *data, double range[2]) { int i; range[0] = DBL_MAX; range[1] = -DBL_MAX; for (i = 0; i < nvox; i++) { double tmp; switch (datatype) { case DT_INT8: tmp = (double) ((char *)data)[i]; break; case DT_UINT8: tmp = (double) ((unsigned char *)data)[i]; break; case DT_INT16: tmp = (double) ((short *)data)[i]; break; case DT_UINT16: tmp = (double) ((unsigned short *)data)[i]; break; case DT_INT32: tmp = (double) ((int *)data)[i]; break; case DT_UINT32: tmp = (double) ((unsigned int *)data)[i]; break; case DT_FLOAT32: tmp = (double) ((float *)data)[i]; break; case DT_FLOAT64: tmp = (double) ((double *)data)[i]; break; default: fprintf(stderr, "Data type %d not handled\n", datatype); break; } if (tmp < range[0]) { range[0] = tmp; } if (tmp > range[1]) { range[1] = tmp; } } } int main(int argc, char **argv) { /* NIFTI stuff */ nifti_image *nii_ptr; /* MINC stuff */ int mnc_fd; /* MINC file descriptor */ nc_type mnc_mtype; /* MINC memory data type */ int mnc_msign; /* MINC !0 if signed data */ static nc_type mnc_vtype; /* MINC voxel data type */ static int mnc_vsign; /* MINC !0 if signed data */ int mnc_ndims; /* MINC image dimension count */ int mnc_dimids[MAX_VAR_DIMS]; /* MINC image dimension identifiers */ int mnc_iid; /* MINC Image variable ID */ long mnc_start[MAX_VAR_DIMS]; /* MINC data starts */ long mnc_count[MAX_VAR_DIMS]; /* MINC data counts */ char *mnc_hist; /* MINC history */ double mnc_vrange[2]; /* MINC valid min/max */ double mnc_srange[2]; /* MINC image min/max */ double mnc_time_step; double mnc_time_start; int mnc_spatial_axes[MAX_NII_DIMS]; double mnc_starts[MAX_SPACE_DIMS]; double mnc_steps[MAX_SPACE_DIMS]; double mnc_dircos[MAX_SPACE_DIMS][MAX_SPACE_DIMS]; Transform mnc_xform; General_transform mnc_linear_xform; int mnc_vid; /* Dimension variable id */ struct analyze75_hdr ana_hdr; /* Other stuff */ char out_str[1024]; /* Big string for filename */ int i; /* Generic loop counter the first */ int j; /* Generic loop counter the second */ char *str_ptr; /* Generic ASCIZ string pointer */ int r; /* Result code. */ static int qflag = 0; /* Quiet flag (default is non-quiet) */ static int rflag = 1; /* Scan range flag */ static int oflag = DIMORDER_ZYX; static int flip[MAX_SPACE_DIMS]; static char *mnc_ordered_dim_names[MAX_SPACE_DIMS]; static ArgvInfo argTable[] = { {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *)&mnc_vtype, "Write voxel data in 8-bit integer format."}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *)&mnc_vtype, "Write voxel data in 16-bit integer format."}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *)&mnc_vtype, "Write voxel data in 32-bit integer format."}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *)&mnc_vtype, "Write voxel data in 32-bit floating point format."}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *)&mnc_vtype, "Write voxel data in 64-bit floating point format."}, {"-signed", ARGV_CONSTANT, (char *) 1, (char *)&mnc_vsign, "Write integer voxel data in signed format."}, {"-unsigned", ARGV_CONSTANT, (char *) 0, (char *)&mnc_vsign, "Write integer voxel data in unsigned format."}, {"-noscanrange", ARGV_CONSTANT, (char *) 0, (char *)&rflag, "Do not scan data range."}, {"-quiet", ARGV_CONSTANT, (char *) 0, (char *)&qflag, "Quiet operation"}, {"-transverse", ARGV_CONSTANT, (char *) DIMORDER_ZYX, (char *) &oflag, "Assume transverse (ZYX) ordering for spatial dimensions"}, {"-sagittal", ARGV_CONSTANT, (char *) DIMORDER_XZY, (char *) &oflag, "Assume sagittal (XZY) ordering for spatial dimensions"}, {"-coronal", ARGV_CONSTANT, (char *) DIMORDER_YZX, (char *) &oflag, "Assume coronal (YZX) ordering for spatial dimensions"}, {"-xyz", ARGV_CONSTANT, (char *) DIMORDER_XYZ, (char *) &oflag, "Assume XYZ ordering for spatial dimensions"}, {"-zxy", ARGV_CONSTANT, (char *) DIMORDER_ZXY, (char *) &oflag, "Assume ZXY ordering for spatial dimensions"}, {"-yxz", ARGV_CONSTANT, (char *) DIMORDER_YXZ, (char *) &oflag, "Assume YXZ ordering for spatial dimensions"}, {"-flipx", ARGV_CONSTANT, (char *) 1, (char *)&flip[DIM_X], "Invert direction of X (left-right) axis"}, {"-flipy", ARGV_CONSTANT, (char *) 1, (char *)&flip[DIM_Y], "Invert direction of Y (posterior-anterior) axis"}, {"-flipz", ARGV_CONSTANT, (char *) 1, (char *)&flip[DIM_Z], "Invert direction of Z (inferior-superior) axis"}, {NULL, ARGV_END, NULL, NULL, NULL} }; ncopts = 0; /* Clear global netCDF error reporting flag */ mnc_hist = time_stamp(argc, argv); mnc_vtype = NC_NAT; if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) { fprintf(stderr, "Too few arguments\n"); return usage(); } if (argc == 2) { strcpy(out_str, argv[1]); str_ptr = strrchr(out_str, '.'); if (str_ptr != NULL) { if (!strcmp(str_ptr, ".nii") || !strcmp(str_ptr, ".hdr")) { *str_ptr = '\0'; strcat(out_str, ".mnc"); } } } else if (argc == 3) { strcpy(out_str, argv[2]); } else { fprintf(stderr, "Filename argument required\n"); return usage(); } /* Read in the entire NIfTI file. */ nii_ptr = nifti_image_read(argv[1], 1); if (nii_ptr->nifti_type == 0) { /* Analyze file!!! */ FILE *fp; int ss; int must_swap; fp = fopen(argv[1], "rb"); if (fp != NULL) { fread(&ana_hdr, sizeof (ana_hdr), 1, fp); fclose(fp); must_swap = 0; ss = ana_hdr.dime.dim[0]; if (ss != 0) { if (ss < 0 || ss > 7) { nifti_swap_2bytes(1, &(ss)); if (ss < 0 || ss > 7) { /* We should never get here!! */ fprintf(stderr, "Bad dimension count!!\n"); } else { must_swap = 1; } } } else { ss = ana_hdr.hk.sizeof_hdr; if (ss != sizeof(ana_hdr)) { nifti_swap_4bytes(1, &(ss)); if (ss != sizeof(ana_hdr)) { /* We should never get here!! */ fprintf(stderr, "Bad header size!!\n"); } else { must_swap = 1; } } } if (must_swap) { nifti_swap_4bytes(1, &(ana_hdr.hk.sizeof_hdr)); nifti_swap_4bytes(1, &(ana_hdr.hk.extents)); nifti_swap_2bytes(1, &(ana_hdr.hk.session_error)); nifti_swap_4bytes(1, &(ana_hdr.dime.compressed)); nifti_swap_4bytes(1, &(ana_hdr.dime.verified)); nifti_swap_4bytes(1, &(ana_hdr.dime.glmax)); nifti_swap_4bytes(1, &(ana_hdr.dime.glmin)); nifti_swap_2bytes(8, ana_hdr.dime.dim); nifti_swap_4bytes(8, ana_hdr.dime.pixdim); nifti_swap_2bytes(1, &(ana_hdr.dime.datatype)); nifti_swap_2bytes(1, &(ana_hdr.dime.bitpix)); nifti_swap_4bytes(1, &(ana_hdr.dime.vox_offset)); nifti_swap_4bytes(1, &(ana_hdr.dime.cal_max)); nifti_swap_4bytes(1, &(ana_hdr.dime.cal_min)); } if (!qflag) { printf("orient = %d\n", ana_hdr.hist.orient); } } } if (!qflag) { nifti_image_infodump(nii_ptr); } /* Set up the spatial axis correspondence for the call to * convert_transform_to_starts_and_steps() */ switch (oflag) { default: case DIMORDER_ZYX: mnc_ordered_dim_names[DIM_X] = MIxspace; mnc_ordered_dim_names[DIM_Y] = MIyspace; mnc_ordered_dim_names[DIM_Z] = MIzspace; mnc_spatial_axes[DIM_X] = DIM_X; mnc_spatial_axes[DIM_Y] = DIM_Y; mnc_spatial_axes[DIM_Z] = DIM_Z; break; case DIMORDER_ZXY: mnc_ordered_dim_names[DIM_X] = MIyspace; mnc_ordered_dim_names[DIM_Y] = MIxspace; mnc_ordered_dim_names[DIM_Z] = MIzspace; mnc_spatial_axes[DIM_X] = DIM_Y; mnc_spatial_axes[DIM_Y] = DIM_X; mnc_spatial_axes[DIM_Z] = DIM_Z; break; case DIMORDER_XYZ: mnc_ordered_dim_names[DIM_X] = MIzspace; mnc_ordered_dim_names[DIM_Y] = MIyspace; mnc_ordered_dim_names[DIM_Z] = MIxspace; mnc_spatial_axes[DIM_X] = DIM_Z; mnc_spatial_axes[DIM_Y] = DIM_Y; mnc_spatial_axes[DIM_Z] = DIM_X; break; case DIMORDER_XZY: mnc_ordered_dim_names[DIM_X] = MIyspace; mnc_ordered_dim_names[DIM_Y] = MIzspace; mnc_ordered_dim_names[DIM_Z] = MIxspace; mnc_spatial_axes[DIM_X] = DIM_Y; mnc_spatial_axes[DIM_Y] = DIM_Z; mnc_spatial_axes[DIM_Z] = DIM_X; break; case DIMORDER_YZX: mnc_ordered_dim_names[DIM_X] = MIxspace; mnc_ordered_dim_names[DIM_Y] = MIzspace; mnc_ordered_dim_names[DIM_Z] = MIyspace; mnc_spatial_axes[DIM_X] = DIM_X; mnc_spatial_axes[DIM_Y] = DIM_Z; mnc_spatial_axes[DIM_Z] = DIM_Y; break; case DIMORDER_YXZ: mnc_ordered_dim_names[DIM_X] = MIzspace; mnc_ordered_dim_names[DIM_Y] = MIxspace; mnc_ordered_dim_names[DIM_Z] = MIyspace; mnc_spatial_axes[DIM_X] = DIM_Z; mnc_spatial_axes[DIM_Y] = DIM_X; mnc_spatial_axes[DIM_Z] = DIM_Y; break; } switch (nii_ptr->datatype) { case DT_INT8: mnc_msign = 1; mnc_mtype = NC_BYTE; mnc_vrange[0] = CHAR_MIN; mnc_vrange[1] = CHAR_MAX; break; case DT_UINT8: mnc_msign = 0; mnc_mtype = NC_BYTE; mnc_vrange[0] = 0; mnc_vrange[1] = UCHAR_MAX; break; case DT_INT16: mnc_msign = 1; mnc_mtype = NC_SHORT; mnc_vrange[0] = SHRT_MIN; mnc_vrange[1] = SHRT_MAX; break; case DT_UINT16: mnc_msign = 0; mnc_mtype = NC_SHORT; mnc_vrange[0] = 0; mnc_vrange[1] = USHRT_MAX; break; case DT_INT32: mnc_msign = 1; mnc_mtype = NC_INT; mnc_vrange[0] = INT_MIN; mnc_vrange[1] = INT_MAX; break; case DT_UINT32: mnc_msign = 0; mnc_mtype = NC_INT; mnc_vrange[0] = 0; mnc_vrange[1] = UINT_MAX; break; case DT_FLOAT32: mnc_msign = 1; mnc_mtype = NC_FLOAT; mnc_vrange[0] = -FLT_MAX; mnc_vrange[1] = FLT_MAX; break; case DT_FLOAT64: mnc_msign = 1; mnc_mtype = NC_DOUBLE; mnc_vrange[0] = -DBL_MAX; mnc_vrange[1] = DBL_MAX; break; default: fprintf(stderr, "Data type %d not handled\n", nii_ptr->datatype); break; } if (mnc_vtype == NC_NAT) { mnc_vsign = mnc_msign; mnc_vtype = mnc_mtype; } /* Open the MINC file. It should not already exist. */ mnc_fd = micreate(out_str, NC_NOCLOBBER); if (mnc_fd < 0) { fprintf(stderr, "Can't create output file '%s'\n", out_str); return (-1); } /* Create the necessary dimensions in the minc file */ mnc_ndims = 0; if (nii_ptr->nt > 1) { mnc_dimids[mnc_ndims] = ncdimdef(mnc_fd, MItime, nii_ptr->nt); mnc_start[mnc_ndims] = 0; mnc_count[mnc_ndims] = nii_ptr->nt; mnc_ndims++; r = micreate_std_variable(mnc_fd, MItime, NC_INT, 0, NULL); switch (nii_ptr->time_units) { case NIFTI_UNITS_UNKNOWN: case NIFTI_UNITS_SEC: mnc_time_step = nii_ptr->dt; mnc_time_start = nii_ptr->toffset; break; case NIFTI_UNITS_MSEC: mnc_time_step = nii_ptr->dt / 1000; mnc_time_start = nii_ptr->toffset / 1000; break; case NIFTI_UNITS_USEC: mnc_time_step = nii_ptr->dt / 1000000; mnc_time_start = nii_ptr->toffset / 1000000; break; default: fprintf(stderr, "Unknown time units value %d\n", nii_ptr->time_units); break; } miattputdbl(mnc_fd, r, MIstart, mnc_time_start); miattputdbl(mnc_fd, r, MIstep, mnc_time_step); miattputstr(mnc_fd, r, MIunits, "s"); } if (nii_ptr->nz > 1) { mnc_dimids[mnc_ndims] = ncdimdef(mnc_fd, mnc_ordered_dim_names[DIM_Z], nii_ptr->nz); mnc_start[mnc_ndims] = 0; mnc_count[mnc_ndims] = nii_ptr->nz; mnc_ndims++; r = micreate_std_variable(mnc_fd, mnc_ordered_dim_names[DIM_Z], NC_INT, 0, NULL); miattputdbl(mnc_fd, r, MIstep, nii_ptr->dz); miattputstr(mnc_fd, r, MIunits, "mm"); } if (nii_ptr->ny > 1) { mnc_dimids[mnc_ndims] = ncdimdef(mnc_fd, mnc_ordered_dim_names[DIM_Y], nii_ptr->ny); mnc_start[mnc_ndims] = 0; mnc_count[mnc_ndims] = nii_ptr->ny; mnc_ndims++; r = micreate_std_variable(mnc_fd, mnc_ordered_dim_names[DIM_Y], NC_INT, 0, NULL); miattputdbl(mnc_fd, r, MIstep, nii_ptr->dy); miattputstr(mnc_fd, r, MIunits, "mm"); } if (nii_ptr->nx > 1) { mnc_dimids[mnc_ndims] = ncdimdef(mnc_fd, mnc_ordered_dim_names[DIM_X], nii_ptr->nx); mnc_start[mnc_ndims] = 0; mnc_count[mnc_ndims] = nii_ptr->nx; mnc_ndims++; r = micreate_std_variable(mnc_fd, mnc_ordered_dim_names[DIM_X], NC_INT, 0, NULL); miattputdbl(mnc_fd, r, MIstep, nii_ptr->dx); miattputstr(mnc_fd, r, MIunits, "mm"); } if (nii_ptr->nu > 1) { mnc_dimids[mnc_ndims] = ncdimdef(mnc_fd, MIvector_dimension, nii_ptr->nu); mnc_start[mnc_ndims] = 0; mnc_count[mnc_ndims] = nii_ptr->nu; mnc_ndims++; } /* Create scalar image-min and image-max variables. */ micreate_std_variable(mnc_fd, MIimagemax, NC_DOUBLE, 0, NULL); micreate_std_variable(mnc_fd, MIimagemin, NC_DOUBLE, 0, NULL); /* Create the group variables. */ micreate_std_variable(mnc_fd, MIstudy, NC_INT, 0, NULL); if (strlen(nii_ptr->descrip) > 0 && strlen(nii_ptr->descrip) < 79 ) { int varid = micreate_std_variable(mnc_fd, MIpatient, NC_INT, 0, NULL); (void) miattputstr(mnc_fd, varid, MIfull_name, nii_ptr->descrip); } else { micreate_std_variable(mnc_fd, MIpatient, NC_INT, 0, NULL); } micreate_std_variable(mnc_fd, MIacquisition, NC_INT, 0, NULL); /* Create the MINC image variable. If we can't, there is no * further processing possible... */ mnc_iid = micreate_std_variable(mnc_fd, MIimage, mnc_vtype, mnc_ndims, mnc_dimids); if (mnc_iid < 0) { fprintf(stderr, "Can't create the image variable\n"); return (-1); } miattputstr(mnc_fd, mnc_iid, MIsigntype, (mnc_vsign) ? MI_SIGNED : MI_UNSIGNED); /* Calculate the starts, steps, and direction cosines. This only * be done properly if the file is NIfTI-1 file. If it is an Analyze * file we have to resort to other methods... */ if (nii_ptr->nifti_type != 0 && (nii_ptr->sform_code != NIFTI_XFORM_UNKNOWN || nii_ptr->qform_code != NIFTI_XFORM_UNKNOWN)) { make_identity_transform(&mnc_xform); if (nii_ptr->sform_code != NIFTI_XFORM_UNKNOWN) { if (!qflag) { printf("Using s-form transform:\n"); } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { Transform_elem(mnc_xform, i, j) = nii_ptr->sto_xyz.m[i][j]; if (!qflag) { printf("%8.4f, ", nii_ptr->sto_xyz.m[i][j]); } } if (!qflag) { printf("\n"); } } } else { if (!qflag) { printf("Using q-form transform:\n"); } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { Transform_elem(mnc_xform, i, j) = nii_ptr->qto_xyz.m[i][j]; if (!qflag) { printf("%8.4f, ", nii_ptr->qto_xyz.m[i][j]); } } if (!qflag) { printf("\n"); } } } create_linear_transform(&mnc_linear_xform, &mnc_xform); convert_transform_to_starts_and_steps(&mnc_linear_xform, MAX_SPACE_DIMS, NULL, mnc_spatial_axes, mnc_starts, mnc_steps, mnc_dircos); } else { /* No official transform was found (possibly this is an Analyze * file). Just use some reasonable defaults. */ mnc_steps[mnc_spatial_axes[DIM_X]] = nii_ptr->dx; mnc_steps[mnc_spatial_axes[DIM_Y]] = nii_ptr->dy; mnc_steps[mnc_spatial_axes[DIM_Z]] = nii_ptr->dz; mnc_starts[mnc_spatial_axes[DIM_X]] = -(nii_ptr->dx * nii_ptr->nx) / 2; mnc_starts[mnc_spatial_axes[DIM_Y]] = -(nii_ptr->dy * nii_ptr->ny) / 2; mnc_starts[mnc_spatial_axes[DIM_Z]] = -(nii_ptr->dz * nii_ptr->nz) / 2; /* Unlike the starts and steps, the direction cosines do NOT change * based upon the data orientation. */ for (i = 0; i < MAX_SPACE_DIMS; i++) { for (j = 0; j < MAX_SPACE_DIMS; j++) { mnc_dircos[i][j] = (i == j) ? 1.0 : 0.0; } } } switch (nii_ptr->xyz_units) { case NIFTI_UNITS_METER: for (i = 0; i < MAX_SPACE_DIMS; i++) { mnc_starts[i] *= 1000; mnc_steps[i] *= 1000; } break; case NIFTI_UNITS_MM: break; case NIFTI_UNITS_MICRON: for (i = 0; i < MAX_SPACE_DIMS; i++) { mnc_starts[i] /= 1000; mnc_steps[i] /= 1000; } break; default: fprintf(stderr, "Unknown XYZ units %d\n", nii_ptr->xyz_units); break; } /* Now we write the spatial axis information to the file. The starts, * steps, and cosines have to be associated with the correct spatial * axes. Also, we perform any orientation flipping that was requested. */ for (i = 0; i < MAX_SPACE_DIMS; i++) { if (!qflag) { printf("%s start: %8.4f step: %8.4f cosines: %8.4f %8.4f %8.4f\n", mnc_spatial_names[i], mnc_starts[i], mnc_steps[i], mnc_dircos[i][DIM_X], mnc_dircos[i][DIM_Y], mnc_dircos[i][DIM_Z]); } mnc_vid = ncvarid(mnc_fd, mnc_spatial_names[i]); /* If we selected "flipping" of the appropriate axis, do it here */ if (flip[i]) { miattputdbl(mnc_fd, mnc_vid, MIstart, mnc_starts[i]+((mnc_count[i]-1)*mnc_steps[i])); miattputdbl(mnc_fd, mnc_vid, MIstep, -mnc_steps[i]); } else { miattputdbl(mnc_fd, mnc_vid, MIstart, mnc_starts[i]); miattputdbl(mnc_fd, mnc_vid, MIstep, mnc_steps[i]); } ncattput(mnc_fd, mnc_vid, MIdirection_cosines, NC_DOUBLE, MAX_SPACE_DIMS, mnc_dircos[i]); } /* Find the valid minimum and maximum of the data, in order to set the * global image minimum and image maximum properly. */ if (rflag) { find_data_range(nii_ptr->datatype, nii_ptr->nvox, nii_ptr->data, mnc_vrange); } if (nii_ptr->scl_slope != 0.0) { /* Convert slope/offset to min/max */ mnc_srange[0] = (mnc_vrange[0] * nii_ptr->scl_slope) + nii_ptr->scl_inter; mnc_srange[1] = (mnc_vrange[1] * nii_ptr->scl_slope) + nii_ptr->scl_inter; } else { mnc_srange[0] = mnc_vrange[0]; mnc_srange[1] = mnc_vrange[1]; } ncattput(mnc_fd, mnc_iid, MIvalid_range, NC_DOUBLE, 2, mnc_vrange); miattputstr(mnc_fd, NC_GLOBAL, MIhistory, mnc_hist); /* Switch out of definition mode. */ ncendef(mnc_fd); /* Finally, write the values of the image-min, image-max, and image * variables. */ mivarput1(mnc_fd, ncvarid(mnc_fd, MIimagemin), mnc_start, NC_DOUBLE, MI_SIGNED, &mnc_srange[0]); mivarput1(mnc_fd, ncvarid(mnc_fd, MIimagemax), mnc_start, NC_DOUBLE, MI_SIGNED, &mnc_srange[1]); mivarput(mnc_fd, mnc_iid, mnc_start, mnc_count, mnc_mtype, (mnc_msign) ? MI_SIGNED : MI_UNSIGNED, nii_ptr->data); miclose(mnc_fd); return (0); } minc-2.2.00/conversion/vff2mnc/0000755000265600003100000000000012030114723013236 500000000000000minc-2.2.00/conversion/vff2mnc/vff2mnc.h0000644000265600003100000000470712027132661014707 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : vff2mnc.h @DESCRIPTION: Header file that includes things needed for vff2mnc @METHOD : @GLOBALS : @CREATED : Jul 2006 (Leila Baghdadi) @MODIFIED : * $Log: vff2mnc.h,v $ * Revision 1.2 2007-12-11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 1.1 2007/01/16 18:38:18 baghdadi * header file for vff2mnc * * Adopted from vfftominc (perl script) of John G. Sled. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #if HAVE_SYS_TYPES_H #include #endif #include #include #include #include #include #include #include #if HAVE_FLOAT_H #include #endif #include #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #define MAX_VFF_DIMS 3 #define MAX_BUF_LINE 80 #define MAX_BUF_TEXT 1000 #define MAX_DESCRIPTION 2 typedef char string_t[511+1]; #define STRING_T_LEN (sizeof(string_t) - 1) #ifndef S_ISDIR #define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) #endif #define CHKMEM(x) \ if ((x) == NULL) \ (fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__), \ exit(-1)) #define TESTRPT(msg, val) (fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val), r) struct globals { char *minc_history; /* Global for minc history */ char *pname; /* program name */ int little_endian; char * dirname; int List; }; extern struct globals G; struct vff_attrs { int y_bin; int z_bin; int bands; double center_of_rotation; double central_slice; double rfan_y; double rfan_z; double angle_increment; int reverse_order; int bits; int day; int month; int year; string_t cmd_line; }; struct mnc_vars { mitype_t mnc_type; int mnc_ndims; /* MINC image dimension count */ long mnc_start[MAX_VFF_DIMS]; /* MINC data starts */ long mnc_count[MAX_VFF_DIMS]; /* MINC data counts */ char *mnc_hist; /* MINC history */ double mnc_srange[2]; /* MINC image min/max */ double mnc_starts[MAX_VFF_DIMS]; double mnc_steps[MAX_VFF_DIMS]; }; minc-2.2.00/conversion/vff2mnc/vff2mnc.man10000644000265600003100000000226612027132661015312 00000000000000.TH "vff2mnc" "1" "Jul 10 2006" "$Revision: 1.2 $" "" .SH "NAME" .B vff2mnc \- convert set of vff file(s) to one 3D MINC2.0 format file. .SH "SYNOPSIS" .B vff2mnc .I [] .B vff2mnc .I \-help .SH "DESCRIPTION" The .B vff2mnc command is used to convert vff format files to MINC2.0 format. "VFF" stands for "Vextractor File Format". This format is used for storing vector data between sessions. The vff file contains the image information at the very top in text format and the actual image right after the form feed character '\f' in binary. .SH "OPTIONS" .SH "Output file options" .TP .BI \-noswap Do not swap bytes when creating the MINC2.0 file. .TP .BI \-list Print list of series (don't create files). .SH "Generic options for all commands" .TP .BI \-help Print summary of command\-line options and abort .TP .BI \-version Print the program and library versions and abort .SH "AUTHORS" Leila Baghdadi (adopted from JG Sled Perl code) Please direct all complaints and inquiries to Leila Baghdadi .SH "BUGS" Probably many. But must discover them first .SH "SEE ALSO" .SH "COPYRIGHTS" Copyrights 1993\-2006 for the Montreal Neurological Institute. minc-2.2.00/conversion/vff2mnc/vff2mnc.c0000644000265600003100000010572412027132661014703 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : vff2mnc.c @DESCRIPTION: Program to convert vff file(s) to minc @GLOBALS : @CREATED : Jul 2006 (Leila Baghdadi) @MODIFIED : * $Log: vff2mnc.c,v $ * Revision 1.7 2010-03-27 15:10:59 rotor * * removed default volume_io caching * * fixed a few warnings in vff2mnc (fgets) * * Revision 1.6 2008/09/23 02:18:08 alex * Fixed typo on line 141 which prevented minc to be built * * Revision 1.5 2008/09/04 16:15:01 baghdadi * corrected start value to world coordinate system * * Revision 1.4 2008/01/11 07:17:07 stever * Remove unused variables. * * Revision 1.3 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 1.2 2007/01/19 17:52:56 baghdadi * Added minor revision for string manipulations. * * Revision 1.1 2007/01/16 18:37:57 baghdadi * To convert vff files produced by the CT scanner to MINC2.0 * * Adopted from vfftominc (perl script) of John G. Sled. ---------------------------------------------------------------------------- */ #include "vff2mnc.h" #include #if HAVE_DIRENT_H #include #endif #if defined (_MSC_VER) #include #endif #include #include /* Function Prototypes */ static void computeScalarRange(int datatype,double range[2], long count,void *buffer); static int usage(void); static void free_list(int num_files, const char **file_list); void read_2Dvff_files_header(const char **file_list, int num_files, struct mnc_vars *m2, struct vff_attrs *vattrs); void read_2Dvff_files_image(mihandle_t hvol, const char **file_list, int num_files, struct mnc_vars m2, struct vff_attrs vattrs,double range[2]); void read_3Dvff_file_header(char *filename, struct mnc_vars *m2, struct vff_attrs *vattrs); void read_3Dvff_file_image(mihandle_t hvol, char *filename, struct mnc_vars m2, struct vff_attrs vattrs, double range[2]); int add_vff_attribute_to_file(mihandle_t hvol,const struct vff_attrs *vattrs); int add_attributes_from_files(mihandle_t hvol); int find_filenames_first(string_t fullpath_pro,string_t fullpath_des,string_t fullpath_par, int *found_protocol,int *found_description, int *found_parameters); struct globals G; #define VERSION_STRING "2.0.12 built " __DATE__ " " __TIME__ static ArgvInfo argTable[] = { {NULL, ARGV_VERINFO, VERSION_STRING, NULL, NULL }, {"-noswap", ARGV_CONSTANT, (char *) FALSE, (char *) &G.little_endian, "Change to noswap default is swap"}, {"-addattrs", ARGV_STRING, (char *) 1, (char *) &G.dirname, "Add attributes from files in the given directory"}, {"-list", ARGV_CONSTANT, (char *) TRUE, (char *) &G.List, "Print list of series (don't create files)"}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char *argv[]) { int r; const char **file_list = NULL; /* List of file names */ struct vff_attrs vffattrs; struct mnc_vars mnc2; char out_str[1024]; /* Big string for filename */ midimhandle_t hdim[MAX_VFF_DIMS]; mihandle_t hvol; double mnc_vrange[2]; /* MINC valid min/max */ int num_file_args; /* Number of files on command line */ string_t out_dir; /* Output directory */ int length; struct stat st; int ifile; int num_files; /* Total number of files */ int is_file=0; int is_list=0; int ival; char *extension; mnc2.mnc_srange[0]= -1; mnc2.mnc_srange[1]= -1; G.pname = argv[0]; /* get program name */ G.dirname = NULL; G.little_endian = 1; /*default is little endian unless otherwise*/ G.minc_history = time_stamp(argc, argv); /* Create minc history string */ if (ParseArgv(&argc, argv, argTable, 0) || argc < 2) { usage(); exit(EXIT_FAILURE); } if (G.dirname != NULL) { #if HAVE_DIRENT_H if (stat(G.dirname, &st) != 0 || !S_ISDIR(st.st_mode)) { fprintf(stderr,"Option -addattrs requires directory as argument!!!\n"); exit(EXIT_FAILURE); } #endif } if (G.List) { num_file_args = argc - 1; } else { strcpy(out_str, argv[1]); extension = strrchr(out_str, '.'); if (extension != NULL ) { extension++; if (strcmp(extension, "mnc") !=0) { usage(); exit(EXIT_FAILURE); } } if (argc == 3) { /* check if last argument is dir */ num_file_args = argc - 2; strcpy(out_dir, argv[argc - 1]); /* make sure path ends with slash */ length = strlen(out_dir); if (out_dir[length - 1] != '/') { out_dir[length++] = '/'; out_dir[length++] = '\0'; } if (stat(out_dir, &st) != 0 || !S_ISDIR(st.st_mode)) {/* assume filename */ is_file =1; } } else { //list of 2d files must check! num_file_args = argc - 2; is_list = 1; } } if (!is_file || G.List) { /* Get space for file lists */ /* Allocate the array of pointers used to implement the * list of filenames. */ file_list = malloc(1 * sizeof(char *)); CHKMEM(file_list); /* Go through the list of files, expanding directories where they * are encountered... */ num_files = 0; for (ifile = 1 ; ifile <= num_file_args; ifile++) { #if HAVE_DIRENT_H if (stat(argv[ifile + 1], &st) == 0 && S_ISDIR(st.st_mode)) { DIR *dp; struct dirent *np; char *tmp_str; length = strlen(argv[ifile + 1]); dp = opendir(argv[ifile + 1]); if (dp != NULL) { while ((np = readdir(dp)) != NULL) { /* Generate the full path to the file. */ tmp_str = malloc(length + strlen(np->d_name) + 2); strcpy(tmp_str, argv[ifile + 1]); if (tmp_str[length-1] != '/') { tmp_str[length] = '/'; tmp_str[length+1] = '\0'; } strcat(&tmp_str[length], np->d_name); if (stat(tmp_str, &st) == 0 && S_ISREG(st.st_mode)) { file_list = realloc(file_list, (num_files + 1) * sizeof(char *)); file_list[num_files++] = tmp_str; } else { free(tmp_str); } } closedir(dp); } else { fprintf(stderr, "Error opening directory '%s'\n", argv[ifile + 1]); } } else { file_list = realloc(file_list, (num_files + 1) * sizeof(char *)); file_list[num_files++] = strdup(argv[ifile + 1]); } #else file_list = realloc(file_list, (num_files + 1) * sizeof(char *)); file_list[num_files++] = strdup(argv[ifile + 1]); #endif } } if (G.List) { exit(EXIT_SUCCESS); } if (is_file) { read_3Dvff_file_header(argv[2],&mnc2,&vffattrs); } else { read_2Dvff_files_header(file_list,num_files,&mnc2,&vffattrs); } /* ok starting to create minc2.0 file assuming 3D must take care of 2D*/ r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, mnc2.mnc_count[2], &hdim[0]); if (r != 0) { TESTRPT("failed create_dimension zspace", r); return (1); } r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, mnc2.mnc_count[1], &hdim[1]); if (r != 0) { TESTRPT("failed create_dimension yspace", r); return (1); } r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, mnc2.mnc_count[0], &hdim[2]); if (r != 0) { TESTRPT("failed create_dimension xspace", r); return (1); } r = miset_dimension_start(hdim[0], mnc2.mnc_starts[2]); if (r < 0) { TESTRPT("failed dimension start xspace", r); return (1); } r = miset_dimension_start(hdim[1], mnc2.mnc_starts[1]); if (r < 0) { TESTRPT("failed dimension start yspace", r); return (1); } /* create negative start for xspace to correct orientation */ r = miset_dimension_start(hdim[2], mnc2.mnc_starts[0] * -1); if (r < 0) { TESTRPT("failed dimension start zspace", r); return (1); } /* create negative spacing for zspace to correct orientation */ r = miset_dimension_separation(hdim[0], mnc2.mnc_steps[2] * -1); if (r < 0) { TESTRPT("failed dimension separation xspace", r); return (1); } /* create negative spacing for yspace to correct orientation */ r = miset_dimension_separation(hdim[1], mnc2.mnc_steps[1] * -1); if (r < 0) { TESTRPT("failed dimension separation yspace", r); return (1); } r = miset_dimension_separation(hdim[2], mnc2.mnc_steps[0]); if (r < 0) { TESTRPT("failed dimension separation zspace", r); return (1); } r = micreate_volume(out_str,MAX_VFF_DIMS, hdim, mnc2.mnc_type, MI_CLASS_REAL, NULL, &hvol); if (r != 0) { TESTRPT("error creating volume", r); return (1); } r = micreate_volume_image(hvol); if (r != 0) { TESTRPT("error creating volume", r); return (1); } // read image slice by slice if (is_file) { read_3Dvff_file_image(hvol, argv[2], mnc2, vffattrs, mnc_vrange); } else { read_2Dvff_files_image(hvol,file_list,num_files, mnc2, vffattrs, mnc_vrange); } miset_volume_valid_range(hvol,mnc_vrange[1], mnc_vrange[0]); if (mnc2.mnc_srange[0] == -1 || mnc2.mnc_srange[1] == -1) { /* min and max are not specified in the file voxel range is set same as real range */ mnc2.mnc_srange[0] = mnc_vrange[0]; mnc2.mnc_srange[1] = mnc_vrange[1]; } miset_volume_range(hvol,mnc2.mnc_srange[1], mnc2.mnc_srange[0]); if (is_file) { /* create minc history 3D */ strcat(vffattrs.cmd_line,G.minc_history); G.minc_history = vffattrs.cmd_line; /* attributes from vff file itself 3D case*/ add_vff_attribute_to_file(hvol,&vffattrs); } if (G.dirname != NULL) { /* attributes from external files 3D case*/ add_attributes_from_files(hvol); } else if (!is_file) { /* just afew attributes from 2D case */ ival = vffattrs.year; r = miset_attr_values(hvol, MI_TYPE_INT, "study", MIstart_year,1 , &ival); if (r < 0) { TESTRPT("failed to add date:year attribute", r); } ival = vffattrs.month; r = miset_attr_values(hvol, MI_TYPE_INT, "study", MIstart_month,1 , &ival); if (r < 0) { TESTRPT("failed to add date:month attribute", r); } ival = vffattrs.day; r = miset_attr_values(hvol, MI_TYPE_INT, "study", MIstart_day,1 , &ival); if (r < 0) { TESTRPT("failed to add date:day attribute", r); } } /* add history attribute */ r = miadd_history_attr(hvol,strlen(G.minc_history), G.minc_history); if (r < 0) { TESTRPT("error creating history", r); return (1); } if (file_list != NULL) { free_list(num_files, file_list); free(file_list); } miclose_volume(hvol); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : computeScalarRange @INPUT : datatype range (max, min) count (dim1 * dim2) buffer (actual data) @OUTPUT : voxel range max and min @RETURNS : (nothing) @DESCRIPTION: Function to scan data for voxel min and max @METHOD : @GLOBALS : @CALLS : @CREATED : Jul 2006 (Leila Baghdadi) @MODIFIED : Adopted from Bert's code for DICOM files. ---------------------------------------------------------------------------- */ static void computeScalarRange(int datatype,double range[2],long count,void *buffer) { int i; range[0] = DBL_MAX; range[1] = -DBL_MAX; for(i=0; i < count; i++) { double tmp; switch (datatype) { case MI_TYPE_UBYTE: tmp = (double) ((unsigned char *)buffer)[i]; break; case MI_TYPE_BYTE: tmp = (double) ((char *)buffer)[i]; break; case MI_TYPE_SHORT: tmp = (double) ((short *)buffer)[i]; break; case MI_TYPE_USHORT: tmp = (double) ((unsigned short *)buffer)[i]; break; case MI_TYPE_FLOAT: tmp = (double) ((float *)buffer)[i]; break; default: printf("Data type %d not handled\n", datatype); break; } if (tmp < range[0]) { range[0] = tmp; } if (tmp > range[1]) { range[1] = tmp; } } } static int usage(void) { static const char msg[] = { "vff2mnc: Convert VFF file(s) to MINC2.0 format\n" "usage: vff2mnc [options] [ ...]\n" }; fprintf(stderr,"%s", msg); return (-1); } static void free_list(int num_files, const char **file_list) { int i; for (i = 0; i < num_files; i++) { if (file_list[i] != NULL) { free((void *) file_list[i]); } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_2Dvff_files_header @INPUT : file_list (list of files with directory) num_files number of filenames m2 minc2 variables (struct) vattrs vff attributes to be added to minc2.0 @OUTPUT : (nothing) @RETURNS : @DESCRIPTION: Function to read 2D vff files header information @METHOD : @GLOBALS : @CALLS : @CREATED : Jul 2006 (Leila Baghdadi) @MODIFIED : ---------------------------------------------------------------------------- */ void read_2Dvff_files_header(const char **file_list, int num_files, struct mnc_vars *m2, struct vff_attrs *vattrs) { FILE *fp ; int i; char linebuf[1024]; char temp[10]; char *pch; long rawsize; double element_size = 1; m2->mnc_steps[0] = 1; m2->mnc_steps[1] = 1; m2->mnc_steps[2] = 1; m2->mnc_starts[0] = 0; m2->mnc_starts[1] = 0; m2->mnc_starts[2] = 0; // set z dimension m2->mnc_count[2] = num_files; /* check files */ for (i=0; i < num_files; i++) { fp = fopen(file_list[i] , "rb" ) ; if( fp == NULL ) { exit(EXIT_FAILURE); /* bad open? */ } /* ensure file is VFF */ if(fgets(linebuf, sizeof(linebuf), fp) == NULL){ fprintf(stderr, "Error with fgets on line %d of %s\n", __LINE__, __FILE__); } if (strncmp(linebuf, "ncaa", 4) != 0) { fclose(fp); printf("File is not in vff format!!!\n"); exit(EXIT_FAILURE); } /* create a dictionary */ while (linebuf[0] != '\f') { if(fgets(linebuf, sizeof(linebuf), fp) == NULL){ fprintf(stderr, "Error with fgets on line %d of %s\n", __LINE__, __FILE__); } pch=strchr(linebuf, '='); if (pch != NULL && pch[1] !=';') { strncpy(temp, linebuf, pch-linebuf); temp[pch-linebuf]='\0'; if (strcmp(temp, "rank") == 0) { if (atoi(pch+1) != 2) { printf("Looking for 2D file got %d\n",atoi(pch+1)); exit(EXIT_FAILURE); } m2->mnc_ndims = atoi(pch+1); } else if (strcmp(temp, "size") == 0) { m2->mnc_count[0] = atoi(pch+1); pch = (char*) memchr (pch+1, ' ', strlen(linebuf)); m2->mnc_count[1] = atoi(pch+1); } else if (strcmp(temp, "rawsize") == 0) { rawsize = atoi(pch+1); } else if (strcmp(temp, "spacing") == 0) { m2->mnc_steps[0] = atof(pch+1); pch = (char*) memchr (pch+1, ' ', strlen(linebuf)); m2->mnc_steps[1] = atoi(pch+1); } else if (strcmp(temp, "origin") == 0) { m2->mnc_starts[0] = atof(pch+1); pch = (char*) memchr (pch+1, ' ', strlen(linebuf)); m2->mnc_starts[1] = atof(pch+1); } else if (strcmp(temp, "bands") == 0) { vattrs->bands = atoi(pch+1); } else if (strcmp(temp, "bits") == 0) { switch(atoi(pch+1)) { case 8: m2->mnc_type = MI_TYPE_UBYTE; vattrs->bits = 8; break; case 16: m2->mnc_type = MI_TYPE_SHORT; vattrs->bits = 16; break; default: printf("Could not determine data type!!!\n"); exit(EXIT_FAILURE); } } else if (strcmp(temp, "date") == 0) { vattrs->day = atoi(pch+7); pch[7]='\0'; vattrs->month = atoi(pch+5); pch[5]='\0'; vattrs->year = atoi(pch+1); } else if (strcmp(temp, "min") == 0) { m2->mnc_srange[0] = atof(pch+1); } else if (strcmp(temp, "max") == 0) { m2->mnc_srange[1] = atof(pch+1); } else if (strcmp(temp, "elementsize") == 0) { element_size = atof(pch+1); for(i=0; imnc_steps[i] *= element_size; m2->mnc_starts[i] *= element_size; } } } } fclose(fp); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_2Dvff_files_image @INPUT : hvol minc volume handle file_list (list of files with directory) num_files number of filenames m2 minc2 variables (struct) vattrs vff attributes to be added to minc2.0 range (data min and max range) @OUTPUT : (nothing) @RETURNS : @DESCRIPTION: Function to read the 2D vff files image @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 2007 (Leila Baghdadi) @MODIFIED : ---------------------------------------------------------------------------- */ void read_2Dvff_files_image(mihandle_t hvol, const char **file_list, int num_files, struct mnc_vars m2, struct vff_attrs vattrs, double range[2]) { FILE *fp ; int i,counts,r; void *buffer; int number_of_bits = vattrs.bits/8; unsigned long start[MAX_VFF_DIMS]; /* MINC data starts */ unsigned long count[MAX_VFF_DIMS]; double valid_range[2]; range[0] = DBL_MAX; range[1] = -DBL_MAX; start[1] = 0; start[2] = 0; count[1] = m2.mnc_count[1]; count[2] = m2.mnc_count[0]; counts = m2.mnc_count[0]*m2.mnc_count[1]; // allocate enough memory for one image (i.e, one slice) buffer = malloc(counts * number_of_bits); CHKMEM(buffer); for (i=0; i < num_files; i++) { // set start to the current slice start[0] = i; count[0] = 1; // open file fp = fopen(file_list[i] , "rb" ) ; if( fp == NULL ) { exit(EXIT_FAILURE); /* bad open? */ } // Set file position indicator to beginning of data r = fseek(fp,-counts* number_of_bits,SEEK_END); if ( r != 0) { printf(" fseek is reporting a problem!!\n"); exit(EXIT_FAILURE); } r = fread(buffer,sizeof(char),counts * number_of_bits,fp); if ( r == 0) { printf(" fread is reporting a problem.\n"); exit(EXIT_FAILURE); } if (G.little_endian && vattrs.bits==16) { /* default switch byte order of 16bit data */ swab(buffer, buffer, counts * number_of_bits); } // write the slice r = miset_voxel_value_hyperslab(hvol, m2.mnc_type, start, count, buffer); if (r != 0) { TESTRPT("can not write data with hperslab function",r); exit(EXIT_FAILURE); } //calculate min and max of slice computeScalarRange(m2.mnc_type,valid_range,count[1] * count[2],buffer); if (valid_range[0] < range[0]) { range[0] = valid_range[0]; } if (valid_range[1] > range[1]) { range[1] = valid_range[1]; } fclose(fp); } free(buffer); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_3Dvff_file_header @INPUT : filename (vff filename) m2 minc2 variables (struct) vattrs vff attributes to be added to minc2.0 @OUTPUT : (nothing) @RETURNS : @DESCRIPTION: Function to read the 3D vff file header information. @METHOD : @GLOBALS : @CALLS : @CREATED : Jul 2006 (Leila Baghdadi) @MODIFIED : ---------------------------------------------------------------------------- */ void read_3Dvff_file_header(char *filename, struct mnc_vars *m2, struct vff_attrs *vattrs) { FILE *fp ; char linebuf[1024]; char temp[20]; double element_size; char *pch; int counter; int i; m2->mnc_steps[0]=1; m2->mnc_steps[1]=1; m2->mnc_steps[2]=1; /* open file */ fp = fopen(filename , "rb" ) ; if( fp == NULL ) { exit(EXIT_FAILURE); /* bad open? */ } /* ensure file is VFF */ if(fgets(linebuf, sizeof(linebuf), fp) == NULL){ fprintf(stderr, "Error with fgets on line %d of %s\n", __LINE__, __FILE__); } if (strncmp(linebuf, "ncaa", 4) != 0) { fclose(fp); printf("File is not in vff format!!!\n"); exit(EXIT_FAILURE); } /* create a dictionary */ while (linebuf[0] != '\f') { counter =0; if(fgets(linebuf, sizeof(linebuf), fp) == NULL){ fprintf(stderr, "Error with fgets on line %d of %s\n", __LINE__, __FILE__); } pch=strchr(linebuf, '='); if (pch != NULL && pch[1] !=';') { strncpy(temp, linebuf, pch-linebuf); temp[pch-linebuf]='\0'; if (strcmp(temp, "rank") == 0) { m2->mnc_ndims = atoi(pch+1); } else if (strcmp(temp, "size") == 0) { while(pch != NULL) { m2->mnc_count[counter] = atoi(pch+1); pch = (char*) memchr (pch+1, ' ', strlen(linebuf)); counter++; } } else if (strcmp(temp, "origin") == 0) { while(pch != NULL) { m2->mnc_starts[counter] = atof(pch+1); pch = (char*) memchr (pch+1, ' ', strlen(linebuf)); counter++; } } else if (strcmp(temp, "y_bin") == 0) { vattrs->y_bin = atoi(pch+1); } else if (strcmp(temp, "z_bin") == 0) { vattrs->z_bin = atoi(pch+1); } else if (strcmp(temp, "bands") == 0) { vattrs->bands = atoi(pch+1); } else if (strcmp(temp, "center_of_rotation") == 0) { vattrs->center_of_rotation = atof(pch+1); } else if (strcmp(temp, "central_slice") == 0) { vattrs->central_slice = atof(pch+1); } else if (strcmp(temp, "rfan_y") == 0) { vattrs->rfan_y = atof(pch+1); } else if (strcmp(temp, "rfan_z") == 0) { vattrs->rfan_z = atof(pch+1); } else if (strcmp(temp, "angle_increment") == 0) { vattrs->angle_increment = atof(pch+1); } else if (strcmp(temp, "bits") == 0) { switch(atoi(pch+1)) { case 8: m2->mnc_type = MI_TYPE_UBYTE; vattrs->bits = 8; break; case 16: m2->mnc_type = MI_TYPE_SHORT; vattrs->bits = 16; break; default: printf("Could not determine data type!!!\n"); exit(EXIT_FAILURE); } } else if (strcmp(temp, "date") == 0) { vattrs->day = atoi(pch+7); pch[7]='\0'; vattrs->month = atoi(pch+5); pch[5]='\0'; vattrs->year = atoi(pch+1); } else if (strcmp(temp, "reverse_order") == 0) { if (strcmp(pch+1,"no")) vattrs->reverse_order = 0; else vattrs->reverse_order = 1; } else if (strcmp(temp, "min") == 0) { m2->mnc_srange[0] = atof(pch+1); } else if (strcmp(temp, "max") == 0) { m2->mnc_srange[1] = atof(pch+1); } else if (strcmp(temp, "spacing") == 0) { while(pch != NULL) { m2->mnc_steps[counter] = atof(pch+1); pch = (char*) memchr (pch+1, ' ', strlen(linebuf)); counter++; } } else if (strcmp(temp, "elementsize") == 0) { element_size = atof(pch+1); for(i=0; imnc_steps[i] *= element_size; m2->mnc_starts[i] *= element_size; } } else if (strcmp(temp, "cmdLine") == 0) { strcpy(vattrs->cmd_line,linebuf); } } } fclose(fp); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_3Dvff_file_image @INPUT : hvol minc volume handle filename (vff filename) m2 minc2 variables (struct) vattrs vff attributes to be added to minc2.0 range (data min and max range) @OUTPUT : (nothing) @RETURNS : @DESCRIPTION: Function to read the 3D vff file image @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 2007 (Leila Baghdadi) @MODIFIED : ---------------------------------------------------------------------------- */ void read_3Dvff_file_image(mihandle_t hvol, char *filename, struct mnc_vars m2, struct vff_attrs vattrs, double range[2]) { FILE *fp ; int i,counts,r; void *buffer; int number_of_bits = vattrs.bits/8; unsigned long start[MAX_VFF_DIMS]; /* MINC data starts */ unsigned long count[MAX_VFF_DIMS]; double valid_range[2]; range[0] = DBL_MAX; range[1] = -DBL_MAX; start[1] = 0; start[2] = 0; count[1] = m2.mnc_count[1]; count[2] = m2.mnc_count[0]; counts = m2.mnc_count[0]*m2.mnc_count[1]; /* open file */ fp = fopen(filename , "rb" ); if( fp == NULL ) { exit(EXIT_FAILURE); /* bad open? */ } // Set file position indicator to beginning of image r = fseek(fp,-counts * m2.mnc_count[2] * number_of_bits,SEEK_END); if ( r != 0) { printf(" fseek is reporting a problem!!\n"); exit(EXIT_FAILURE); } // allocate memory for one slice only buffer = malloc( counts * number_of_bits); CHKMEM(buffer); for (i = 0; i < m2.mnc_count[2]; i++) { // set start to the current slice start[0] = i; count[0] = 1; // read data one slice at a time r = fread(buffer,sizeof(char),counts * number_of_bits,fp); if ( r == 0) { printf(" fread is reporting a problem leila.\n"); exit(EXIT_FAILURE); } if (G.little_endian && vattrs.bits==16) { swab(buffer, buffer, counts * number_of_bits); } // write the slice r = miset_voxel_value_hyperslab(hvol, m2.mnc_type, start, count, buffer); if (r != 0) { TESTRPT("can not write data with hperslab function",r); exit(EXIT_FAILURE); } //calculate min and max of slice computeScalarRange(m2.mnc_type,valid_range,counts,buffer); if (valid_range[0] < range[0]) { range[0] = valid_range[0]; } if (valid_range[1] > range[1]) { range[1] = valid_range[1]; } } free(buffer); fclose(fp); } /* ----------------------------- MNI Header ----------------------------------- @NAME : add_vff_attributes_to_file @INPUT : hvol volume handle vattrs vff attributes to be added to minc2.0 @OUTPUT : (nothing) @RETURNS : @DESCRIPTION: adds various attributes to minc file @METHOD : @GLOBALS : @CALLS : @CREATED : Jul 2006 (Leila Baghdadi) @MODIFIED : ---------------------------------------------------------------------------- */ int add_vff_attribute_to_file(mihandle_t hvol,const struct vff_attrs *vattrs) { int ival; double dval; int r; ival = vattrs->y_bin; r = miset_attr_values(hvol, MI_TYPE_INT, "acquisition", "ybin",1 , &ival); if (r < 0) { TESTRPT("failed to add y_bin attribute", r); } ival = vattrs->z_bin; r = miset_attr_values(hvol, MI_TYPE_INT, "acquisition", "z_bin",1 , &ival); if (r < 0) { TESTRPT("failed to add z_bin attribute", r); } ival = vattrs->bands; r = miset_attr_values(hvol, MI_TYPE_INT, "acquisition", "bands",1 , &ival); if (r < 0) { TESTRPT("failed to add bands attribute", r); } dval = vattrs->center_of_rotation; r = miset_attr_values(hvol, MI_TYPE_DOUBLE, "acquisition", "center_of_rotation",1 , &dval); if (r < 0) { TESTRPT("failed to add center_of_rotation attribute", r); } dval = vattrs->central_slice; r = miset_attr_values(hvol, MI_TYPE_DOUBLE, "acquisition", "central_slice",1 , &dval); if (r < 0) { TESTRPT("failed to add central_slice attribute", r); } dval = vattrs->rfan_y; r = miset_attr_values(hvol, MI_TYPE_DOUBLE, "acquisition", "rfan_y",1 , &dval); if (r < 0) { TESTRPT("failed to add rfan_y attribute", r); } dval = vattrs->rfan_z; r = miset_attr_values(hvol, MI_TYPE_DOUBLE, "acquisition", "rfan_z",1 , &dval); if (r < 0) { TESTRPT("failed to add rfan_z attribute", r); } dval = vattrs->angle_increment; r = miset_attr_values(hvol, MI_TYPE_DOUBLE, "acquisition", "angle_increment",1 , &dval); if (r < 0) { TESTRPT("failed to add angle_increment attribute", r); } ival = vattrs->reverse_order; r = miset_attr_values(hvol, MI_TYPE_INT, "acquisition", "reverse_order",1 , &ival); if (r < 0) { TESTRPT("failed to add reverse_order attribute", r); } ival = vattrs->year; r = miset_attr_values(hvol, MI_TYPE_INT, "study", MIstart_year,1 , &ival); if (r < 0) { TESTRPT("failed to add date:year attribute", r); } ival = vattrs->month; r = miset_attr_values(hvol, MI_TYPE_INT, "study", MIstart_month,1 , &ival); if (r < 0) { TESTRPT("failed to add date:month attribute", r); } ival = vattrs->day; r = miset_attr_values(hvol, MI_TYPE_INT, "study", MIstart_day,1 , &ival); if (r < 0) { TESTRPT("failed to add date:day attribute", r); } return(0); } /* ----------------------------- MNI Header ----------------------------------- @NAME : add_attributes_from_files @INPUT : hvol volume handle @OUTPUT : (nothing) @RETURNS : @DESCRIPTION: adds a few files generated with vff file to minc file @METHOD : This method assumes the txt files are in the top directory @GLOBALS : @CALLS : @CREATED : Jul 2006 (Leila Baghdadi) @MODIFIED : This code is a bit ugly thanks for the wodnerful work of windows. ---------------------------------------------------------------------------- */ int add_attributes_from_files(mihandle_t hvol) { FILE *inf; char *strbuf; char *buffer; string_t fullpath_pro; string_t fullpath_des; string_t fullpath_par; char *p; int r,i; char **str; int found_protocol=0; int found_description=0; int found_parameters=0; /* first find files names --> different platforms */ find_filenames_first(fullpath_pro,fullpath_des,fullpath_par, &found_protocol,&found_description, &found_parameters); if (!found_protocol) { printf("could not find file with extension protocol\n"); } else { /* add *.protocol to "acquisition" protocol attribute */ inf = fopen(fullpath_pro,"r"); if (inf == NULL) { printf("Could not open file %s \n", fullpath_pro); exit(EXIT_FAILURE); } else { strbuf = malloc(MAX_BUF_LINE + 1); CHKMEM(strbuf); strbuf[0]='\0'; buffer = malloc(MAX_BUF_TEXT + 1); CHKMEM(buffer); buffer[0]='\0'; while (fgets(strbuf, MAX_BUF_LINE, inf) != NULL) { strcat(buffer,strbuf); } } fclose(inf); r = miset_attr_values(hvol, MI_TYPE_STRING, "acquisition", "protocol", strlen(buffer) ,buffer); free(buffer); free(strbuf); if (r < 0) { TESTRPT("failed to add protocol attribute", r); } } if (!found_description) { printf("Could not find file Description.txt\n"); } else { /* add Description.txt to patient name and study id */ inf = fopen(fullpath_des,"r"); if (inf == NULL) { printf("Could not open file %s \n", fullpath_des); exit(EXIT_FAILURE); } else { /* just need the first two lines of this file */ str = malloc(MAX_DESCRIPTION); CHKMEM(str); for (i=0; i < MAX_DESCRIPTION; i++) { str[i] = malloc(MAX_BUF_LINE + 1); CHKMEM(str[i]); if(fgets(str[i], MAX_BUF_LINE, inf) == NULL){ fprintf(stderr, "Error with fgets on line %d of %s\n", __LINE__, __FILE__); } for (p = str[i]; *p != '\0'; p++) { if (*p == '\r') { *p = '\0'; } } } r = miset_attr_values(hvol, MI_TYPE_STRING, "patient", "full_name",strlen(str[0]) , str[0]); if (r < 0) { TESTRPT("failed to add full_name attribute", r); } r = miset_attr_values(hvol, MI_TYPE_STRING, "study", "study_id",strlen(str[1]) , str[1]); if (r < 0) { TESTRPT("failed to add study_id attribute", r); } fclose(inf); for (i=0; i < MAX_DESCRIPTION; i++) { free(str[i]); } free(str); } } if (!found_parameters) { printf("Could not find file Parameters.txt\n"); } else { /* add Parameters.txt to "acquisition" scan_parameters */ inf = fopen(fullpath_par,"r"); if (inf == NULL) { printf("Could not open file %s \n", fullpath_par); exit(EXIT_FAILURE); } else { strbuf = malloc(MAX_BUF_LINE + 1); CHKMEM(strbuf); strbuf[0]='\0'; buffer = malloc(MAX_BUF_TEXT + 1); CHKMEM(buffer); buffer[0]='\0'; while (fgets(strbuf, MAX_BUF_LINE, inf) != NULL) { strcat(buffer,strbuf); } } fclose(inf); r = miset_attr_values(hvol, MI_TYPE_STRING, "acquisition", "scan_parameters",strlen(buffer) ,buffer); free(buffer); free(strbuf); if (r < 0) { TESTRPT("failed to add scan_parameters attribute", r); } } return(0); } int find_filenames_first(string_t fullpath_pro,string_t fullpath_des,string_t fullpath_par, int *found_protocol,int *found_description, int *found_parameters) { char *ptr; #if HAVE_DIRENT_H DIR *dp; struct dirent *np; dp = opendir(G.dirname); if (dp != NULL) { while ((np = readdir(dp)) != NULL) { if (np->d_name != "." && np->d_name != "..") { /* add *.protocol to "acquisition" protocol attribute */ ptr = strstr(np->d_name,"protocol"); if (ptr != NULL) { *found_protocol = 1; strcpy(fullpath_pro,np->d_name); } /* add Description.txt to patient name and study id */ ptr = strstr(np->d_name,"Description.txt"); if (ptr != NULL) { *found_description = 1; strcpy(fullpath_des,np->d_name); } /* add Parameters.txt to "acquisition" scan_parameters */ ptr = strstr(np->d_name,"Parameters.txt"); if (ptr != NULL) { *found_parameters=1; strcpy(fullpath_par,np->d_name); } } } } closedir(dp); #endif #if defined (_MSC_VER) WIN32_FIND_DATA FindFileData; HANDLE hFind = INVALID_HANDLE_VALUE; char DirSpec[MAX_BUF_LINE + 1]; char dirname[MAX_BUF_LINE + 1]; DWORD dwError; strncpy(DirSpec, G.dirname, MAX_BUF_LINE); DirSpec[MAX_BUF_LINE]='\0'; strncat(DirSpec, "\\*", 3); /* make sure the directory ends with '/' */ strncpy(dirname, G.dirname, MAX_BUF_LINE); dirname[MAX_BUF_LINE]='\0'; if (G.dirname[strlen(G.dirname)-1] != '/') { strcat(dirname,"/"); } hFind = FindFirstFile(DirSpec, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { printf(" Invalid file handle with Error %u \n", GetLastError()); return(1); } else { do { /* add *.protocol to "acquisition" protocol attribute */ ptr = strstr(FindFileData.cFileName,"protocol"); if (ptr != NULL) { *found_protocol = 1; strcpy(fullpath_pro, dirname); strcat(fullpath_pro,FindFileData.cFileName); } /* add Description.txt to patient name and study id */ ptr = strstr(FindFileData.cFileName,"Description.txt"); if (ptr != NULL) { *found_description = 1; strcpy(fullpath_des, dirname); strcat(fullpath_des,FindFileData.cFileName); } /* add Parameters.txt to "acquisition" scan_parameters */ ptr = strstr(FindFileData.cFileName,"Parameters.txt"); if (ptr != NULL) { *found_parameters=1; strcpy(fullpath_par, dirname); strcat(fullpath_par,FindFileData.cFileName); } } while (FindNextFile(hFind, &FindFileData) != 0); dwError = GetLastError(); FindClose(hFind); if (dwError != ERROR_NO_MORE_FILES) { printf(" Find next file %u\n", dwError); return(1); } } #endif return(0); } minc-2.2.00/conversion/CMakeLists.txt0000644000265600003100000000326112030075003014354 00000000000000# CMakeFiles.txt for the MINC2 conversion progs # # Andrew Janke - a.janke@gmail.com #LINK_DIRECTORIES() LINK_LIBRARIES( ${MINC2_LIBRARIES}) ADD_DEFINITIONS(-DHAVE_CONFIG_H) # conversion progs (and libraries) INCLUDE_DIRECTORIES(Acr_nema) ADD_LIBRARY(acr_nema STATIC Acr_nema/acr_io.c Acr_nema/dicom_client_routines.c Acr_nema/dicom_network.c Acr_nema/element.c Acr_nema/file_io.c Acr_nema/globals.c Acr_nema/group.c Acr_nema/message.c Acr_nema/value_repr.c) ADD_EXECUTABLE(dcm2mnc dcm2mnc/dcm2mnc.c dcm2mnc/dicom_to_minc.c dcm2mnc/siemens_to_dicom.c dcm2mnc/dicom_read.c dcm2mnc/minc_file.c dcm2mnc/progress.c dcm2mnc/string_to_filename.c) TARGET_LINK_LIBRARIES(dcm2mnc acr_nema ) ADD_EXECUTABLE(ecattominc ecattominc/ecattominc.c ecattominc/insertblood.c ecattominc/ecat_file.c ecattominc/machine_indep.c ) ADD_EXECUTABLE(minctoecat minctoecat/minctoecat.c minctoecat/ecat_write.c minctoecat/machine_indep.c ) TARGET_LINK_LIBRARIES(minctoecat ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(mnc2nii nifti1/mnc2nii.c nifti1/nifti1_io.c nifti1/znzlib.c ) TARGET_LINK_LIBRARIES(mnc2nii ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(nii2mnc nifti1/nii2mnc.c nifti1/nifti1_io.c nifti1/znzlib.c ) TARGET_LINK_LIBRARIES(nii2mnc ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(upet2mnc micropet/upet2mnc.c ) IF(BUILD_MINC2) ADD_EXECUTABLE(vff2mnc vff2mnc/vff2mnc.c ) INSTALL(TARGETS vff2mnc DESTINATION bin) ENDIF(BUILD_MINC2) # install progs INSTALL(TARGETS dcm2mnc ecattominc minctoecat mnc2nii nii2mnc upet2mnc DESTINATION bin) minc-2.2.00/ezminc/0000755000265600003100000000000012030114720010772 500000000000000minc-2.2.00/ezminc/examples/0000755000265600003100000000000012030114723012613 500000000000000minc-2.2.00/ezminc/examples/volume_msq_dist.cpp0000644000265600003100000000544612027132661016471 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : volume_msq_dist @DESCRIPTION: an example of calculating mean squared dissimilarity @COPYRIGHT : Copyright 2011 Vladimir Fonov, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_1_rw.h" #include #include "minc_1_simple.h" using namespace minc; int main(int argc,char **argv) { try { if(argc<4) { std::cerr<<"Usage: "< "<0) size*=rdr1.ndim(i); } for(int i=0;i<5;i++) { if(rdr1.nspacing(i)!=rdr2.nspacing(i) || rdr1.nspacing(i)!=rdr_m.nspacing(i)) { std::cerr<<"Different step size! "< buffer1(size),buffer2(size); std::vector mask(size); load_standard_volume(rdr1,&buffer1[0]); load_standard_volume(rdr2,&buffer2[0]); load_standard_volume(rdr_m,&mask[0]); double avg=0; int cnt=0; for(int i=0;i #include #include "minc_compat.h" #else #include #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* For compatibility with NetCDF 2.x which uses NC_LONG rather than NC_INT. Since NC_INT is defined in an enum, and since there are no version macros, we use NC_FILL_INT as an indicator of whether NC_INT is defined. */ #ifndef NC_FILL_INT # define NC_INT NC_LONG #endif /* Constant used with nc_type variables to indicate that the data type should be taken from the source object or file. This replaces earlier use of NC_UNSPECIFIED and is equivalent to NetCDF NC_NAT in version 3.5 and later. */ #define MI_ORIGINAL_TYPE ((nc_type) 0) /* NC_UNSPECIFIED is defined here for backwards compatibility. With NetCDF 2.x, NC_UNSPECIFIED may already be defined either through a macro or an enum. In the latter case, this macro will override the enum. */ #ifndef NC_UNSPECIFIED # define NC_UNSPECIFIED MI_ORIGINAL_TYPE #endif /* Some useful constants */ #define MI_EMPTY_STRING "" /* Error flags */ #define MI_ERROR (-1) #define MI_NOERROR 0 /* Maximum length of standard attributes */ #define MI_MAX_ATTSTR_LEN 64 /* Number of spatial dimensions */ #define MI_NUM_SPACE_DIMS 3 /* Maximum number of image dimensions for image conversion */ /* Bert 10-Aug-2004 - MI_MAX_IMGDIMS used to be defined to be MAX_VAR_DIMS, * a constant defined in netcdf.h. For many years MAX_VAR_DIMS was 100, * but in netCDF 3.5.1 the value was changed to 512. * Unfortunately, the definitions of MI_ICV_DIM_SIZE, MI_ICV_DIM_STEP, * and MI_ICV_DIM_START assume that MI_MAX_IMGDIMS is less than or * equal to 100. To avoid changing the MINC API, we have to define * MI_MAX_IMGDIMS to 100 here. Otherwise the miicv_inqdbl() function * will return bogus values for these ICV properties. */ #define MI_MAX_IMGDIMS 100 /* NetCDF standard attributes */ #define MIunits "units" #define MIlong_name "long_name" #define MIvalid_range "valid_range" #define MIvalid_max "valid_max" #define MIvalid_min "valid_min" #define MI_FillValue "_FillValue" #define MItitle "title" #define MIhistory "history" /* General variable attributes */ #define MIvartype "vartype" #define MIvarid "varid" #define MIsigntype "signtype" #define MIparent "parent" #define MIchildren "children" #define MIcomments "comments" #define MIversion "version" /* General attribute constants */ /* Prefix for identifying a variable attribute pointer */ #define MI_VARATT_POINTER_PREFIX "--->" /* Separator for elements of MIchildren */ #define MI_CHILD_SEPARATOR "\n" /* MIvartype values */ #define MI_GROUP "group________" #define MI_DIMENSION "dimension____" #define MI_DIM_WIDTH "dim-width____" #define MI_VARATT "var_attribute" /* MIvarid value */ #define MI_STDVAR "MINC standard variable" /* MIsigntype values */ #define MI_SIGNED "signed__" #define MI_UNSIGNED "unsigned" /* MIversion value */ #define MI_VERSION_1_0 "MINC Version 1.0" #define MI_CURRENT_VERSION MI_VERSION_1_0 /* Generally useful values for boolean attributes */ #define MI_TRUE "true_" #define MI_FALSE "false" /* Dimension names and names of associated variables */ #define MIxspace "xspace" #define MIyspace "yspace" #define MIzspace "zspace" #define MItime "time" #define MItfrequency "tfrequency" #define MIxfrequency "xfrequency" #define MIyfrequency "yfrequency" #define MIzfrequency "zfrequency" #define MIvector_dimension "vector_dimension" #define MIxspace_width "xspace-width" #define MIyspace_width "yspace-width" #define MIzspace_width "zspace-width" #define MItime_width "time-width" #define MItfrequency_width "tfrequency-width" #define MIxfrequency_width "xfrequency-width" #define MIyfrequency_width "yfrequency-width" #define MIzfrequency_width "zfrequency-width" /* Dimension variable attribute names */ /* For dimension variables (MIspacing is also for dimension width vars) */ #define MIspacing "spacing" #define MIstep "step" #define MIstart "start" #define MIspacetype "spacetype" #define MIalignment "alignment" #define MIdirection_cosines "direction_cosines" /* For dimension width variables */ #define MIwidth "width" #define MIfiltertype "filtertype" /* Dimension attribute constants */ /* MIgridtype values */ #define MI_REGULAR "regular__" #define MI_IRREGULAR "irregular" /* MIspacetype values */ #define MI_NATIVE "native____" #define MI_TALAIRACH "talairach_" #define MI_CALLOSAL "callosal__" /* MIalignment values */ #define MI_START "start_" #define MI_CENTRE "centre" #define MI_END "end___" #define MI_CENTER MI_CENTRE /* MIfiltertype values */ #define MI_SQUARE "square____" #define MI_GAUSSIAN "gaussian__" #define MI_TRIANGULAR "triangular" /* The root variable */ #define MIrootvariable "rootvariable" /* The image variable and its attributes */ #define MIimage "image" #define MIimagemax "image-max" #define MIimagemin "image-min" #define MIcomplete "complete" /* The patient variable and its attributes */ #define MIpatient "patient" #define MIfull_name "full_name" #define MIother_names "other_names" #define MIidentification "identification" #define MIother_ids "other_ids" #define MIbirthdate "birthdate" #define MIsex "sex" #define MIage "age" #define MIweight "weight" #define MIsize "size" #define MIaddress "address" #define MIinsurance_id "insurance_id" /* Patient attribute constants */ #define MI_MALE "male__" #define MI_FEMALE "female" #define MI_OTHER "other_" /* The study variable and its attributes */ #define MIstudy "study" #define MIstart_time "start_time" #define MIstart_year "start_year" #define MIstart_month "start_month" #define MIstart_day "start_day" #define MIstart_hour "start_hour" #define MIstart_minute "start_minute" #define MIstart_seconds "start_seconds" #define MImodality "modality" #define MImanufacturer "manufacturer" #define MIdevice_model "device_model" #define MIinstitution "institution" #define MIdepartment "department" #define MIstation_id "station_id" #define MIreferring_physician "referring_physician" #define MIattending_physician "attending_physician" #define MIradiologist "radiologist" #define MIoperator "operator" #define MIadmitting_diagnosis "admitting_diagnosis" #define MIprocedure "procedure" #define MIstudy_id "study_id" /* Study attribute constants */ #define MI_PET "PET__" #define MI_SPECT "SPECT" #define MI_GAMMA "GAMMA" #define MI_MRI "MRI__" #define MI_MRS "MRS__" #define MI_MRA "MRA__" #define MI_CT "CT___" #define MI_DSA "DSA__" #define MI_DR "DR___" #define MI_LABEL "label" /* The acquisition variable and its attributes */ #define MIacquisition "acquisition" #define MIprotocol "protocol" #define MIscanning_sequence "scanning_sequence" #define MIrepetition_time "repetition_time" #define MIecho_time "echo_time" #define MIinversion_time "inversion_time" #define MInum_averages "num_averages" #define MIimaging_frequency "imaging_frequency" #define MIimaged_nucleus "imaged_nucleus" #define MIradionuclide "radionuclide" #define MIcontrast_agent "contrast_agent" #define MIradionuclide_halflife "radionuclide_halflife" #define MItracer "tracer" #define MIinjection_time "injection_time" #define MIinjection_year "injection_year" #define MIinjection_month "injection_month" #define MIinjection_day "injection_day" #define MIinjection_hour "injection_hour" #define MIinjection_minute "injection_minute" #define MIinjection_seconds "injection_seconds" #define MIinjection_length "injection_length" #define MIinjection_dose "injection_dose" #define MIdose_units "dose_units" #define MIinjection_volume "injection_volume" #define MIinjection_route "injection_route" /* Constants for image conversion variable (icv) properties */ /* Maximum number of icv's allowed */ /* changed to 32 as netcdf 4.x no longer defines MAX_NC_OPEN */ /* #define MI_MAX_NUM_ICV MAX_NC_OPEN */ #define MI_MAX_NUM_ICV 32 /* Default max and min for normalization */ #define MI_DEFAULT_MAX 1.0 #define MI_DEFAULT_MIN 0.0 /* For converting data type */ #define MI_ICV_TYPE 1 #define MI_ICV_SIGN 2 #define MI_ICV_DO_RANGE 3 #define MI_ICV_VALID_MAX 4 #define MI_ICV_VALID_MIN 5 /* For doing normalization */ #define MI_ICV_DO_NORM 6 #define MI_ICV_USER_NORM 7 #define MI_ICV_IMAGE_MAX 8 #define MI_ICV_IMAGE_MIN 9 /* Values actually used in normalization - read-only */ #define MI_ICV_NORM_MAX 10 #define MI_ICV_NORM_MIN 11 /* For doing dimension conversions */ #define MI_ICV_DO_DIM_CONV 12 /* For converting vector fields to scalar */ #define MI_ICV_DO_SCALAR 13 /* For flipping axis direction */ #define MI_ICV_XDIM_DIR 14 #define MI_ICV_YDIM_DIR 15 #define MI_ICV_ZDIM_DIR 16 /* For changing size of first two dimensions (excluding MIvector_dimension) */ #define MI_ICV_ADIM_SIZE 17 #define MI_ICV_BDIM_SIZE 18 #define MI_ICV_KEEP_ASPECT 19 /* The pixel size and location of first two dimensions (these are readonly) */ #define MI_ICV_ADIM_STEP 20 #define MI_ICV_BDIM_STEP 21 #define MI_ICV_ADIM_START 22 #define MI_ICV_BDIM_START 23 /* Number of image dimensions for dimension conversion */ #define MI_ICV_NUM_IMGDIMS 24 /* Number of dimensions of image variable taking into account vector/scalar data (read-only property) */ #define MI_ICV_NUM_DIMS 25 /* Id of file and image variable (read-only properties) */ #define MI_ICV_CDFID 26 #define MI_ICV_VARID 27 /* Names of MIimagemax and MIimagemin variables */ #define MI_ICV_MAXVAR 28 #define MI_ICV_MINVAR 29 /* For setting input values to a specified fillvalue */ #define MI_ICV_DO_FILLVALUE 30 #define MI_ICV_FILLVALUE 31 /* Image dimension properties. For each dimension, add the dimension number (counting from fastest to slowest). */ #define MI_ICV_DIM_SIZE 1000 #define MI_ICV_DIM_STEP 1100 #define MI_ICV_DIM_START 1200 /* Constants that can be used as values for the above properties. */ /* Possible values for MI_ICV_?DIM_DIR */ #define MI_ICV_POSITIVE 1 #define MI_ICV_NEGATIVE (-1) #define MI_ICV_ANYDIR 0 /* Possible value for MI_ICV_?DIM_SIZE */ #define MI_ICV_ANYSIZE (-1) /* Error codes. Note that they must not conflict with NetCDF error codes since they are stored in the same global variable. */ #define MI_ERR_NONNUMERIC 1331 /* Non-numeric type */ #define MI_ERR_NONCHAR 1332 /* Non-character type */ #define MI_ERR_NONSCALAR 1333 /* Non-scalar attribute */ #define MI_ERR_BADOP 1334 /* Bad operation for MI_varaccess */ #define MI_ERR_NOTPOINTER 1335 /* Attribute is not a pointer */ #define MI_ERR_BAD_STDVAR 1336 /* Not a standard variable */ #define MI_ERR_BADSUFFIX 1337 /* Bad dimension width suffix */ #define MI_ERR_NOICV 1338 /* Out of icv slots */ #define MI_ERR_BADICV 1339 /* Illegal icv identifier */ #define MI_ERR_BADPROP 1340 /* Unknown icv property */ #define MI_ERR_ICVATTACHED 1341 /* Tried to modify attached icv */ #define MI_ERR_TOOFEWDIMS 1342 /* Too few dimensions to be an image */ #define MI_ERR_ICVNOTATTACHED 1343 /* Tried to access an unattached icv */ #define MI_ERR_DIMSIZE 1344 /* Dimensions differ in size */ #define MI_ERR_ICV_INVCOORDS 1345 /* Invalid icv coordinates */ #define MI_ERR_WRONGNDIMS 1346 /* Too many dimensions for a dim var */ #define MI_ERR_BADMATCH 1347 /* Variables do not match for copy */ #define MI_ERR_MAXMIN_DIMS 1348 /* Imagemax/min variables vary over image dimensions */ #define MI_ERR_UNCOMPRESS 1349 /* Not able to uncompress file */ /* MINC public functions */ /* From netcdf_convenience.c */ MNCAPI char *miexpand_file(char *path, char *tempfile, int header_only, int *created_tempfile); MNCAPI int miopen(char *path, int mode); MNCAPI int micreate(char *path, int cmode); MNCAPI int miclose(int cdfid); MNCAPI int miattget_with_sign(int cdfid, int varid, char *name, char *insign, nc_type datatype, char *outsign, int max_length, void *value, int *att_length); MNCAPI int miattget(int cdfid, int varid, char *name, nc_type datatype, int max_length, void *value, int *att_length); MNCAPI int miattget1(int cdfid, int varid, char *name, nc_type datatype, void *value); MNCAPI char *miattgetstr(int cdfid, int varid, char *name, int maxlen, char *value); MNCAPI int miattputint(int cdfid, int varid, char *name, int value); MNCAPI int miattputdbl(int cdfid, int varid, char *name, double value); MNCAPI int miattputstr(int cdfid, int varid, char *name, char *value); MNCAPI int mivarget(int cdfid, int varid, long start[], long count[], nc_type datatype, char *sign, void *values); MNCAPI int mivarget1(int cdfid, int varid, long mindex[], nc_type datatype, char *sign, void *value); MNCAPI int mivarput(int cdfid, int varid, long start[], long count[], nc_type datatype, char *sign, void *values); MNCAPI int mivarput1(int cdfid, int varid, long mindex[], nc_type datatype, char *sign, void *value); MNCAPI long *miset_coords(int nvals, long value, long coords[]); MNCAPI long *mitranslate_coords(int cdfid, int invar, long incoords[], int outvar, long outcoords[]); MNCAPI int micopy_all_atts(int incdfid, int invarid, int outcdfid, int outvarid); MNCAPI int micopy_var_def(int incdfid, int invarid, int outcdfid); MNCAPI int micopy_var_values(int incdfid, int invarid, int outcdfid, int outvarid); MNCAPI int micopy_all_var_defs(int incdfid, int outcdfid, int nexclude, int excluded_vars[]); MNCAPI int micopy_all_var_values(int incdfid, int outcdfid, int nexclude, int excluded_vars[]); MNCAPI char *micreate_tempfile(void); /* From minc_convenience.c */ MNCAPI int miget_datatype(int cdfid, int imgid, nc_type *datatype, int *is_signed); MNCAPI int miget_default_range(nc_type datatype, int is_signed, double default_range[]); MNCAPI int miget_valid_range(int cdfid, int imgid, double valid_range[]); MNCAPI int miset_valid_range(int cdfid, int imgid, double valid_range[]); MNCAPI int miget_image_range(int cdfid, double image_range[]); MNCAPI int mivar_exists(int cdfid, char *varname); MNCAPI int miattput_pointer(int cdfid, int varid, char *name, int ptrvarid); MNCAPI int miattget_pointer(int cdfid, int varid, char *name); MNCAPI int miadd_child(int cdfid, int parent_varid, int child_varid); MNCAPI int micreate_std_variable(int cdfid, char *name, nc_type datatype, int ndims, int dim[]); MNCAPI int micreate_group_variable(int cdfid, char *name); MNCAPI const char *miget_version(void); MNCAPI int miappend_history(int fd, const char *tm_stamp); MNCAPI int micreate_ident(char * id_str, size_t length); /* From image_conversion.c */ MNCAPI int miicv_create(void); MNCAPI int miicv_free(int icvid); MNCAPI int miicv_setdbl(int icvid, int icv_property, double value); MNCAPI int miicv_setint(int icvid, int icv_property, int value); MNCAPI int miicv_setlong(int icvid, int icv_property, long value); MNCAPI int miicv_setstr(int icvid, int icv_property, char *value); MNCAPI int miicv_inqdbl(int icvid, int icv_property, double *value); MNCAPI int miicv_inqint(int icvid, int icv_property, int *value); MNCAPI int miicv_inqlong(int icvid, int icv_property, long *value); MNCAPI int miicv_inqstr(int icvid, int icv_property, char *value); MNCAPI int miicv_ndattach(int icvid, int cdfid, int varid); MNCAPI int miicv_detach(int icvid); MNCAPI int miicv_get(int icvid, long start[], long count[], void *values); MNCAPI int miicv_put(int icvid, long start[], long count[], void *values); /* From dim_conversion.c */ MNCAPI int miicv_attach(int icvid, int cdfid, int varid); /* From minc_error.c */ MNCAPI void milog_init(const char *); MNCAPI int milog_set_verbosity(int); /* default voxel loop buffer size */ #define MI2_DEF_BUFF_SIZE 4096 #define MI2_DEF_MAX_MEM 104857 #if MINC2 /* New functions, not directly part of compatibility layer. */ extern int MI2varsize(int fd, int varid, long *size_ptr); #define MI2_GRPNAME "/minc-2.0" /* These must not interfere with any NC_ flags we might have to support. */ #define MI2_CREATE_V2 0x1000 /* Force V2 format */ #define MI2_CREATE_V1 0x2000 /* Force V1 format */ /* Possible compression type values. */ #define MI2_COMP_UNKNOWN (-1) #define MI2_COMP_NONE 0 #define MI2_COMP_ZLIB 1 #define MI2_CHUNK_UNKNOWN (-1) #define MI2_CHUNK_OFF 0 #define MI2_CHUNK_ON 1 #define MI2_CHUNK_MIN_SIZE 4 #define MI2_OPTS_V1 1 struct mi2opts { int struct_version; int comp_type; int comp_param; int chunk_type; int chunk_param; }; #define MI2_ISH5OBJ(x) (H5Iget_type(x) > 0) #else #define MI2_ISH5OBJ(x) (0) #endif /* MINC2 */ #ifdef __cplusplus } #endif /* __cplusplus */ /* End ifndef MINC_HEADER_FILE */ #endif minc-2.2.00/libsrc/ParseArgv.h0000644000265600003100000000520412027132662012762 00000000000000/* * ParseArgv.h -- * * Declarations for Tk-related things that are visible * outside of the Tk module itself. * * Copyright 1989-1992 Regents of the University of California. * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * * This file has been modified to be used only for argv parsing without * reference to tk, tcl or X11. Base on tk.h from tk2.3 * $Header: /private-cvsroot/minc/libsrc/ParseArgv.h,v 6.6 2004-10-15 13:44:52 bert Exp $ SPRITE (Berkeley) */ #include "minc.h" /* * Definitions that allow this header file to be used either with or * without ANSI C features like function prototypes. */ #undef _ANSI_ARGS_ #if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) # define _ANSI_ARGS_(x) x #else # define _ANSI_ARGS_(x) () #endif /* * Structure used to specify how to handle argv options. */ typedef struct { char *key; /* The key string that flags the option in the * argv array. */ int type; /* Indicates option type; see below. */ char *src; /* Value to be used in setting dst; usage * depends on type. */ char *dst; /* Address of value to be modified; usage * depends on type. */ char *help; /* Documentation message describing this option. */ } ArgvInfo; /* * Legal values for the type field of a ArgvInfo: see the user * documentation for details. */ #define ARGV_CONSTANT 15 #define ARGV_INT 16 #define ARGV_STRING 17 #define ARGV_LONG 100 #define ARGV_REST 19 #define ARGV_FLOAT 20 #define ARGV_FUNC 21 #define ARGV_GENFUNC 22 #define ARGV_HELP 23 #define ARGV_VERSION 24 #define ARGV_VERINFO 25 #define ARGV_END 27 /* * Flag bits for passing to ParseArgv: */ #define ARGV_NO_DEFAULTS 0x1 #define ARGV_NO_LEFTOVERS 0x2 #define ARGV_NO_ABBREV 0x4 #define ARGV_DONT_SKIP_FIRST_ARG 0x8 #define ARGV_NO_PRINT 0x10 /* bert- value was 0x16, which was bogus */ /* *-------------------------------------------------------------- * * Exported procedures and variables. * *-------------------------------------------------------------- */ #if defined(__cplusplus) extern "C" { #endif MNCAPI int ParseArgv _ANSI_ARGS_((int *argcPtr, char **argv, ArgvInfo *argTable, int flags)); #if defined(__cplusplus) } #endif minc-2.2.00/libsrc/voxel_loop.h0000644000265600003100000003523012027132662013260 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : voxel_loop.h @DESCRIPTION: Header file for voxel_loop.c @GLOBALS : @CREATED : January 10, 1994 (Peter Neelin) @MODIFIED : * $Log: voxel_loop.h,v $ * Revision 6.4 2005-08-26 21:04:58 bert * Use #if rather than #ifdef with MINC2 symbol * * Revision 6.3 2004/10/15 13:46:52 bert * Minor changes for Windows compatibility * * Revision 6.2 2004/04/27 15:43:04 bert * Added set_loop_v2format() * * Revision 6.1 2002/01/14 21:28:26 neelin * Moved nd_loop, voxel_loop, ParseArgv and time_stamp from ../progs/Proglib * in order to include them in the main minc library. * * Revision 6.3 2001/11/28 18:39:17 neelin * Added get_info_vxoel_index to allow users to get the full multi-dimensional * file index of the current voxel. * Modifications to allow arg_string to be NULL. * * Revision 6.2 2000/09/19 14:36:05 neelin * Added ability for caller to specify functions for allocating and freeing * voxel buffers used in loop. This is particularly useful for embedding * the voxel_loop code in other programs, such as Python, which manage memory * in their own way. * * Revision 6.1 1999/10/19 14:45:16 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 1.3 1995/03/21 15:33:07 neelin * Changed call to voxel_function to always use proper vector length and * set num_voxels to the number of voxels, not multiplying by vector length. * * Revision 1.2 1995/03/21 14:06:39 neelin * Improved interface and added lots of functionality (much for the benefit * of mincconcat). * * Revision 1.1 94/12/14 10:18:21 neelin * Initial revision * * Revision 2.0 94/09/28 10:36:28 neelin * Release of minc version 0.2 * * Revision 1.3 94/09/28 10:36:22 neelin * Pre-release * * Revision 1.2 94/01/12 10:19:19 neelin * Added logging. Turned off filling. Added miclose for files. * * Revision 1.1 94/01/11 15:16:09 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Includes */ #include "minc.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Incomplete structure typedefs */ typedef struct Loop_Info Loop_Info; typedef struct Loop_Options Loop_Options; /* User function typedefs */ /* ----------------------------- MNI Header ----------------------------------- @NAME : VoxelFunction @INPUT : caller_data - pointer to client data. num_voxels - number of voxels to process. Note that the total number of input values is num_voxels * input_vector_length. num_input_buffers - number of input buffers to handle on this call - either total number of input files or 1 (for accumulating over files). input_vector_length - length of input vector. input_data - array of pointers to input buffers (1 for each input file, unless we are accumulating). num_output_buffers - number of output buffers to handle on this call - will be the total number of output files unless we are accumulating over files (see set_loop_accumulate). output_vector_length - length of output vector == input_vector_length or as set by set_loop_output_vector_size. loop_info - pointer that can be passed to functions returning looping information @OUTPUT : output_data - array of pointers to output buffers. Set values to -DBL_MAX to represent illegal, out-of-range values. If extra buffers are requested by set_loop_accumulate, they will follow the output buffers. @RETURNS : (nothing) @DESCRIPTION: Typedef for function called by voxel_loop to process data. ---------------------------------------------------------------------------- */ typedef void (*VoxelFunction) (void *caller_data, long num_voxels, int num_input_buffers, int input_vector_length, double *input_data[], int num_output_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); /* ----------------------------- MNI Header ----------------------------------- @NAME : VoxelInputFileFunction @INPUT : caller_data - pointer to client data. input_mincid - mincid for current input file input_curfile - current input file number (count from zero) loop_info - pointer that can be passed to functions returning looping information @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Typedef for function called by voxel_loop to get information for each input file. ---------------------------------------------------------------------------- */ typedef void (*VoxelInputFileFunction) (void *caller_data, int input_mincid, int input_curfile, Loop_Info *loop_info); /* ----------------------------- MNI Header ----------------------------------- @NAME : VoxelOutputFileFunction @INPUT : caller_data - pointer to client data. output_mincid - mincid for current output file output_curfile - current output file number (count from zero) loop_info - pointer that can be passed to functions returning looping information @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Typedef for function called by voxel_loop to modify the header of an output file (in define mode) ---------------------------------------------------------------------------- */ typedef void (*VoxelOutputFileFunction) (void *caller_data, int output_mincid, int output_curfile, Loop_Info *loop_info); /* ----------------------------- MNI Header ----------------------------------- @NAME : VoxelStartFunction @INPUT : caller_data - pointer to client data. num_voxels - number of voxels to process. output_num_buffers - number of output buffers to handle on this call - will be the total number of output files plus the number of extra buffers requested by set_loop_accumulate. output_vector_length - length of output vector = 1 or as set by set_loop_output_vector_size. loop_info - pointer that can be passed to functions returning looping information @OUTPUT : output_data - array of pointers to output buffers. If extra buffers are requested by set_loop_accumulate, they will follow the output buffers. @RETURNS : (nothing) @DESCRIPTION: Typedef for function called by voxel_loop to initialize data processing when accumulating over files (specified when calling set_loop_accumulate). ---------------------------------------------------------------------------- */ typedef void (*VoxelStartFunction) (void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); /* ----------------------------- MNI Header ----------------------------------- @NAME : VoxelFinishFunction @INPUT : caller_data - pointer to client data. num_voxels - number of voxels to process. output_num_buffers - number of output buffers to handle on this call - will be the total number of output files plus the number of extra buffers requested by set_loop_accumulate. output_vector_length - length of output vector = 1 or as set by set_loop_output_vector_size. loop_info - pointer that can be passed to functions returning looping information @OUTPUT : output_data - array of pointers to output buffers. If extra buffers are requested by set_loop_accumulate, they will follow the output buffers. @RETURNS : (nothing) @DESCRIPTION: Typedef for function called by voxel_loop to finish data processing when accumulating over files (specified when calling set_loop_accumulate). ---------------------------------------------------------------------------- */ typedef void (*VoxelFinishFunction) (void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); /* ----------------------------- MNI Header ----------------------------------- @NAME : AllocateBufferFunction @INPUT : caller_data - pointer to client data. do_allocations - if TRUE, allocate data, if FALSE, free data num_input_buffers - number of input buffers to allocate num_input_voxels - number of voxels in each input buffer input_vector_length - number of values per input voxel num_output_buffers - number of output buffers to allocate num_output_voxels - number of voxels in each output buffer output_vector_length - number of values per output voxel num_extra_buffers - number of working buffers to allocate num_extra_voxels - number of voxels in each extra buffer extra_vector_length - number of values per extra voxel loop_info - pointer that can be passed to functions returning looping information input_buffers, output_buffers, extra_buffers - if do_allocation is FALSE, then arrays of pointers to buffers that need to be freed. The pointer arrays should also be freed. @OUTPUT : input_buffers, output_buffers, extra_buffers - if do_allocation is TRUE, then these arrays of buffers should be allocated (both the array of pointers and the buffers). The pointer array should have length num_xxx_buffers and each buffer should have length num_xxx_voxels*xxx_vector_length and be of type double. @RETURNS : (nothing) @DESCRIPTION: Typedef for function called by voxel_loop to allocate and free buffers. ---------------------------------------------------------------------------- */ typedef void (*AllocateBufferFunction) (void *caller_data, int do_allocation, int num_input_buffers, int num_input_voxels, int input_vector_length, double ***input_buffers, int num_output_buffers, int num_output_voxels, int output_vector_length, double ***output_buffers, int num_extra_buffers, int num_extra_voxels, int extra_vector_length, double ***extra_buffers, Loop_Info *loop_info); /* Function declarations */ MNCAPI void voxel_loop(int num_input_files, char *input_files[], int num_output_files, char *output_files[], char *arg_string, Loop_Options *loop_options, VoxelFunction voxel_function, void *caller_data); MNCAPI Loop_Options *create_loop_options(void); MNCAPI void free_loop_options(Loop_Options *loop_options); MNCAPI void set_loop_clobber(Loop_Options *loop_options, int clobber); #if MINC2 MNCAPI void set_loop_v2format(Loop_Options *loop_options, int use_v2_format); #endif /* MINC2 */ MNCAPI void set_loop_verbose(Loop_Options *loop_options, int verbose); MNCAPI void set_loop_datatype(Loop_Options *loop_options, nc_type datatype, int is_signed, double valid_min, double valid_max); MNCAPI void set_loop_max_open_files(Loop_Options *loop_options, int max_open_files); MNCAPI void set_loop_check_dim_info(Loop_Options *loop_options, int check_dim_info); MNCAPI void set_loop_convert_input_to_scalar(Loop_Options *loop_options, int convert_input_to_scalar); MNCAPI void set_loop_output_vector_size(Loop_Options *loop_options, int output_vector_size); MNCAPI void set_loop_first_input_mincid(Loop_Options *loop_options, int input_mincid); MNCAPI void set_loop_buffer_size(Loop_Options *loop_options, long buffer_size); MNCAPI void set_loop_dimension(Loop_Options *loop_options, char *dimension_name); MNCAPI void set_loop_input_file_function (Loop_Options *loop_options, VoxelInputFileFunction input_file_function); MNCAPI void set_loop_output_file_function (Loop_Options *loop_options, VoxelOutputFileFunction output_file_function); MNCAPI void set_loop_copy_all_header(Loop_Options *loop_options, int copy_all_header); MNCAPI void set_loop_accumulate(Loop_Options *loop_options, int do_accumulation, int num_extra_buffers, VoxelStartFunction start_function, VoxelFinishFunction finish_function); MNCAPI void set_loop_allocate_buffer_function(Loop_Options *loop_options, AllocateBufferFunction allocate_buffer_function); MNCAPI void get_info_shape(Loop_Info *loop_info, int ndims, long start[], long count[]); MNCAPI void get_info_voxel_index(Loop_Info *loop_info, long subscript, int ndims, long index[]); MNCAPI int get_info_current_file(Loop_Info *loop_info); MNCAPI int get_info_current_mincid(Loop_Info *loop_info); MNCAPI int get_info_current_index(Loop_Info *loop_info); MNCAPI int get_info_whole_file(Loop_Info *loop_info); #ifdef __cplusplus } #endif /* __cplusplus */ minc-2.2.00/libsrc/nd_loop.h0000644000265600003100000000557612027132662012536 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : nd_loop.h @DESCRIPTION: Header file for nd_loop.c @METHOD : Use these routines in the following way: Set start, end and increment vectors to define looping; nd_begin_looping(start, current, ndims); while (!nd_end_of_loop(current, end, ndims)) { nd_update_current_count(current, increment, end, current_count, ndims); Use current and current_count to work on hyperslab; nd_increment_loop(current, start, increment, end, ndims); } @GLOBALS : @CREATED : December 2, 1994 (Peter Neelin) @MODIFIED : * $Log: nd_loop.h,v $ * Revision 6.2 2004-10-15 13:47:13 bert * Minor changes for Windows compatibility * * Revision 6.1 2002/01/14 21:28:26 neelin * Moved nd_loop, voxel_loop, ParseArgv and time_stamp from ../progs/Proglib * in order to include them in the main minc library. * * Revision 6.1 1999/10/19 14:45:14 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 1.3 1994/12/02 09:40:37 neelin * Fixed arguments to nd_end_of_loop. * * Revision 1.2 94/12/02 09:20:17 neelin * Added comments to clarify use of routines. * * Revision 1.1 94/12/02 08:40:31 neelin * Initial revision * @COPYRIGHT : Copyright 1994 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc.h" #if defined(__cplusplus) extern "C" { #endif MNCAPI void nd_begin_looping(long start[], long current[], int ndims); MNCAPI int nd_end_of_loop(long current[], long end[], int ndims); MNCAPI void nd_update_current_count(long current[], long increment[], long end[], long current_count[], int ndims); MNCAPI void nd_increment_loop(long current[], long start[], long increment[], long end[], int ndims); #if defined(__cplusplus) } #endif minc-2.2.00/libsrc/time_stamp.h0000644000265600003100000000414412027132662013234 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : time_stamp.h @DESCRIPTION: Header file for time_stamp.c @GLOBALS : @CREATED : February 1, 1993 (Peter Neelin) @MODIFIED : * $Log: time_stamp.h,v $ * Revision 6.2 2004-10-15 13:46:51 bert * Minor changes for Windows compatibility * * Revision 6.1 2002/01/14 21:28:26 neelin * Moved nd_loop, voxel_loop, ParseArgv and time_stamp from ../progs/Proglib * in order to include them in the main minc library. * * Revision 6.2 1999/10/19 15:57:18 neelin * Fixed log message containing log substitution * * Revision 6.1 1999/10/19 14:45:14 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:34:31 neelin * Release of minc version 0.2 * * Revision 1.4 94/09/28 10:34:20 neelin * Pre-release * * Revision 1.3 93/08/04 13:04:00 neelin * Added RCS Log to keep track of modifications in source * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ MNCAPI char *time_stamp(int argc, char *argv[]); #ifdef __cplusplus } #endif /* __cplusplus */ minc-2.2.00/libsrc/minc_compat.h0000644000265600003100000000563412027132662013370 00000000000000#if MINC2 /* Functions for enabling/disabling error messages from the library. */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ MNCAPI int MI2typelen(int); MNCAPI int MI2varname(int fd, int varid, char *varnm); MNCAPI int MI2varid(int fd, const char *varnm); MNCAPI int MI2attinq(int fd, int varid, const char *attnm, nc_type *type_ptr, int *length_ptr); MNCAPI int MI2attname(int fd, int varid, int attid, char *name); MNCAPI int MI2inquire(int fd, int *ndims_ptr, int *nvars_ptr, int *natts_ptr, int *unlimdim_ptr); MNCAPI int MI2varinq(int fd, int varid, char *varnm_ptr, nc_type *type_ptr, int *ndims_ptr, int *dims_ptr, int *natts_ptr); MNCAPI int MI2dimid(int fd, const char *dimnm); MNCAPI int MI2diminq(int fd, int dimid, char *dimnm_ptr, long *len_ptr); MNCAPI int MI2dimdef(int fd, const char *dimnm, long length); MNCAPI int MI2attget(int fd, int varid, const char *attnm, void *value); MNCAPI int MI2attput(int fd, int varid, const char *attnm, nc_type val_typ, int val_len, void *val_ptr); MNCAPI int MI2endef(int fd); MNCAPI int MI2vardef(int fd, const char *varnm, nc_type vartype, int ndims, const int *dimids); MNCAPI int MI2varget(int fd, int varid, const long *start_ptr, const long *count_ptr, void *val_ptr); MNCAPI int MI2varput(int fd, int varid, const long *start_ptr, const long *count_ptr, const void *val_ptr); MNCAPI int MI2varput1(int fd, int varid, const long *mindex_ptr, const void *val_ptr); MNCAPI int MI2attdel(int fd, int varid, const char *attnm); MNCAPI int MI2dimrename(int fd, int dimid, const char *new_name); MNCAPI int MI2varputg(int fd, int varid, const long *startp, const long *countp, const long *stridep, const long *imapp, const void *valp); MNCAPI int MI2attcopy(int infd, int invarid, const char *name, int outfd, int outvarid); MNCAPI int MI2redef(int fd); MNCAPI int MI2sync(int fd); MNCAPI int MI2setfill(int fd, int fillmode); #ifndef _MI2_FORCE_NETCDF_ #define nctypelen MI2typelen #define ncvarname MI2varname #define ncvarid MI2varid #define ncdimid MI2dimid #define ncvarinq MI2varinq #define ncdiminq MI2diminq #define ncdimdef MI2dimdef #define ncattdel MI2attdel #define ncvardef MI2vardef #define ncvarput1 MI2varput1 #define ncvarput MI2varput #define ncvarget MI2varget #define ncattinq MI2attinq #define ncvarputg MI2varputg #define nccreate micreate #define ncopen miopen #define ncclose miclose #define ncattput MI2attput #define ncinquire MI2inquire #define ncattname MI2attname #define ncdimrename MI2dimrename #define ncattcopy MI2attcopy #define ncendef MI2endef #define ncattget MI2attget #define ncredef MI2redef #define ncsync MI2sync #define ncsetfill MI2setfill #ifndef NC_NOFILL #define NC_NOFILL 0x100 #endif #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _MI2_FORCE_NETCDF_ not defined */ #endif /* MINC2 */ minc-2.2.00/libsrc/minc_simple.h0000644000265600003100000000617212027132662013374 00000000000000/* minc_simple.h * * Simplified interface for MINC files. */ #define MINC_STATUS_OK 0 #define MINC_STATUS_ERROR (-1) #define MINC_TYPE_CHAR 10 #define MINC_TYPE_UCHAR 20 #define MINC_TYPE_SHORT 30 #define MINC_TYPE_USHORT 40 #define MINC_TYPE_INT 50 #define MINC_TYPE_UINT 60 #define MINC_TYPE_FLOAT 70 #define MINC_TYPE_DOUBLE 80 #define MINC_3D 3 /* Number of spatial dimensions */ /* Get information about a MINC file. */ MNCAPI int minc_file_size(char *path, /* Path to the file */ long *ct, /* Total length of time axis, in voxels */ long *cz, /* Total length of Z axis, in voxels */ long *cy, /* Total length of Y axis, in voxels */ long *cx, /* Total length of X axis, in voxels */ long *cvoxels, /* Total number of voxels */ long *cbytes); /* Total number of bytes as native datatype */ /* Load data from a MINC file. */ MNCAPI int minc_load_data(char *path, /* Path to the file */ void *dataptr, /* Buffer to store data */ int datatype, /* Type of data as read into memory */ long *ct, long *cz, long *cy, long *cx, double *dt, double *dz, double *dy, double *dx, void **infoptr); /* Define an output file. Return value is a file handle, or * MINC_STATUS_ERROR if a problem is detected. */ MNCAPI int minc_save_start(char *path, /* Path to the file */ int filetype, /* Date type as stored in the file */ long ct, /* Total length of time axis, in voxels */ long cz, /* Total length of Z axis, in voxels */ long cy, /* Total length of Y axis, in voxels */ long cx, /* Total length of X axis, in voxels */ double dt, /* Sample width along time axis, in seconds */ double dz, /* Sample width along Z axis, in mm */ double dy, /* Sample width along Y axis, in mm */ double dx, /* Sample width along X axis, in mm */ void *infoptr, /* Opaque file structure information */ const char *history); /* New history information */ /* Write data to file. Return value is MINC_STATUS_OK or MINC_STATUS_ERROR. */ MNCAPI int minc_save_data(int handle, /* Handle returned by minc_save_start */ void *dataptr, /* Data to write */ int datatype, /* Type of data in memory */ long st, /* Start position of 4D hyperslab */ long sz, long sy, long sx, long ct, /* Size of 4D hyperslab */ long cz, long cy, long cx); /* Called when a particular file is complete. */ MNCAPI int minc_save_done(int handle); /* Called to free memory associated with the infoptr. */ MNCAPI void minc_free_info(void *infoptr); MNCAPI int minc_get_world_transform(char *path, double transform[MINC_3D][MINC_3D + 1]); minc-2.2.00/libsrc/read_file_names.h0000644000265600003100000000142112027132662014162 00000000000000 /* ----------------------------- MNI Header ----------------------------------- @NAME : read_file_names @INPUT : filelist - name of file from which to read names @OUTPUT : num_files - number of files read in @RETURNS : Pointer to a NULL-terminated array of file names @DESCRIPTION: Reads in a list of file names from file filelist or stdin if "-" is specified. Returns NULL if an error occurs. If no error occurs, then a pointer to an empty array is returned and num_files is zero. @METHOD : @GLOBALS : @CALLS : @CREATED : March 8, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ char **read_file_names(char *filelist, int *num_files); minc-2.2.00/libsrc/minc_basic.h0000644000265600003100000001700312027132662013157 00000000000000 #ifndef MINC_BASIC_HEADER_FILE #define MINC_BASIC_HEADER_FILE /* ----------------------------- MNI Header ----------------------------------- @NAME : minc_basic.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Constants and macros for private use by MINC routines. @METHOD : @GLOBALS : @CALLS : @CREATED : August 28, 1992 (Peter Neelin) @MODIFIED : * $Log: minc_basic.h,v $ * Revision 6.8 2010-03-27 15:09:28 rotor * * back to 1000000 * * Revision 6.7 2010-03-02 12:23:14 rotor * * ported HDF calls to 1.8.x * * Makefile.am: updated for minccmp * * Revision 6.6 2008/04/11 05:15:00 rotor * * rewrote error code (Claude) to remove global defs that were * causing build problems with DYLIB on OSX * * Revision 6.5 2008/01/12 01:05:37 rotor * * initial commits from Steve to remove warnings * * Revision 6.4 2007/08/09 17:05:25 rotor * * added some fixes of Claudes for chunking and internal compression * * Revision 6.3 2004/04/27 15:48:15 bert * Minor changes * * Revision 6.2 2001/04/17 18:40:13 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:08 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:38:01 neelin * Release of minc version 0.2 * * Revision 1.8 94/09/28 10:37:26 neelin * Pre-release * * Revision 1.7 93/10/28 10:18:23 neelin * Added FILLVALUE_EPSILON for doing fillvalue checking in icv's. * * Revision 1.6 93/08/11 12:06:37 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @RCSID : $Header: /private-cvsroot/minc/libsrc/minc_basic.h,v 6.8 2010-03-27 15:09:28 rotor Exp $ MINC (MNI) ---------------------------------------------------------------------------- */ #include /* --------- MINC specific constants ------------- */ /* Maximum buffer size for conversions. Should not be a power of 2 - this can cause poor performance on some systems (e.g. SGI) due to caching- related inefficiencies */ #define MI_MAX_VAR_BUFFER_SIZE 1000000 /* Possible values for sign of a value */ #define MI_PRIV_DEFSIGN 0 #define MI_PRIV_SIGNED 1 #define MI_PRIV_UNSIGNED 2 /* Operations for MI_varaccess */ #define MI_PRIV_GET 10 #define MI_PRIV_PUT 11 /* Suffix for dimension width variable names */ #define MI_WIDTH_SUFFIX "-width" /* Epsilon for detecting fillvalues */ #define FILLVALUE_EPSILON (10.0 * FLT_EPSILON) /* NetCDF routine name variable (for error logging) */ extern char *cdf_routine_name ; /* defined in globdef.c */ #define MI_NC_ROUTINE_VAR cdf_routine_name /* Macros for logging errors. All routines should start with MI_SAVE_ROUTINE and exit with MI_RETURN (which includes MI_RETURN_ERROR and MI_CHK_ERROR). All the macros except MI_CHK_ERROR are single line commands. MI_CHK_ERROR is in a block and so should not be followed by a ';' */ #define MI_SAVE_ROUTINE_NAME(name) MI_save_routine_name(name) #define MI_RETURN(value) \ return( MI_return() ? (value) : (value) ) #define MI_RETURN_ERROR(error) \ return( MI_return_error() ? (error) : (error) ) #define MI_LOG_PKG_ERROR2(p1,p2) MI_log_pkg_error2(p1, p2) #define MI_LOG_PKG_ERROR3(p1,p2,p3) MI_log_pkg_error3(p1, p2, p3) #define MI_LOG_SYS_ERROR1(p1) MI_log_sys_error1(p1) #define MI_CHK_ERR(expr) {if ((expr)<0) MI_RETURN_ERROR(MI_ERROR);} /* Macros for converting data types. These macros are compound statements, so don't put a semi-colon after them. dvalue should be a double, type is an int NetCDF type, sign is one of MI_PRIV_UNSIGNED and MI_PRIV_SIGNED and ptr is a void pointer */ #define MI_TO_DOUBLE(dvalue, type, sign, ptr) \ switch (type) { \ case NC_BYTE : \ case NC_CHAR: \ switch (sign) { \ case MI_PRIV_UNSIGNED : \ dvalue = (double) *((unsigned char *) ptr); break; \ case MI_PRIV_SIGNED : \ dvalue = (double) *((signed char *) ptr); break; \ } \ break; \ case NC_SHORT : \ switch (sign) { \ case MI_PRIV_UNSIGNED : \ dvalue = (double) *((unsigned short *) ptr); break; \ case MI_PRIV_SIGNED : \ dvalue = (double) *((signed short *) ptr); break; \ } \ break; \ case NC_INT : \ switch (sign) { \ case MI_PRIV_UNSIGNED : \ dvalue = (double) *((unsigned int *) ptr); break; \ case MI_PRIV_SIGNED : \ dvalue = (double) *((signed int *) ptr); break; \ } \ break; \ case NC_FLOAT : \ dvalue = (double) *((float *) ptr); \ break; \ case NC_DOUBLE : \ dvalue = (double) *((double *) ptr); \ break; \ case NC_NAT : \ MI_LOG_PKG_ERROR2(MI_ERR_NONNUMERIC, \ "Attempt to convert NC_NAT value to double"); \ dvalue = 0; \ break; \ } #define MI_FROM_DOUBLE(dvalue, type, sign, ptr) \ switch (type) { \ case NC_BYTE : \ case NC_CHAR : \ switch (sign) { \ case MI_PRIV_UNSIGNED : \ dvalue = MAX(0, dvalue); \ dvalue = MIN(UCHAR_MAX, dvalue); \ *((unsigned char *) ptr) = ROUND(dvalue); \ break; \ case MI_PRIV_SIGNED : \ dvalue = MAX(SCHAR_MIN, dvalue); \ dvalue = MIN(SCHAR_MAX, dvalue); \ *((signed char *) ptr) = ROUND(dvalue); \ break; \ } \ break; \ case NC_SHORT : \ switch (sign) { \ case MI_PRIV_UNSIGNED : \ dvalue = MAX(0, dvalue); \ dvalue = MIN(USHRT_MAX, dvalue); \ *((unsigned short *) ptr) = ROUND(dvalue); \ break; \ case MI_PRIV_SIGNED : \ dvalue = MAX(SHRT_MIN, dvalue); \ dvalue = MIN(SHRT_MAX, dvalue); \ *((signed short *) ptr) = ROUND(dvalue); \ break; \ } \ break; \ case NC_INT : \ switch (sign) { \ case MI_PRIV_UNSIGNED : \ dvalue = MAX(0, dvalue); \ dvalue = MIN(UINT_MAX, dvalue); \ *((unsigned int *) ptr) = ROUND(dvalue); \ break; \ case MI_PRIV_SIGNED : \ dvalue = MAX(INT_MIN, dvalue); \ dvalue = MIN(INT_MAX, dvalue); \ *((signed int *) ptr) = ROUND(dvalue); \ break; \ } \ break; \ case NC_FLOAT : \ dvalue = MAX(-FLT_MAX,dvalue); \ *((float *) ptr) = MIN(FLT_MAX,dvalue); \ break; \ case NC_DOUBLE : \ *((double *) ptr) = dvalue; \ break; \ case NC_NAT : \ MI_LOG_PKG_ERROR2(MI_ERR_NONNUMERIC, \ "Attempt to convert to NC_NAT from double"); \ dvalue = 0; \ break; \ } /**/ #define _(x) x /* For future gettext */ #endif minc-2.2.00/libsrc/minc_config.h0000644000265600003100000000075312027132662013347 00000000000000#ifndef _MINC_CONFIG_H_ #define _MINC_CONFIG_H_ #define MICFG_FORCE_V2 "MINC_FORCE_V2" #define MICFG_COMPRESS "MINC_COMPRESS" #define MICFG_CHUNKING "MINC_CHUNKING" #define MICFG_LOGFILE "MINC_LOGFILE" #define MICFG_LOGLEVEL "MINC_LOGLEVEL" #define MICFG_MAXBUF "MINC_MAX_FILE_BUFFER_KB" #define MICFG_MAXMEM "MINC_MAX_MEMORY_KB" extern int miget_cfg_bool(const char *); extern int miget_cfg_int(const char *); extern char * miget_cfg_str(const char *); #endif /* _MINC_CONFIG_H_ */ minc-2.2.00/libsrc/minc_error.h0000644000265600003100000000550612027132662013234 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_error.h @DESCRIPTION: File containing error codes for minc package. @GLOBALS : @CALLS : @CREATED : 17 Feburary, 2004 (Robert Vincent) @MODIFIED : * * $Log: minc_error.h,v $ * Revision 6.4 2008-04-11 05:15:00 rotor * * rewrote error code (Claude) to remove global defs that were * causing build problems with DYLIB on OSX * * Revision 6.3 2004/12/03 21:52:35 bert * Minor changes for Windows build * * Revision 6.2 2004/10/15 13:46:15 bert * Minor changes for Windows compatibility * * Revision 6.1 2004/04/27 15:42:47 bert * Define MINC logging codes * * @COPYRIGHT : Copyright 2004 Robert Vincent, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #ifndef _MINC_ERROR_H_ #define _MINC_ERROR_H_ 1 /* message levels */ #define MI_MSG_FATAL 0 #define MI_MSG_ERROR 1 #define MI_MSG_WARNING 2 #define MI_MSG_INFO 3 #define MI_MSG_DEBUG 4 #define MI_MSG_BASE (10000) typedef enum mimsgcode { MI_MSG_UNCMPFAIL = MI_MSG_BASE, MI_MSG_NOWRITECMP, MI_MSG_OPENFILE, MI_MSG_CREATEFILE, MI_MSG_CLOSEFILE, MI_MSG_FINDATTR, MI_MSG_ATTRNOTNUM, MI_MSG_READATTR, MI_MSG_NOMEMATTR, MI_MSG_CONVATTR, MI_MSG_ATTRNOTSCALAR, MI_MSG_ATTRNOTSTR, MI_MSG_WRITEATTR, MI_MSG_READVAR, MI_MSG_WRITEVAR, MI_MSG_FINDVAR, MI_MSG_ATTRCOUNT, MI_MSG_ATTRNAME, MI_MSG_COPYATTR, MI_MSG_VARINQ, MI_MSG_UNLIMDIM, MI_MSG_DIMINQ, MI_MSG_VARCONFLICT, MI_MSG_DIMDEF, MI_MSG_VARDEF, MI_MSG_VARMISMATCH, MI_MSG_VARDIFFSIZE, MI_MSG_VARCOUNT, MI_MSG_OUTPUTVAR, MI_MSG_COPYVAR, MI_MSG_VARNOTNUM, MI_MSG_OUTOFMEM, MI_MSG_ATTRNOTPTR, MI_MSG_VARNOTSTD, MI_MSG_DIMWIDTH, MI_MSG_MAXMINVARY, MI_MSG_SNH, MI_MSG_INTSIZE, MI_MSG_FLTSIZE, MI_MSG_TYPECLASS, MI_MSG_NOTIMPL, MI_MSG_BADTYPE, MI_MSG_OPENDSET, MI_MSG_READDSET, MI_MSG_WRITEDSET, MI_MSG_TOOMANYDIMS, MI_MSG_ICVATTACHED, MI_MSG_BADICV, MI_MSG_BADPROP, MI_MSG_ICVNOTATTACHED, MI_MSG_ICVCOORDS, MI_MSG_BADOP } mimsgcode_t; MNCAPI int milog_message(mimsgcode_t code, ...); #endif /* _MINC_ERROR_H_ not defined */ minc-2.2.00/libsrc/minc_private.h0000644000265600003100000000545512027132662013560 00000000000000 #ifndef MINC_PRIVATE_HEADER_FILE #define MINC_PRIVATE_HEADER_FILE /* ----------------------------- MNI Header ----------------------------------- @NAME : minc_private.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: The general include file for MINC routines. @METHOD : @GLOBALS : @CALLS : @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : * $Log: minc_private.h,v $ * Revision 6.4 2004-12-14 23:53:46 bert * Get rid of compilation warnings * * Revision 6.3 2004/10/15 13:47:31 bert * Minor changes for Windows compatibility * * Revision 6.2 2004/04/27 15:47:47 bert * #include minc_config.h and minc_error.h * * Revision 6.1 1999/10/19 14:45:09 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.1 1995/02/08 19:00:55 neelin * Removed include of math.h * * Revision 2.0 1994/09/28 10:38:07 neelin * Release of minc version 0.2 * * Revision 1.7 94/09/28 10:37:27 neelin * Pre-release * * Revision 1.6 93/10/06 10:00:30 neelin * Added include of memory.h for memcpy on SUNs. * * Revision 1.5 93/08/11 12:06:39 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @RCSID : $Header: /private-cvsroot/minc/libsrc/minc_private.h,v 6.4 2004-12-14 23:53:46 bert Exp $ MINC (MNI) ---------------------------------------------------------------------------- */ #if defined(_MSC_VER) /* If we are building on the Microsoft C compiler, we want to * explicitly export all public functions from the DLL */ #define MNCAPI __declspec(dllexport) #else #define MNCAPI #endif #include "config.h" #define _GNU_SOURCE 1 /* Include all BSD & GNU interfaces */ #include #include #include #include #include "minc.h" #include "minc_useful.h" #include "minc_basic.h" #include "minc_structures.h" #include "minc_routines.h" #include "minc_config.h" #include "minc_error.h" #endif minc-2.2.00/libsrc/minc_routines.h0000644000265600003100000001013612027132662013746 00000000000000#ifndef MINC_ROUTINES_HEADER_FILE #define MINC_ROUTINES_HEADER_FILE /* ----------------------------- MNI Header ----------------------------------- @NAME : minc_routines.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Provides prototypes for private and semiprivate MINC routines. @METHOD : @GLOBALS : @CALLS : @CREATED : August 28, 1992 (Peter Neelin) @MODIFIED : * $Log: minc_routines.h,v $ * Revision 6.4 2005-08-26 21:04:58 bert * Use #if rather than #ifdef with MINC2 symbol * * Revision 6.3 2004/12/14 23:53:46 bert * Get rid of compilation warnings * * Revision 6.2 2004/10/15 13:47:39 bert * Minor changes for Windows compatibility * * Revision 6.1 1999/10/19 14:45:10 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.2 1995/02/08 19:01:06 neelin * Moved private function declarations from minc_routines.h to appropriate file. * * Revision 2.1 1995/01/20 15:21:20 neelin * Added midecompress_file with ability to decompress only the header of a file. * * Revision 2.0 94/09/28 10:38:08 neelin * Release of minc version 0.2 * * Revision 1.9 94/09/28 10:37:29 neelin * Pre-release * * Revision 1.8 93/08/11 12:06:41 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @RCSID : $Header: /private-cvsroot/minc/libsrc/minc_routines.h,v 6.4 2005-08-26 21:04:58 bert Exp $ MINC (MNI) ---------------------------------------------------------------------------- */ /* MINC routines that should only be visible to the package (semiprivate) */ /* From minc_error.c */ SEMIPRIVATE int MI_save_routine_name(char *name); SEMIPRIVATE int MI_return(void); SEMIPRIVATE int MI_return_error(void); SEMIPRIVATE void MI_log_pkg_error2(int p1, char *p2); SEMIPRIVATE void MI_log_pkg_error3(int p1, char *p2, char *p3); SEMIPRIVATE void MI_log_sys_error1(char *p1); /* From value_conversion.c */ SEMIPRIVATE int MI_varaccess(int operation, int cdfid, int varid, long start[], long count[], nc_type datatype, int sign, void *values, int *bufsize_step, mi_icv_type *icvp); SEMIPRIVATE int MI_var_loop(int ndims, long start[], long count[], int value_size, int *bufsize_step, long max_buffer_size, void *caller_data, int (*action_func) (int, long [], long [], long, void *, void *)); SEMIPRIVATE int MI_get_sign_from_string(nc_type datatype, char *sign); SEMIPRIVATE int MI_convert_type(long number_of_values, nc_type intype, int insign, void *invalues, nc_type outtype, int outsign, void *outvalues, mi_icv_type *icvp); /* From image_conversion.c */ SEMIPRIVATE mi_icv_type *MI_icv_chkid(int icvid); #if MINC2 extern int hdf_var_declare(int fd, char *varnm, char *varpath, int ndims, hsize_t *sizes); extern int hdf_create(const char *path, int cmode, struct mi2opts *opts_ptr); extern int hdf_open(const char *path, int mode); extern int hdf_close(int fd); #endif /* MINC2 */ #endif minc-2.2.00/libsrc/minc_structures.h0000644000265600003100000002173512027132662014330 00000000000000#ifndef MINC_STRUCTURES_HEADER_FILE #define MINC_STRUCTURES_HEADER_FILE /* ----------------------------- MNI Header ----------------------------------- @NAME : minc_structures.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Defines structures for use by MINC routines @METHOD : @GLOBALS : @CALLS : @CREATED : August 28, 1992 (Peter Neelin) @MODIFIED : * $Log: minc_structures.h,v $ * Revision 6.1 1999-10-19 14:45:10 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/10 18:14:50 neelin * Fixed handling of invalid data when icv scale is zero. * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:38:09 neelin * Release of minc version 0.2 * * Revision 1.10 94/09/28 10:37:30 neelin * Pre-release * * Revision 1.9 93/08/11 12:06:42 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @RCSID : $Header: /private-cvsroot/minc/libsrc/minc_structures.h,v 6.1 1999-10-19 14:45:10 neelin Exp $ MINC (MNI) ---------------------------------------------------------------------------- */ /* Image conversion variable structure type */ typedef struct mi_icv_struct mi_icv_type; struct mi_icv_struct { /* semiprivate : fields available to the package */ int do_scale; /* Indicates to MI_convert_type that scaling should be done */ double scale; /* For scaling in MI_convert_type */ double offset; int do_dimconvert; /* Indicates that dimensional conversion function should be given */ int (*dimconvert_func) (int operation, mi_icv_type *icvp, long start[], long count[], void *values, long bufstart[], long bufcount[], void *buffer); int do_fillvalue; /* Indicates to MI_convert_type that fillvalue checking should be done */ double fill_valid_min; /* Range limits for fillvalue checking */ double fill_valid_max; /* private : fields available only to icv routines */ /* Fields that hold values passed by user */ nc_type user_type; /* Type to that user wants */ int user_typelen; /* Length of type in bytes */ int user_sign; /* Sign that user wants */ int user_do_range; /* Does the user want range scaling? */ double user_vmax; /* Range of values that user wants */ double user_vmin; int user_do_norm; /* Indicates that user wants value normalization */ int user_user_norm; /* If TRUE, user specifies range for norm, otherwise norm is taken from variable range */ char *user_maxvar; /* Name of MIimagemax variable */ char *user_minvar; /* Name of MIimagemin variable */ double user_imgmax; /* Range for normalization */ double user_imgmin; int user_do_dimconv; /* Indicates that user wants to do dimension conversion stuff */ int user_do_scalar; /* Indicates that user wants scalar fields */ int user_xdim_dir; /* Direction for x, y and z dimensions */ int user_ydim_dir; int user_zdim_dir; int user_num_imgdims; /* Number of image (fastest varying) dimensions */ long user_dim_size[MI_MAX_IMGDIMS]; /* Size of fastest varying dimensions for user */ int user_keep_aspect; /* Indicates that user wants to preserve the aspect ratio when resizing images */ int user_do_fillvalue; /* Indicates that user wants fillvalue checking to be done */ double user_fillvalue; /* Fillvalue that user wants */ /* Fields that hold values from real variable */ int cdfid; /* Id of cdf */ int varid; /* Id of variable */ int imgmaxid; /* Id of MIimagemax */ int imgminid; /* Id of Miimagemin */ int var_ndims; /* Number of dimensions of variable */ int var_dim[MAX_VAR_DIMS]; /* Dimensions of variable */ nc_type var_type; /* Variable type */ int var_typelen; /* Length of type in bytes */ int var_sign; /* Variable sign */ double var_vmax; /* Range of values in variable */ double var_vmin; int var_is_vector; /* Is this variable a vector field */ long var_vector_size; /* Size of vector dimension */ long var_dim_size[MI_MAX_IMGDIMS]; /* Size of image dimensions in variable */ /* Fields derived from user values and variable values */ int derv_usr_float; /* Are user or variable values floating point? */ int derv_var_float; double derv_imgmax; /* Range for normalization */ double derv_imgmin; int derv_firstdim; /* First dimension (counting from fastest, ie. backwards) over which MIimagemax or MIimagemin vary */ int derv_do_zero; /* Indicates if we should zero user's buffer on GETs */ int derv_do_bufsize_step; /* Indicates if we need to worry about bufsize_step */ int derv_bufsize_step[MAX_VAR_DIMS]; /* Array of convenient multiples for buffer allocation */ int derv_var_compress; /* Indicate need for compressing variable or */ int derv_usr_compress; /* user buffer */ int derv_dimconv_fastdim; /* Fastest varying dimensions for dimension conversion */ long derv_var_pix_num; /* Number of pixels to compress/expand for */ long *derv_var_pix_off; /* variable and user buffers, as well as */ long derv_usr_pix_num; /* pointers to arrays of offsets */ long *derv_usr_pix_off; long derv_icv_start[MAX_VAR_DIMS]; /* Space for storing parameters to */ long derv_icv_count[MAX_VAR_DIMS]; /* MI_icv_access */ /* Stuff that affects first user_num_imgdims (excluding any vector dimension) as image dimensions */ int derv_dim_flip[MI_MAX_IMGDIMS]; /* Flip dimension? */ int derv_dim_grow[MI_MAX_IMGDIMS]; /* Expand variable to fit user's array? */ int derv_dim_scale[MI_MAX_IMGDIMS]; /* Grow/shrink scale factor */ int derv_dim_off[MI_MAX_IMGDIMS]; /* Pixels to skip in user's image */ double derv_dim_step[MI_MAX_IMGDIMS]; /* Step, start for user's image (analogous to MIstep, MIstart) for first user_num_imgdims dims */ double derv_dim_start[MI_MAX_IMGDIMS]; }; /* Structure for passing values for MI_varaccess */ typedef struct { int operation; int cdfid; int varid; nc_type var_type, call_type; int var_sign, call_sign; int var_value_size, call_value_size; mi_icv_type *icvp; int do_scale; int do_dimconvert; int do_fillvalue; long *start, *count; void *values; } mi_varaccess_type; /* Structure for passing values for micopy_var_values */ typedef struct { int value_size; /* Size of each value */ int incdfid, outcdfid; /* Input and output cdf files */ int invarid, outvarid; /* Input and output variables */ } mi_vcopy_type; /* Structure for passing values for MI_icv_dimconvert */ typedef struct { int do_compress, do_expand; long end[MAX_VAR_DIMS]; long in_pix_num, out_pix_num; /* Variables for compressing/expanding */ long *in_pix_off, *out_pix_off; void *in_pix_first, *out_pix_first; void *in_pix_last, *out_pix_last; nc_type intype, outtype; /* Variable types and signs */ int insign, outsign; long buf_step[MAX_VAR_DIMS]; /* Step sizes for pointers */ long usr_step[MAX_VAR_DIMS]; long *istep, *ostep; void *istart, *ostart; /* Beginning of buffers */ } mi_icv_dimconv_type; #endif minc-2.2.00/libsrc/minc_useful.h0000644000265600003100000001216212027132662013402 00000000000000 #ifndef MINC_USEFUL_HEADER_FILE #define MINC_USEFUL_HEADER_FILE /* ----------------------------- MNI Header ----------------------------------- @NAME : minc_useful.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A set of macros and definitions useful for MINC routines. (derived from mni_def.h) @METHOD : @GLOBALS : @CALLS : @CREATED : July 15, 1991 David MacDonald @MODIFIED : * $Log: minc_useful.h,v $ * Revision 6.2 2004-10-15 13:47:55 bert * Minor changes for Windows compatibility * * Revision 6.1 1999/10/19 14:45:10 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/10 19:22:18 neelin * Removed redefinition of NULL and added pointer casts in appropriate places. * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:38:10 neelin * Release of minc version 0.2 * * Revision 1.7 94/09/28 10:37:31 neelin * Pre-release * * Revision 1.6 93/08/11 12:06:44 neelin * Added RCS logging in source. * July 29, 1992 Peter Neelin - changed name for MINC routines and added some macros @COPYRIGHT : Copyright 1993 David MacDonald and Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The authors and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @RCSID : $Header: /private-cvsroot/minc/libsrc/minc_useful.h,v 6.2 2004-10-15 13:47:55 bert Exp $ MINC (MNI) ---------------------------------------------------------------------------- */ /* ------------ define signed for vaxes ----------------- */ #if (defined(vax) && !defined(__STDC__)) #define signed #endif /* --------- define the prefixes to all functions ---------- */ #ifndef MNCAPI # define MNCAPI #endif #define PRIVATE static #define SEMIPRIVATE /* --------- define TRUE and FALSE ------------------------ */ #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* --------- macro to determine the size of a static array, e.g., int array[] = { 1, 3, 9, 5 }; ------------ */ #define SIZEOF_STATIC_ARRAY( array ) \ ( sizeof(array) / sizeof((array)[0])) /* --------- interpolate between a and b ------------------- */ #define INTERPOLATE( alpha, a, b ) ((a) + (alpha) * ((b) - (a))) /* --------- PI, and angles -------------------------------- */ #define PI M_PI /* from math.h */ #define DEG_TO_RAD (PI / 180.0) #define RAD_TO_DEG (180.0 / PI) /* --------- Absolute value, min, and max. Bear in mind that these may evaluate an expression multiple times, i.e., ABS( x - y ), and therefore may be inefficient, or incorrect, i.e, ABS( ++x ); ------------------ */ #define ABS( x ) ( ((x) > (0)) ? (x) : (-(x)) ) /* ---------- Round to nearest integer - must be cast to integer in order for rounding to take effect, and the cast must truncate towards zero - eg. i = (int) ROUND(x); Same caveats as ABS ------------------ */ #define ROUND( x ) ((x) + ( ((x) >= 0) ? 0.5 : (-0.5) ) ) #undef MAX #define MAX( x, y ) ( ((x) >= (y)) ? (x) : (y) ) #define MAX3( x, y, z ) MAX( x, MAX(y,z) ) #undef MIN #define MIN( x, y ) ( ((x) <= (y)) ? (x) : (y) ) #define MIN3( x, y, z ) MIN( x, MIN(y,z) ) /* --------- gets the address of a 2-d array element in a 1-d array ----- */ #define IJ( i, j, nj ) ( (i) * (nj) + (j) ) /* --------- gets the address of a 3-d array element in a 1-d array ----- */ #define IJK( i, j, k, nj, nk ) ( (k) + (nk) * ((j) + (nj) * (i)) ) /* --------- memory allocation macros -------------------------- */ #define MALLOC( n_items, type ) \ ( (type *) malloc( (size_t) (n_items) * sizeof(type) ) ) #define CALLOC( n_items, type ) \ ( (type *) calloc( (size_t) (n_items), sizeof(type) ) ) #define REALLOC( ptr, n_items, type ) \ ( (type *) realloc( (void *) ptr, (size_t) (n_items) * sizeof(type) ) ) #define FREE( ptr ) \ free( (void *) ptr ) /* --------- environment variables -------------------------- */ #ifdef sun char *getenv(); /* on suns, this declaration is not in stdlib.h */ #endif #define ENV_EXISTS( env ) ( getenv(env) != (char *) 0 ) /* --------- string macros -------------------------- */ #define STRINGS_EQUAL(str1,str2) (strcmp(str1,str2)==0) #endif minc-2.2.00/libsrc/minc_varlists.h0000644000265600003100000000513612027132662013751 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_varlists.h @DESCRIPTION: Contains lists of minc variables for use by routines in file minc_convenience.c. @METHOD : Note that lists should be NULL terminated. @CREATED : Peter Neelin (August 7, 1992) @MODIFIED : * $Log: minc_varlists.h,v $ * Revision 6.1 1999-10-19 14:45:11 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:38:12 neelin * Release of minc version 0.2 * * Revision 1.5 94/09/28 10:37:32 neelin * Pre-release * * Revision 1.4 93/08/11 12:06:45 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @RCSID : $Header: /private-cvsroot/minc/libsrc/minc_varlists.h,v 6.1 1999-10-19 14:45:11 neelin Exp $ MINC (MNI) ---------------------------------------------------------------------------- */ /* Variables containing list of standard dimension names and variable names */ /* List of dimension variables. Note that MIvector_dimension is not included since it should not have an associated variable. */ static char *dimvarlist[]={MIxspace, MIyspace, MIzspace, MItime, MItfrequency, MIxfrequency, MIyfrequency, MIzfrequency, NULL}; /* List of dimension width variables */ static char *dimwidthlist[]={MIxspace_width, MIyspace_width, MIzspace_width, MItime_width, MItfrequency_width, MIxfrequency_width, MIyfrequency_width, MIzfrequency_width, NULL}; /* List of variables */ static char *varlist[]={MIrootvariable, MIimage, MIimagemax, MIimagemin, MIpatient, MIstudy, MIacquisition, NULL}; minc-2.2.00/libsrc/type_limits.h0000644000265600003100000000377212027132662013442 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : type_limits.h @DESCRIPTION: Includes limits.h and float.h, undefining things that are defined in both to avoid errors from lint (on SGI). @METHOD : @CREATED : August 7, 1992 (Peter Neelin) @MODIFIED : * $Log: type_limits.h,v $ * Revision 6.1 1999-10-19 14:45:12 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:38:19 neelin * Release of minc version 0.2 * * Revision 1.5 94/09/28 10:37:33 neelin * Pre-release * * Revision 1.4 93/08/11 12:06:47 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @RCSID : $Header: /private-cvsroot/minc/libsrc/type_limits.h,v 6.1 1999-10-19 14:45:12 neelin Exp $ MINC (MNI) ---------------------------------------------------------------------------- */ #include /* Undefine those things that get redefined in float.h */ #ifdef FLT_DIG #undef FLT_DIG #endif #ifdef DBL_DIG #undef DBL_DIG #endif #ifdef DBL_MIN #undef DBL_MIN #endif #ifdef DBL_MAX #undef DBL_MAX #endif #include minc-2.2.00/libsrc/hdf_convenience.h0000644000265600003100000000444212027132662014210 00000000000000/* hdf_convenience.h */ /* DUMMY rootvariable ID */ #define MI_ROOTVARIABLE_ID (NC_MAX_VARS + 1) /* Impossible value */ /* HDF functions for compatibility layer. */ extern int hdf_varname(int fd, int varid, char *varnm); extern int hdf_varid(int fd, const char *varnm); extern int hdf_attget(int fd, int varid, const char *attnm, void *value); extern int hdf_attput(int fd, int varid, const char *attnm, nc_type val_typ, int val_len, void *val_ptr); extern int hdf_attdel(int fd, int varid, const char *attnm); extern int hdf_attinq(int fd, int varid, const char *attnm, nc_type *type_ptr, int *length_ptr); extern int hdf_attname(int fd, int varid, int attnum, char *name); extern int hdf_inquire(int fd, int *ndims_ptr, int *nvars_ptr, int *natts_ptr, int *unlimdim_ptr); extern int hdf_varinq(int fd, int varid, char *varnm_ptr, nc_type *type_ptr, int *ndims_ptr, int *dims_ptr, int *natts_ptr); extern int hdf_dimid(int fd, const char *dimnm); extern int hdf_diminq(int fd, int dimid, char *dimnm_ptr, long *len_ptr); extern int hdf_dimdef(int fd, const char *dimnm, long length); extern void hdf_enddef(int fd); extern int hdf_vardef(int fd, const char *varnm, nc_type vartype, int ndims, const int *dimids); extern int hdf_varget(int fd, int varid, const long *start_ptr, const long *count_ptr, void *val_ptr); extern int hdf_vargetg(int fd, int varid, const long *startp, const long *countp, const long *stridep, const long *imapp, void *valp); extern int hdf_varput(int fd, int varid, const long *start_ptr, const long *count_ptr, const void *val_ptr); extern int hdf_varput1(int fd, int varid, const long *mindex_ptr, const void *val_ptr); extern int hdf_varputg(int fd, int varid, const long *startp, const long *countp, const long *stridep, const long *imapp, const void *valp); extern int hdf_varsize(int fd, int varid, long *size_ptr); extern int hdf_dimrename(int fd, int dimid, const char *new_name); extern herr_t hdf_copy_attr(hid_t in_id, const char *attr_name, void *op_data); extern int hdf_open(const char *path, int mode); extern int hdf_create(const char *path, int mode, struct mi2opts *opts_ptr); extern int hdf_close(int fd); extern int hdf_access(const char *path); minc-2.2.00/libsrc/ParseArgv.man30000644000265600003100000004061712027132662013400 00000000000000'\" '\" Copyright 1990-1992 Regents of the University of California '\" Permission to use, copy, modify, and distribute this '\" documentation for any purpose and without fee is hereby '\" granted, provided that this notice appears in all copies. '\" The University of California makes no representations about '\" the suitability of this material for any purpose. It is '\" provided "as is" without express or implied warranty. '\" '\" Modified to be used without tk or tcl (Peter Neelin, November 30,1992) '\" Based on tk 2.3 file : '\" $Header: /private-cvsroot/minc/libsrc/ParseArgv.man3,v 6.1 2002-01-14 21:28:26 neelin Exp $ SPRITE (Berkeley) '\" .\" The definitions below are for supplemental macros used in Sprite .\" manual entries. .\" .\" .HS name section [date [version]] .\" Replacement for .TH in other man pages. See below for valid .\" section names. .\" .\" .AP type name in/out [indent] .\" Start paragraph describing an argument to a library procedure. .\" type is type of argument (int, etc.), in/out is either "in", "out", .\" or "in/out" to describe whether procedure reads or modifies arg, .\" and indent is equivalent to second arg of .IP (shouldn't ever be .\" needed; use .AS below instead) .\" .\" .AS [type [name]] .\" Give maximum sizes of arguments for setting tab stops. Type and .\" name are examples of largest possible arguments that will be passed .\" to .AP later. If args are omitted, default tab stops are used. .\" .\" .BS .\" Start box enclosure. From here until next .BE, everything will be .\" enclosed in one large box. .\" .\" .BE .\" End of box enclosure. .\" .\" .VS .\" Begin vertical sidebar, for use in marking newly-changed parts .\" of man pages. .\" .\" .VE .\" End of vertical sidebar. .\" .\" .DS .\" Begin an indented unfilled display. .\" .\" .DE .\" End of indented unfilled display. .\" '\" # Heading for Sprite man pages .de HS .if '\\$2'cmds' .TH \\$1 1 \\$3 \\$4 .if '\\$2'lib' .TH \\$1 3 \\$3 \\$4 .if '\\$2'tcl' .TH \\$1 3 \\$3 \\$4 .if '\\$2'tk' .TH \\$1 3 \\$3 \\$4 .if t .wh -1.3i ^B .nr ^l \\n(.l .ad b .. '\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ie !"\\$3"" \{\ .ta \\n()Au \\n()Bu \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. '\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. '\" # BS - start boxed text '\" # ^y = starting y location '\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. '\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. '\" # VS - start vertical sidebar '\" # ^Y = starting y location '\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. '\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. '\" # Special macro to handle page bottom: finish off current '\" # box/sidebar if in box/sidebar mode, then invoked standard '\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. '\" # DS - begin display .de DS .RS .nf .sp .. '\" # DE - end display .de DE .fi .RE .sp .5 .. .HS ParseArgv tk .BS .SH NAME ParseArgv \- process command-line options .SH SYNOPSIS \fB#include \fR .sp int .br \fBParseArgv\fR(\fIargcPtr, argv, argTable, flags\fR) .SH ARGUMENTS .AS ArgvInfo *argTable .AP int argcPtr in/out Pointer to number of arguments in argv; gets modified to hold number of unprocessed arguments that remain after the call. .AP char **argv in/out Command line arguments passed to main program. Modified to hold unprocessed arguments that remain after the call. .AP ArgvInfo *argTable in Array of argument descriptors, terminated by element with type ARGV_END. .AP int flags in If non-zero, then it specifies one or more flags that control the parsing of arguments. Different flags may be OR'ed together. .na The flags currently defined are ARGV_DONT_SKIP_FIRST_ARG, ARGV_NO_ABBREV, ARGV_NO_LEFTOVERS, ARGV_NO_DEFAULTS and ARGV_NO_PRINT. .ad .BE .SH DESCRIPTION .PP \fBParseArgv\fR processes an array of command-line arguments according to a table describing the kinds of arguments that are expected. Each of the arguments in \fIargv\fR is processed in turn: if it matches one of the entries in \fIargTable\fR, the argument is processed according to that entry and discarded. The arguments that do not match anything in \fIargTable\fR are copied down to the beginning of \fIargv\fR (retaining their original order) and returned to the caller. At the end of the call \fBParseArgv\fR sets \fI*argcPtr\fR to hold the number of arguments that are left in \fIargv\fR, and \fIargv[*argcPtr]\fR will hold the value NULL. Normally, \fBParseArgv\fR assumes that \fIargv[0]\fR is a command name, so it is treated like an argument that doesn't match \fIargTable\fR and returned to the caller; however, if the ARGV_DONT_SKIP_FIRST_ARG bit is set in \fIflags\fR then \fIargv[0]\fR will be processed just like the other elements of \fIargv\fR. .PP \fBParseArgv\fR normally returns the value FALSE (0). If an error occurs while parsing the arguments, then TRUE (1) is returned and \fBParseArgv\fR will print an error message on stderr. In the event of an error return, \fI*argvPtr\fR will not have been modified, but \fIargv\fR could have been partially modified. The possible causes of errors are explained below. .PP The \fIargTable\fR array specifies the kinds of arguments that are expected; each of its entries has the following structure: .DS .ta 2c \fBtypedef struct\fR { \fBchar\fR *\fIkey\fR; \fBint\fR \fItype\fR; \fBchar\fR *\fIsrc\fR; \fBchar\fR *\fIdst\fR; \fBchar\fR *\fIhelp\fR; \fB} ArgvInfo;\fR .DE .LP The \fIkey\fR field is a string such as ``\-display'' or ``\-bg'' that is compared with the values in \fIargv\fR. \fIType\fR indicates how to process an argument that matches \fIkey\fR (more on this below). \fISrc\fR and \fIdst\fR are additional values used in processing the argument. Their exact usage depends on \fItype\fR, but typically \fIsrc\fR indicates a value and \fIdst\fR indicates where to store the value. The \fBchar *\fR declarations for \fIsrc\fR and \fIdst\fR are placeholders: the actual types may be different. Lastly, \fIhelp\fR is a string giving a brief description of this option; this string is printed when users ask for help about command-line options. .PP When processing an argument in \fIargv\fR, \fBParseArgv\fR compares the argument to each of the \fIkey\fR's in \fIargTable\fR. \fBParseArgv\fR selects the first specifier whose \fIkey\fR matches the argument exactly, if such a specifier exists. Otherwise \fBParseArgv\fR selects a specifier for which the argument is a unique abbreviation. If the argument is a unique abbreviation for more than one specifier, then an error is returned. If there is no matching entry in \fIargTable\fR, then the argument is skipped and returned to the caller. .PP Once a matching argument specifier is found, \fBParseArgv\fR processes the argument according to the \fItype\fR field of the specifier. The argument that matched \fIkey\fR is called ``the matching argument'' in the descriptions below. As part of the processing, \fBParseArgv\fR may also use the next argument in \fIargv\fR after the matching argument, which is called ``the following argument''. The legal values for \fItype\fR, and the processing that they cause, are as follows: .TP \fBARGV_END\fR Marks the end of the table. The last entry in \fIargTable\fR must have this type; all of its other fields are ignored and it will never match any arguments. .TP \fBARGV_CONSTANT\fR \fISrc\fR is treated as an integer and \fIdst\fR is treated as a pointer to an integer. \fISrc\fR is stored at \fI*dst\fR. The matching argument is discarded. .TP \fBARGV_INT\fR The following argument must contain an integer string in the format accepted by \fBstrtol\fR (e.g. ``0'' and ``0x'' prefixes may be used to specify octal or hexadecimal numbers, respectively). \fIDst\fR is treated as a pointer to an integer; the following argument is converted to an integer value and stored at \fI*dst\fR. \fISrc\fR is treated as an integer count: if its value is greater than 1, then that many arguments are processed and \fIDst\fR is treated as an array pointer. The matching and following arguments are discarded from \fIargv\fR. .TP \fBARGV_FLOAT\fR The following argument must contain a floating-point number in the format accepted by \fBstrtol\fR. \fIDst\fR is treated as the address of an double-precision floating point value; the following argument is converted to a double-precision value and stored at \fI*dst\fR. \fISrc\fR is treated as an integer count: if its value is greater than 1, then that many arguments are processed and \fIDst\fR is treated as an array pointer. The matching and following arguments are discarded from \fIargv\fR. .TP \fBARGV_STRING\fR In this form, \fIdst\fR is treated as a pointer to a (char *); \fBParseArgv\fR stores at \fI*dst\fR a pointer to the following argument, and discards the matching and following arguments from \fIargv\fR. \fISrc\fR is treated as an integer count: if its value is greater than 1, then that many arguments are processed and \fIDst\fR is treated as an array pointer. .TP \fBARGV_HELP\fR When this kind of option is encountered, \fBParseArgv\fR uses the \fIhelp\fR fields of \fIargTable\fR to format a message describing all the valid arguments. The message is written on stderr and \fBParseArgv\fR returns TRUE. When this happens, the caller normally aborts. If the \fIkey\fR field of a ARGV_HELP specifier is NULL, then the specifier will never match any arguments; in this case the specifier simply provides extra documentation, which will be included when some other ARGV_HELP entry causes help information to be returned. .TP \fBARGV_REST\fR This option is used by programs or commands that allow the last several of their options to be the name and/or options for some other program. If a \fBARGV_REST\fR argument is found, then \fBParseArgv\fR doesn't process any of the remaining arguments; it returns them all at the beginning of \fIargv\fR (along with any other unprocessed arguments). In addition, \fBParseArgv\fR treats \fIdst\fR as the address of an integer value, and stores at \fI*dst\fR the index of the first of the \fBARGV_REST\fR options in the returned \fIargv\fR. This allows the program to distinguish the \fBARGV_REST\fR options from other unprocessed options that preceeded the \fBARGV_REST\fR. .TP \fBARGV_FUNC\fR For this kind of argument, \fIsrc\fR is treated as the address of a procedure, which is invoked to process the following argument. The procedure should have the following structure: .DS .ta 1c 2c 3c 4c 5c 6c \fBint\fI func(dst, key, nextArg) \fBchar\fR *\fIdst\fR; \fBchar\fR *\fIkey\fR; \fBchar\fR *\fInextArg\fR; { } .DE .IP The \fIdst\fR and \fIkey\fR parameters will contain the corresponding fields from the \fIargTable\fR entry, and \fInextArg\fR will point to the following argument from \fIargv\fR (or NULL if there aren't any more arguments left in \fIargv\fR). If \fIfunc\fR uses \fInextArg\fR (so that \fBParseArgv\fR should discard it), then it should return 1. Otherwise it should return 0 and \fBTkParseArgv\fR will process the following argument in the normal fashion. In either event the matching argument is discarded. .TP \fBARGV_GENFUNC\fR This form provides a more general procedural escape. It treats \fIsrc\fR as the address of a procedure, and passes that procedure all of the remaining arguments. The procedure should have the following form: .DS .ta 1c 2c 3c 4c 5c 6c \fBint\fI genfunc(dst, key, argc, argv) \fBchar\fR *\fIdst\fR; \fBchar\fR *\fIkey\fR; \fBint\fR \fIargc\fR; \fBchar\fR **\fIargv\fR; { } .DE .IP The \fIdst\fR and \fIkey\fR parameters will contain the corresponding fields from the \fIargTable\fR entry. \fIArgc\fR and \fIargv\fR refer to all of the options after the matching one. \fIGenfunc\fR should behave in a fashion similar to \fBParseArgv\fR: parse as many of the remaining arguments as it can, then return any that are left by compacting them to the beginning of \fIargv\fR (starting at \fIargv\fR[0]). \fIGenfunc\fR should return a count of how many arguments are left in \fIargv\fR; \fBParseArgv\fR will process them. If \fIgenfunc\fR encounters an error then it should print an error message on stderr, and return -1; when this happens \fBParseArgv\fR will abort its processing and return TRUE. .SH "FLAGS" .IP \fBARGV_DONT_SKIP_FIRST_ARG\fR \fBParseArgv\fR normally treats \fIargv[0]\fR as a program or command name, and returns it to the caller just as if it hadn't matched \fIargTable\fR. If this flag is given, then \fIargv[0]\fR is not given special treatment. .IP \fBARGV_NO_ABBREV\fR Normally, \fBParseArgv\fR accepts unique abbreviations for \fIkey\fR values in \fIargTable\fR. If this flag is given then only exact matches will be acceptable. .IP \fBARGV_NO_LEFTOVERS\fR Normally, \fBParseArgv\fR returns unrecognized arguments to the caller. If this bit is set in \fIflags\fR then \fBParseArgv\fR will return an error if it encounters any argument that doesn't match \fIargTable\fR. The only exception to this rule is \fIargv[0]\fR, which will be returned to the caller with no errors as long as ARGV_DONT_SKIP_FIRST_ARG isn't specified. .IP \fBARGV_NO_DEFAULTS\fR Normally, \fBParseArgv\fR searches an internal table of standard argument specifiers in addition to \fIargTable\fR. If this bit is set in \fIflags\fR, then \fBParseArgv\fR will use only \fIargTable\fR and not its default table. .IP \fBARGV_NO_PRINT\fR Normally, \fBParseArgv\fR prints error message on stderr. If this bit is set in \fIflags\fR, then \fBParseArgv\fR will not print any error messages. .SH EXAMPLE .PP Here is an example definition of an \fIargTable\fR and some sample command lines that use the options. Note the effect on \fIargc\fR and \fIargv\fR; arguments processed by \fBParseArgv\fR are eliminated from \fIargv\fR, and \fIargc\fR is updated to reflect reduced number of arguments. .DS L \fC/* * Define and set default values for globals. */ int debugFlag = 0; int numReps = 100; char defaultFileName[] = "out"; char *fileName = defaultFileName; Boolean exec = FALSE; /* * Define option descriptions. */ ArgvInfo argTable[] = { {"-X", ARGV_CONSTANT, (char *) 1, (char *) &debugFlag, "Turn on debugging printfs"}, {"-N", ARGV_INT, (char *) NULL, (char *) &numReps, "Number of repetitions"}, {"-of", ARGV_STRING, (char *) NULL, (char *) &fileName, "Name of file for output"}, {"x", ARGV_REST, (char *) NULL, (char *) &exec, "File to exec, followed by any arguments (must be last argument)."}, {(char *) NULL, ARGV_END, (char *) NULL, (char *) NULL, (char *) NULL} }; main(argc, argv) int argc; char *argv[]; { \&... if (ParseArgv(&argc, argv, argTable, 0)) { exit(1); } /* * Remainder of the program. */ }\fR .DE .PP Note that default values can be assigned to variables named in \fIargTable\fR: the variables will only be overwritten if the particular arguments are present in \fIargv\fR. Here are some example command lines and their effects. .DS \fCprog -N 200 infile # just sets the numReps variable to 200 prog -of out200 infile # sets fileName to reference "out200" prog -XN 10 infile # sets the debug flag, also sets numReps\fR .DE In all of the above examples, \fIargc\fR will be set by \fBParseArgv\fR to 2, \fIargv\fR[0] will be ``prog'', \fIargv\fR[1] will be ``infile'', and \fIargv\fR[2] will be NULL. .SH KEYWORDS arguments, command line, options minc-2.2.00/libsrc/ParseArgv.c0000644000265600003100000003324212030075003012745 00000000000000/* * ParseArgv.c -- * * This file contains a procedure that handles table-based * argv-argc parsing. * * Copyright 1990 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * * * This file has been modified to not rely on tcl, tk or X11. * Based on tkArgv.c from tk2.3 : * * Modifications by Peter Neelin (November 27, 1992) */ #include "config.h" #include "minc_private.h" #include #include #include #include #include #include /* * Default table of argument descriptors. These are normally available * in every application. */ static ArgvInfo defaultTable[] = { {"-help", ARGV_HELP, (char *) NULL, (char *) NULL, "Print summary of command-line options and abort"}, {"-version", ARGV_VERSION, (char *) NULL, (char *) NULL, "Print version number of program and exit"}, {NULL, ARGV_END, (char *) NULL, (char *) NULL, (char *) NULL} }; /* * Forward declarations for procedures defined in this file: */ static void PrintUsage _ANSI_ARGS_((ArgvInfo *argTable, int flags)); static void PrintVersion(ArgvInfo *argTable); /* *---------------------------------------------------------------------- * * ParseArgv -- * * Process an argv array according to a table of expected * command-line options. See the manual page for more details. * * Results: * The return value is a Boolean value with non-zero indicating an * error. * If an error occurs then an error message is printed on stderr. * Under normal conditions, both *argcPtr and *argv are modified * to return the arguments that couldn't be processed here (they * didn't match the option table, or followed an ARGV_REST * argument). * * Side effects: * *---------------------------------------------------------------------- */ int ParseArgv(argcPtr, argv, argTable, flags) int *argcPtr; /* Number of arguments in argv. Modified * to hold # args left in argv at end. */ char **argv; /* Array of arguments. Modified to hold * those that couldn't be processed here. */ ArgvInfo *argTable; /* Array of option descriptions */ int flags; /* Or'ed combination of various flag bits, * such as ARGV_NO_DEFAULTS. */ { register ArgvInfo *infoPtr; /* Pointer to the current entry in the * table of argument descriptions. */ ArgvInfo *matchPtr; /* Descriptor that matches current argument. */ char *curArg; /* Current argument */ register char c; /* Second character of current arg (used for * quick check for matching; use 2nd char. * because first char. will almost always * be '-'). */ int srcIndex; /* Location from which to read next argument * from argv. */ int dstIndex; /* Index into argv to which next unused * argument should be copied (never greater * than srcIndex). */ int argc; /* # arguments in argv still to process. */ int length; /* Number of characters in current argument. */ int nargs; /* Number of following arguments to get. */ int i; /* Macro to optionally print errors */ #define FPRINTF if (!(flags&ARGV_NO_PRINT)) (void) fprintf if (flags & ARGV_DONT_SKIP_FIRST_ARG) { srcIndex = dstIndex = 0; argc = *argcPtr; } else { srcIndex = dstIndex = 1; argc = *argcPtr-1; } while (argc > 0) { curArg = argv[srcIndex]; srcIndex++; argc--; c = curArg[1]; length = strlen(curArg); /* * Loop throught the argument descriptors searching for one with * the matching key string. If found, leave a pointer to it in * matchPtr. */ matchPtr = NULL; for (i = 0; i < 2; i++) { if (i == 0) { infoPtr = argTable; } else { infoPtr = defaultTable; } for (; infoPtr->type != ARGV_END; infoPtr++) { if (infoPtr->key == NULL) { continue; } if ((infoPtr->key[1] != c) || (strncmp(infoPtr->key, curArg, length) != 0)) { continue; } if (infoPtr->key[length] == 0) { matchPtr = infoPtr; goto gotMatch; } if (flags & ARGV_NO_ABBREV) { continue; } if (matchPtr != NULL) { FPRINTF(stderr, "ambiguous option \"%s\"\n", curArg); return TRUE; } matchPtr = infoPtr; } } if (matchPtr == NULL) { /* * Unrecognized argument. Just copy it down, unless the caller * prefers an error to be registered. */ if (flags & ARGV_NO_LEFTOVERS) { FPRINTF(stderr, "unrecognized argument \"%s\"\n", curArg); } argv[dstIndex] = curArg; dstIndex++; continue; } /* * Take the appropriate action based on the option type */ gotMatch: infoPtr = matchPtr; switch (infoPtr->type) { case ARGV_CONSTANT: *((int *) infoPtr->dst) = (intptr_t) infoPtr->src; break; case ARGV_INT: nargs = (intptr_t) infoPtr->src; if (nargs<1) nargs=1; for (i=0; idst)+i) = strtol(argv[srcIndex], &endPtr, 0); if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { FPRINTF(stderr, "expected integer argument for \"%s\" but got \"%s\"", infoPtr->key, argv[srcIndex]); return TRUE; } srcIndex++; argc--; } } break; case ARGV_LONG: nargs = (intptr_t) infoPtr->src; if (nargs<1) nargs=1; for (i=0; idst)+i) = strtol(argv[srcIndex], &endPtr, 0); if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { FPRINTF(stderr, "expected integer argument for \"%s\" but got \"%s\"", infoPtr->key, argv[srcIndex]); return TRUE; } srcIndex++; argc--; } } break; case ARGV_STRING: nargs = (intptr_t) infoPtr->src; if (nargs<1) nargs=1; for (i=0; idst)+i) = argv[srcIndex]; srcIndex++; argc--; } } break; case ARGV_REST: *((int *) infoPtr->dst) = dstIndex; goto argsDone; case ARGV_FLOAT: nargs = (intptr_t) infoPtr->src; if (nargs<1) nargs=1; for (i=0; idst)+i) = strtod(argv[srcIndex], &endPtr); if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { FPRINTF(stderr, "expected floating-point argument for \"%s\" but got\"%s\"\n", infoPtr->key, argv[srcIndex]); return TRUE; } srcIndex++; argc--; } } break; case ARGV_FUNC: { int (*handlerProc)(); handlerProc = (int (*)())infoPtr->src; if ((*handlerProc)(infoPtr->dst, infoPtr->key, argv[srcIndex])) { srcIndex += 1; argc -= 1; } break; } case ARGV_GENFUNC: { int (*handlerProc)(); handlerProc = (int (*)())infoPtr->src; argc = (*handlerProc)(infoPtr->dst, infoPtr->key, argc, argv+srcIndex); if (argc < 0) { return TRUE; } break; } case ARGV_HELP: PrintUsage (argTable, flags); return TRUE; case ARGV_VERSION: PrintVersion(argTable); return FALSE; default: FPRINTF(stderr, "bad argument type %d in ArgvInfo", infoPtr->type); return TRUE; } } /* * If we broke out of the loop because of an OPT_REST argument, * copy the remaining arguments down. */ argsDone: while (argc) { argv[dstIndex] = argv[srcIndex]; srcIndex++; dstIndex++; argc--; } argv[dstIndex] = (char *) NULL; *argcPtr = dstIndex; return FALSE; missingArg: FPRINTF(stderr, "\"%s\" option requires an additional argument\n", curArg); return TRUE; } /* *---------------------------------------------------------------------- * * PrintUsage -- * * Generate a help string describing command-line options. * * Results: * Prints on stderr (unless ARGV_NO_PRINT is specified in flags) * a help string describing all the options in argTable, plus all those * in the default table unless ARGV_NO_DEFAULTS is * specified in flags. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PrintUsage(argTable, flags) ArgvInfo *argTable; /* Array of command-specific argument * descriptions. */ int flags; /* If the ARGV_NO_DEFAULTS bit is set * in this word, then don't generate * information for default options. */ { register ArgvInfo *infoPtr; int width, i, j, numSpaces; #define NUM_SPACES 20 static char spaces[] = " "; /* char tmp[30]; */ int nargs; /* Macro to optionally print errors */ #define FPRINTF if (!(flags&ARGV_NO_PRINT)) (void) fprintf /* * First, compute the width of the widest option key, so that we * can make everything line up. */ width = 4; for (i = 0; i < 2; i++) { for (infoPtr = i ? defaultTable : argTable; infoPtr->type != ARGV_END; infoPtr++) { int length; if (infoPtr->key == NULL) { continue; } length = strlen(infoPtr->key); if (length > width) { width = length; } } } FPRINTF(stderr, "Command-specific options:"); for (i = 0; ; i++) { for (infoPtr = i ? defaultTable : argTable; infoPtr->type != ARGV_END; infoPtr++) { if (infoPtr->type == ARGV_VERINFO) { continue; } if ((infoPtr->type == ARGV_HELP) && (infoPtr->key == NULL)) { FPRINTF(stderr, "\n%s", infoPtr->help); continue; } FPRINTF(stderr, "\n %s:", infoPtr->key); numSpaces = width + 1 - strlen(infoPtr->key); while (numSpaces > 0) { if (numSpaces >= NUM_SPACES) { FPRINTF(stderr, "%s",spaces); } else { FPRINTF(stderr, "%s",spaces+NUM_SPACES-numSpaces); } numSpaces -= NUM_SPACES; } FPRINTF(stderr, "%s",infoPtr->help); switch (infoPtr->type) { case ARGV_INT: { FPRINTF(stderr, "\n\t\tDefault value:"); nargs = (intptr_t) infoPtr->src; if (nargs<1) nargs=1; for (j=0; jdst)+j)); } break; } case ARGV_FLOAT: { FPRINTF(stderr, "\n\t\tDefault value:"); nargs = (intptr_t) infoPtr->src; if (nargs<1) nargs=1; for (j=0; jdst)+j)); } break; } case ARGV_STRING: { char *string; nargs = (intptr_t) infoPtr->src; if (nargs<1) nargs=1; string = *((char **) infoPtr->dst); if ((nargs==1) && (string == NULL)) break; for (j=0; jdst)+j); if (string != NULL) { FPRINTF(stderr, " \"%s\"", string); } else { FPRINTF(stderr, " \"%s\"", string); } } break; } default: { break; } } } if ((flags & ARGV_NO_DEFAULTS) || (i > 0)) { break; } FPRINTF(stderr, "\nGeneric options for all commands:"); } FPRINTF(stderr, "\n"); } static void PrintVersion(ArgvInfo *argTable) { char *versionStr = VERSION; for ( ; argTable->type != ARGV_END; argTable++) { if (argTable->type == ARGV_VERINFO) { /* Version information found? */ if (argTable->src != NULL) { versionStr = argTable->src; break; } } } printf("program: %s\n", versionStr); printf("libminc: %s\n", miget_version()); printf("netcdf : %s\n", nc_inq_libvers()); #if MINC2 { unsigned int major, minor, release; H5get_libversion(&major, &minor, &release); printf("HDF5 : %d.%d.%d\n", major, minor, release); } #endif exit(0); } minc-2.2.00/libsrc/read_file_names.c0000644000265600003100000000524412027132662014164 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "read_file_names.h" #define FILE_NAME_ALLOC_SIZE 10 #define FILE_PATH_MAX 2046 /* ----------------------------- MNI Header ----------------------------------- @NAME : read_file_names @INPUT : filelist - name of file from which to read names @OUTPUT : num_files - number of files read in @RETURNS : Pointer to a NULL-terminated array of file names @DESCRIPTION: Reads in a list of file names from file filelist or stdin if "-" is specified. Returns NULL if an error occurs. If no error occurs, then a pointer to an empty array is returned and num_files is zero. @METHOD : @GLOBALS : @CALLS : @CREATED : March 8, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ char **read_file_names(char *filelist, int *num_files) { char **files; int array_size; int nfiles; FILE *fp; char line[FILE_PATH_MAX+1]; int length; /* Open the file */ if (strcmp(filelist, "-") == 0) { fp = stdin; } else { fp = fopen(filelist, "r"); if (fp == NULL) { (void) fprintf(stderr, "Error opening file \"%s\"\n", filelist); return NULL; } } /* Allocate an initial array and NULL-terminate it */ array_size = FILE_NAME_ALLOC_SIZE; files = malloc(sizeof(*files) * array_size); if (files == NULL) { (void) fprintf(stderr, "Error allocating memory\n"); return NULL; } nfiles = 0; files[nfiles] = NULL; /* Read in file names */ while (fgets(line, sizeof(line)/sizeof(line[0]), fp) != NULL) { /* Remove a trailing newline and check that there is a name */ length = strlen(line); if ((length > 0) && (line[length-1] == '\n')) { line[length-1] = '\0'; length--; } if (length == 0) continue; /* Make room for names if needed */ while (nfiles >= array_size-1) { array_size += FILE_NAME_ALLOC_SIZE; files = realloc(files, sizeof(*files) * array_size); if (files == NULL) { (void) fprintf(stderr, "Error allocating memory\n"); return NULL; } } /* Save the name, making sure that the list is NULL-terminated */ files[nfiles] = strdup(line); if (files[nfiles] == NULL) { (void) fprintf(stderr, "Error allocating memory\n"); return NULL; } nfiles++; files[nfiles] = NULL; } /* Close the file */ (void) fclose(fp); /* Return the number of files */ *num_files = nfiles; return files; } minc-2.2.00/libsrc/dim_conversion.c0000644000265600003100000011426112027132662014105 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : dim_conversion.c @DESCRIPTION: File of functions to do dimension conversion for image conversion variables (icv). These variables allow conversion of netcdf variables (the MINC image variable, in particular) to a form more convenient for a program. @METHOD : Routines included in this file : public : miicv_attach private : MI_icv_get_dim MI_get_dim_flip MI_get_dim_scale MI_get_dim_bufsize_step MI_icv_get_dim_conversion MI_icv_dimconvert MI_icv_dimconv_init @CREATED : September 9, 1992. (Peter Neelin) @MODIFIED : * $Log: dim_conversion.c,v $ * Revision 6.6 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.5 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.4 2004/10/15 13:44:52 bert * Minor changes for Windows compatibility * * Revision 6.3 2003/11/14 16:52:24 stever * More last-minute fixes. * * Revision 6.2 2003/09/18 16:16:15 bert * Use standard labs() and fabs() instead of our private macros * * Revision 6.1 1999/10/19 14:45:07 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.1 1997/04/10 18:14:50 neelin * Fixed handling of invalid data when icv scale is zero. * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.3 1995/02/08 19:14:44 neelin * More changes for irix 5 lint. * * Revision 2.2 1995/02/08 19:01:06 neelin * Moved private function declarations from minc_routines.h to appropriate file. * * Revision 2.1 1994/11/02 09:42:37 neelin * Fixed conversion of vector to scalar (old code simply returned the first * component of the vector - now averaging is done properly). * * Revision 2.0 94/09/28 10:37:52 neelin * Release of minc version 0.2 * * Revision 1.11 94/09/28 10:37:35 neelin * Pre-release * * Revision 1.10 94/07/05 15:31:07 neelin * Assume that MIstep is positive if it is not found (for flipping dimensions). * * Revision 1.9 94/03/16 10:30:00 neelin * Changed default MI_ICV_STEP: if not found use 1.0 (and 0.0 for start). * * Revision 1.8 93/08/11 12:06:03 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #include #include /* Private functions */ PRIVATE int MI_icv_get_dim(mi_icv_type *icvp, int cdfid, int varid); PRIVATE int MI_get_dim_flip(mi_icv_type *icvp, int cdfid, int dimvid[], int subsc[]); PRIVATE int MI_get_dim_scale(mi_icv_type *icvp, int cdfid, int dimvid[]); PRIVATE int MI_get_dim_bufsize_step(mi_icv_type *icvp, int subsc[]); PRIVATE int MI_icv_get_dim_conversion(mi_icv_type *icvp, int subsc[]); PRIVATE int MI_icv_dimconvert(int operation, mi_icv_type *icvp, long start[], long count[], void *values, long bufstart[], long bufcount[], void *buffer); PRIVATE int MI_icv_dimconv_init(int operation, mi_icv_type *icvp, mi_icv_dimconv_type *dcp, long start[], long count[], void *values, long bufstart[], long bufcount[], void *buffer); /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_attach @INPUT : icvid - icv id cdfid - cdf file id varid - cdf variable id @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Attaches an open cdf file and variable to an image conversion variable for subsequent access through miicvget and miicvput. File must be in data mode. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 9, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_attach(int icvid, int cdfid, int varid) { mi_icv_type *icvp; /* Pointer to icv structure */ long size_diff, user_dim_size; int idim; MI_SAVE_ROUTINE_NAME("miicv_attach"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN_ERROR(MI_ERROR); /* Call routine to set variables for everything except dimension conversion */ {MI_CHK_ERR(miicv_ndattach(icvid, cdfid, varid))} /* Check to see if we need to worry about dimension conversion */ if (!icvp->user_do_dimconv) { MI_RETURN(MI_NOERROR); } /* Reset cdfid and varid in icv structure in case something goes wrong in dimension conversion calculations */ icvp->cdfid = MI_ERROR; icvp->varid = MI_ERROR; /* Get dimensions info */ {MI_CHK_ERR(MI_icv_get_dim(icvp, cdfid, varid))} /* Set the do_dimconvert field of icv structure We do dimension conversion if any dimension needs flipping, scaling or offset, or if we have to convert from vector to scalar. */ icvp->do_dimconvert = (icvp->user_do_scalar && icvp->var_is_vector); for (idim=0; idimuser_num_imgdims; idim++) { if (icvp->derv_dim_flip[idim] || (icvp->derv_dim_scale[idim] != 1) || (icvp->derv_dim_off[idim] != 0)) icvp->do_dimconvert = TRUE; } icvp->dimconvert_func = MI_icv_dimconvert; /* Check if we have to zero user's buffer on GETs */ icvp->derv_do_zero = FALSE; for (idim=0; idimuser_num_imgdims; idim++) { user_dim_size = ((icvp->user_dim_size[idim]<=0) ? icvp->var_dim_size[idim] : icvp->user_dim_size[idim]); if (icvp->derv_dim_grow[idim]) size_diff = user_dim_size - icvp->var_dim_size[idim] * icvp->derv_dim_scale[idim]; else size_diff = user_dim_size - 1 - (icvp->var_dim_size[idim] - 1) / icvp->derv_dim_scale[idim]; if ((icvp->derv_dim_off[idim]!=0) || (size_diff!=0)) icvp->derv_do_zero = TRUE; } /* Set the cdfid and varid fields */ icvp->cdfid = cdfid; icvp->varid = varid; MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_dim @INPUT : icvp - pointer to icv structure cdfid - cdf file id varid - variable id @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets dimension info for the icv @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_get_dim(mi_icv_type *icvp, int cdfid, int varid) /* ARGSUSED */ { int oldncopts; /* For saving value of ncopts */ char dimname[MAX_NC_NAME]; /* Dimensions name */ int idim; /* Looping counter for fastest image dims */ int subsc[MI_MAX_IMGDIMS]; /* Subscripts for fastest image dims */ int dimvid[MI_MAX_IMGDIMS]; /* Variable ids for dimensions */ MI_SAVE_ROUTINE_NAME("MI_icv_get_dim"); /* Check that the variable has at least icvp->user_num_imgdims dimensions */ if (icvp->var_ndims < icvp->user_num_imgdims) { MI_LOG_PKG_ERROR2(MI_ERR_TOOFEWDIMS, "Variable has too few dimensions to be an image"); MI_RETURN_ERROR(MI_ERROR); } /* Check the first dimensions of the variable */ MI_CHK_ERR(ncdiminq(cdfid, icvp->var_dim[icvp->var_ndims-1], dimname, &(icvp->var_vector_size))) icvp->var_is_vector = STRINGS_EQUAL(dimname, MIvector_dimension); /* Check that the variable has at least icvp->user_num_imgdims+1 dimensions if it is a vector field */ if (icvp->var_is_vector && (icvp->var_ndims < icvp->user_num_imgdims+1)) { MI_LOG_PKG_ERROR2(MI_ERR_TOOFEWDIMS, "Variable has too few dimensions to be an image"); MI_RETURN_ERROR(MI_ERROR); } /* Check for dimension flipping and get dimension sizes */ /* Get subscripts for first icvp->user_num_imgdims dimensions */ subsc[0] = (icvp->var_is_vector) ? icvp->var_ndims-2 : icvp->var_ndims-1; for (idim=1; idim < icvp->user_num_imgdims; idim++) subsc[idim]=subsc[idim-1]-1; /* Get dimension variable ids */ for (idim=0; idim < icvp->user_num_imgdims; idim++) { {MI_CHK_ERR(ncdiminq(cdfid, icvp->var_dim[subsc[idim]], dimname, &(icvp->var_dim_size[idim])))}; oldncopts = ncopts; ncopts = 0; dimvid[idim] = ncvarid(cdfid, dimname); ncopts = oldncopts; } /* Check for flipping */ {MI_CHK_ERR(MI_get_dim_flip(icvp, cdfid, dimvid, subsc))} /* Check for scaling of dimension */ {MI_CHK_ERR(MI_get_dim_scale(icvp, cdfid, dimvid))} /* Check for variable buffer size increments */ {MI_CHK_ERR(MI_get_dim_bufsize_step(icvp, subsc))} /* Get information for dimension conversion */ {MI_CHK_ERR(MI_icv_get_dim_conversion(icvp, subsc))} MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_dim_flip @INPUT : icvp - icv pointer cdfid - cdf file id dimvid - variable id subsc - array of dimension subscripts for fastest varying dimensions @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Checks for flipping of icv. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 1, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_get_dim_flip(mi_icv_type *icvp, int cdfid, int dimvid[], int subsc[]) { int oldncopts; /* For saving value of ncopts */ char dimname[MAX_NC_NAME]; /* Dimensions name */ int dim_dir; /* Desired direction for current dimension */ double dimstep; /* Dimension step size (and direction) */ int idim; MI_SAVE_ROUTINE_NAME("MI_get_dim_flip"); /* Loop through fast dimensions */ for (idim=0; idim < icvp->user_num_imgdims; idim++) { /* Get name of the dimension */ {MI_CHK_ERR(ncdiminq(cdfid, icvp->var_dim[subsc[idim]], dimname, NULL))} /* Should we look for dimension flipping? */ icvp->derv_dim_flip[idim]=FALSE; if (STRINGS_EQUAL(dimname, MIxspace) || STRINGS_EQUAL(dimname, MIxfrequency)) dim_dir = icvp->user_xdim_dir; else if (STRINGS_EQUAL(dimname, MIyspace) || STRINGS_EQUAL(dimname, MIyfrequency)) dim_dir = icvp->user_ydim_dir; else if (STRINGS_EQUAL(dimname, MIzspace) || STRINGS_EQUAL(dimname, MIzfrequency)) dim_dir = icvp->user_zdim_dir; else dim_dir = MI_ICV_ANYDIR; /* Look for variable corresponding to dimension */ if (dim_dir != MI_ICV_ANYDIR) { /* Look for flipping? */ /* Get the value of the MIstep attribute to determine whether flipping is needed. Assume that direction is positive if no step is provided. */ dimstep = 1.0; if (dimvid[idim] != MI_ERROR) { /* if dimension exists */ oldncopts = ncopts; ncopts = 0; (void) miattget1(cdfid, dimvid[idim], MIstep, NC_DOUBLE, &dimstep); ncopts = oldncopts; } /* if dimension exists */ if (dim_dir == MI_ICV_POSITIVE) icvp->derv_dim_flip[idim] = (dimstep<0.0); else if (dim_dir == MI_ICV_NEGATIVE) icvp->derv_dim_flip[idim] = (dimstep>0.0); } /* if look for flipping */ } /* for each dimension */ MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_dim_scale @INPUT : icvp - icv pointer cdfid - cdf file id dimvid - dimension variable id @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Checks for scaling of images @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 1, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_get_dim_scale(mi_icv_type *icvp, int cdfid, int dimvid[]) { int oldncopts; /* For saving value of ncopts */ int min_grow, dim_grow; int min_scale, dim_scale; double dimstep, dimstart; int idim; long user_dim_size; MI_SAVE_ROUTINE_NAME("MI_get_dim_scale"); /* Loop through dimensions, calculating scale and looking for smallest one. For each dimension, check to see if we need to shrink or grow the image. (This is get-oriented: grow is TRUE if the variable dimension has to be expanded to fit the user's dimensions). */ for (idim=0; idim < icvp->user_num_imgdims; idim++) { /* Check to see if we user wants resize */ if (icvp->user_dim_size[idim] <= 0) { icvp->derv_dim_grow[idim]=TRUE; icvp->derv_dim_scale[idim]=1; } else { /* Check for growing or shrinking */ icvp->derv_dim_grow[idim] = (icvp->var_dim_size[idim] <= icvp->user_dim_size[idim]); /* If growing */ if (icvp->derv_dim_grow[idim]) { /* Get scale so that whole image fits in user array */ icvp->derv_dim_scale[idim] = icvp->user_dim_size[idim] / icvp->var_dim_size[idim]; } /* Otherwise, shrinking. Things are complicated by the fact that the external variable must fit completely in the user's array */ else { icvp->derv_dim_scale[idim] = 1 + (icvp->var_dim_size[idim] - 1) / icvp->user_dim_size[idim]; } } /* if user wants resizing */ /* Check for smallest scale */ if (idim==0) { min_grow = icvp->derv_dim_grow[idim]; min_scale = icvp->derv_dim_scale[idim]; } else { dim_grow = icvp->derv_dim_grow[idim]; dim_scale = icvp->derv_dim_scale[idim]; /* Check for one of three conditions : (1) smallest so far is growing, but this dim is shrinking (2) both are growing and this dim has smaller scale (3) both are shrinking and this dim has larger scale */ if ((min_grow && !dim_grow) || ((min_grow && dim_grow) && (min_scale > dim_scale)) || ((!min_grow && !dim_grow) && (min_scale < dim_scale))) { min_grow = dim_grow; min_scale = dim_scale; } } /* if not first dim */ } /* for each dimension, get scale */ /* Loop through dimensions, resetting scale if needed, setting offset and pixel step and start */ for (idim=0; idim < icvp->user_num_imgdims; idim++) { /* Check for aspect ratio */ if (icvp->user_keep_aspect) { icvp->derv_dim_grow[idim] = min_grow; icvp->derv_dim_scale[idim] = min_scale; } /* Get user's buffer size */ user_dim_size = ((icvp->user_dim_size[idim]<=0) ? icvp->var_dim_size[idim] : icvp->user_dim_size[idim]); /* Set offset of variable into user's image */ /* If growing */ if (icvp->derv_dim_grow[idim]) { /* Calculate remainder and split it in half */ icvp->derv_dim_off[idim] = ( user_dim_size - icvp->var_dim_size[idim] * icvp->derv_dim_scale[idim] ) / 2; } /* Otherwise, shrinking. Things are complicated by the fact that the external variable must fit completely in the user's array */ else { /* Calculate remainder and split it in half */ icvp->derv_dim_off[idim] = ( user_dim_size - 1 - (icvp->var_dim_size[idim] - 1) / icvp->derv_dim_scale[idim] ) / 2 ; } /* Get pixel step and start for variable and calculate for user. Look for them in the dimension variable (if MIstep is not there, then use defaults step = 1.0, start = 0.0 */ oldncopts = ncopts; ncopts = 0; dimstep = 1.0; (void) miattget1(cdfid, dimvid[idim], MIstep, NC_DOUBLE, &dimstep); /* Flip dimstep if needed */ if (icvp->derv_dim_flip[idim]) dimstep *= (-1); /* Get step size for user's image */ icvp->derv_dim_step[idim] = icvp->derv_dim_grow[idim] ? dimstep / icvp->derv_dim_scale[idim] : dimstep * icvp->derv_dim_scale[idim]; /* Get start position for user's image - if no MIstart for dimension, then assume 0.0 */ dimstart = 0.0; (void) miattget1(cdfid, dimvid[idim], MIstart, NC_DOUBLE, &dimstart); /* Flip dimstart if needed */ if (icvp->derv_dim_flip[idim]) dimstart -= dimstep * (icvp->var_dim_size[idim]-1); /* Calculate start position */ icvp->derv_dim_start[idim] = dimstart + (icvp->derv_dim_step[idim] - dimstep) / 2.0 - icvp->derv_dim_off[idim] * icvp->derv_dim_step[idim]; ncopts = oldncopts; } /* for each dimension */ MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_dim_bufsize_step @INPUT : icvp - icv pointer subsc - array of dimension subscripts for fastest varying dimensions @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Sets the variables giving variable buffer size @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 3, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_get_dim_bufsize_step(mi_icv_type *icvp, int subsc[]) { int idim; MI_SAVE_ROUTINE_NAME("MI_get_dim_bufsize_step"); /* Set default buffer size step */ for (idim=0; idim < MAX_VAR_DIMS; idim++) icvp->derv_bufsize_step[idim]=1; /* Check for converting vector to scalar */ icvp->derv_do_bufsize_step = (icvp->var_is_vector && icvp->user_do_scalar); if (icvp->derv_do_bufsize_step) icvp->derv_bufsize_step[icvp->var_ndims-1] = icvp->var_vector_size; /* Check each dimension to see if we need to worry about the variable buffer size. This only occurs if we are shrinking the dimension from the variable buffer to the user buffer. */ for (idim=0; idim < icvp->user_num_imgdims; idim++) { if (!icvp->derv_dim_grow[idim]) icvp->derv_bufsize_step[subsc[idim]]=icvp->derv_dim_scale[idim]; if (icvp->derv_bufsize_step[subsc[idim]] != 1) icvp->derv_do_bufsize_step = TRUE; } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_dim_conversion @INPUT : icvp - icv pointer subsc - array of dimension subscripts for fastest varying dimensions @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Sets the variables for dimensions converions @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 8, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_get_dim_conversion(mi_icv_type *icvp, int subsc[]) /* ARGSUSED */ { int idim; MI_SAVE_ROUTINE_NAME("MI_icv_get_dim_conversion"); /* Find out whether we need to compress variable or user buffer */ icvp->derv_var_compress = (icvp->var_is_vector && icvp->user_do_scalar); icvp->derv_usr_compress = FALSE; for (idim=0; idimuser_num_imgdims; idim++) { if (icvp->derv_dim_scale[idim]!=1) { if (icvp->derv_dim_grow[idim]) icvp->derv_usr_compress = TRUE; else icvp->derv_var_compress = TRUE; } } /* Get the fastest varying dimension in user's buffer */ icvp->derv_dimconv_fastdim = icvp->var_ndims-1; if (icvp->var_is_vector && icvp->user_do_scalar) icvp->derv_dimconv_fastdim--; /* Find out how many pixels to compress/expand for variable and user buffers and allocate arrays */ if (icvp->var_is_vector && icvp->user_do_scalar) icvp->derv_var_pix_num=icvp->var_vector_size; else icvp->derv_var_pix_num=1; icvp->derv_usr_pix_num=1; for (idim=0; idimuser_num_imgdims; idim++) { if (icvp->derv_dim_grow[idim]) icvp->derv_usr_pix_num *= icvp->derv_dim_scale[idim]; else icvp->derv_var_pix_num *= MIN(icvp->var_dim_size[idim], icvp->derv_dim_scale[idim]); } icvp->derv_var_pix_off = MALLOC(icvp->derv_var_pix_num, long); icvp->derv_usr_pix_off = MALLOC(icvp->derv_usr_pix_num, long); if ((icvp->derv_var_pix_off == NULL) || (icvp->derv_usr_pix_off == NULL)) { MI_LOG_SYS_ERROR1("MI_icv_get_dim_conversion"); MI_RETURN_ERROR(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_dimconvert @INPUT : operation - MI_PRIV_GET or MI_PRIV_PUT icvp - icv structure pointer start - start passed by user count - count passed by user values - pointer to user's data area (for put) bufstart - start of variable buffer bufcount - count of variable buffer buffer - pointer to variable buffer (for get) @OUTPUT : values - pointer to user's data area (for get) buffer - pointer to variable buffer (for put) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Converts values and dimensions from an input buffer to the user's buffer. Called by MI_var_action. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 27, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_dimconvert(int operation, mi_icv_type *icvp, long start[], long count[], void *values, long bufstart[], long bufcount[], void *buffer) { mi_icv_dimconv_type dim_conv_struct; mi_icv_dimconv_type *dcp; double sum0, sum1; /* Counters for averaging values */ double dvalue; /* Pixel value */ long counter[MAX_VAR_DIMS]; /* Dimension loop counter */ void *ptr, *iptr, *optr; /* Pointers for looping through fastest dim */ void *ivecptr[MAX_VAR_DIMS]; /* Pointers to start of each dimension */ void *ovecptr[MAX_VAR_DIMS]; long *end; /* Pointer to array of dimension ends */ int fastdim; /* Dimension that varies fastest */ long ipix; /* Buffer subscript */ int idim; /* Dimension subscript */ int notmodified; /* First dimension not reset */ int out_of_range; /* Flag indicating one pixel of sum out of range */ double dmin, dmax, epsilon; /* Range limits */ MI_SAVE_ROUTINE_NAME("MI_icv_dimconvert"); /* Initialize variables */ dcp = &dim_conv_struct; {MI_CHK_ERR(MI_icv_dimconv_init(operation, icvp, dcp, start, count, values, bufstart, bufcount, buffer))} /* Initialize local variables */ iptr = dcp->istart; optr = dcp->ostart; end = dcp->end; fastdim = icvp->derv_dimconv_fastdim; dmax = icvp->fill_valid_max; dmin = icvp->fill_valid_min; epsilon = (dmax - dmin) * FILLVALUE_EPSILON; epsilon = fabs(epsilon); dmax += epsilon; dmin -= epsilon; /* Initialize counters */ for (idim=0; idim<=fastdim; idim++) { counter[idim] = 0; ivecptr[idim] = iptr; ovecptr[idim] = optr; } /* Loop through data */ while (counter[0] < end[0]) { /* Compress data by averaging if needed */ if (!dcp->do_compress) { {MI_TO_DOUBLE(dvalue, dcp->intype, dcp->insign, iptr)} out_of_range = (icvp->do_fillvalue && ((dvalue < dmin) || (dvalue > dmax))); } else { sum1 = 0.0; sum0 = 0.0; out_of_range=FALSE; for (ipix=0; ipixin_pix_num; ipix++) { ptr=(void *) ((char *)iptr + dcp->in_pix_off[ipix]); /* Check if we are outside the buffer. If we are looking before the buffer, then we need to add in the previous result to do averaging properly. If we are looking after the buffer, then break. */ if (ptrin_pix_first) { /* Get the output value and re-scale it */ {MI_TO_DOUBLE(dvalue, dcp->outtype, dcp->outsign, optr)} if (icvp->do_scale) { dvalue = ((icvp->scale==0.0) ? 0.0 : (dvalue - icvp->offset) / icvp->scale); } } else if (ptr>dcp->in_pix_last) { continue; } else { {MI_TO_DOUBLE(dvalue, dcp->intype, dcp->insign, ptr)} } /* Add in the value, checking for range if needed */ if (icvp->do_fillvalue && ((dvalue < dmin) || (dvalue > dmax))) { out_of_range = TRUE; } else { sum1 += dvalue; sum0++; } } /* Foreach pixel to compress */ /* Average values */ if (sum0!=0.0) dvalue = sum1/sum0; else dvalue = 0.0; } /* If compress */ /* Check for out of range values and scale result */ if (out_of_range) { dvalue = icvp->user_fillvalue; } else if (icvp->do_scale) { dvalue = icvp->scale * dvalue + icvp->offset; } /* Expand data if needed */ if (!dcp->do_expand) { {MI_FROM_DOUBLE(dvalue, dcp->outtype, dcp->outsign, optr)} } else { for (ipix=0; ipixout_pix_num; ipix++) { ptr=(void *) ((char *)optr + dcp->out_pix_off[ipix]); /* Check if we are outside the buffer. */ if ((ptr>=dcp->out_pix_first) && (ptr<=dcp->out_pix_last)) { {MI_FROM_DOUBLE(dvalue, dcp->outtype, dcp->outsign, ptr)} } } /* Foreach pixel to expand */ } /* if expand */ /* Increment the counter and the pointers */ if ((++counter[fastdim]) < end[fastdim]) { optr = (void *) ((char *) optr + dcp->ostep[fastdim]); iptr = (void *) ((char *) iptr + dcp->istep[fastdim]); } else { /* If we reach the end of fastdim, then reset the counter and increment the next dimension down - keep going as needed. The vectors ovecptr and ivecptr give the starting values of optr and iptr for that dimension. */ idim = fastdim; while ((idim>0) && (counter[idim] >= end[idim])) { counter[idim] = 0; idim--; counter[idim]++; ovecptr[idim] = (void *)((char *)ovecptr[idim]+dcp->ostep[idim]); ivecptr[idim] = (void *)((char *)ivecptr[idim]+dcp->istep[idim]); } notmodified = idim; /* Copy the starting index up the vector */ for (idim=notmodified+1; idim<=fastdim; idim++) { ovecptr[idim]=ovecptr[notmodified]; ivecptr[idim]=ivecptr[notmodified]; } optr = ovecptr[fastdim]; iptr = ivecptr[fastdim]; } /* if at end of row */ } /* while more pixels to process */ MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_dimconv_init @INPUT : operation - MI_PRIV_GET or MI_PRIV_PUT icvp - icv structure pointer dcp - dimconvert structure pointer start - start passed by user count - count passed by user values - pointer to user's data area (for put) bufstart - start of variable buffer bufcount - count of variable buffer buffer - pointer to variable buffer (for get) @OUTPUT : @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Sets up stuff for MI_icv_dimconvert. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 4, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_dimconv_init(int operation, mi_icv_type *icvp, mi_icv_dimconv_type *dcp, long start[], long count[], void *values, long bufstart[], long bufcount[], void *buffer) /* ARGSUSED */ { long buffer_len, values_len; /* Buffer lengths, offsets and indices */ long buffer_off, values_off; long buffer_index, values_index; int imgdim_high, imgdim_low; /* Range of subscripts of image dimensions */ int scale, offset; /* Dimension scale and offset */ int idim, jdim; int fastdim; /* Variables for calculating pixel offsets for compress/expand */ long var_dcount[MI_MAX_IMGDIMS+1], var_dend[MI_MAX_IMGDIMS+1]; long usr_dcount[MI_MAX_IMGDIMS+1], usr_dend[MI_MAX_IMGDIMS+1]; long pixcount; int var_fd, usr_fd, dshift; long ipix; MI_SAVE_ROUTINE_NAME("MI_icv_dimconv_init"); /* Check to see if any compression or expansion needs to be done. Work it out for a GET and then swap if a PUT. */ if (operation==MI_PRIV_GET) { dcp->do_compress = icvp->derv_var_compress; dcp->do_expand = icvp->derv_usr_compress; } else { dcp->do_expand = icvp->derv_var_compress; dcp->do_compress = icvp->derv_usr_compress; } fastdim = icvp->derv_dimconv_fastdim; /* Get the indices of high and low image dimensions */ imgdim_high=icvp->var_ndims-1; if (icvp->var_is_vector) imgdim_high--; imgdim_low = imgdim_high - icvp->user_num_imgdims + 1; /* Get the buffer sizes */ buffer_len = icvp->var_typelen; values_len = icvp->user_typelen; for (idim=0; idim < icvp->var_ndims; idim++) { buffer_len *= bufcount[idim]; if (idim<=fastdim) values_len *= icvp->derv_icv_count[idim]; } /* Calculate step size for variable and user buffers. This does not allow for growing or shrinking pixels. That correction is done below. */ if (icvp->var_is_vector && icvp->user_do_scalar) { dcp->buf_step[fastdim+1] = icvp->var_typelen; dcp->buf_step[fastdim] = dcp->buf_step[fastdim+1] * bufcount[fastdim+1]; } else { dcp->buf_step[fastdim] = icvp->var_typelen; } dcp->usr_step[fastdim] = icvp->user_typelen; for (idim=fastdim-1; idim>=0; idim--) { dcp->buf_step[idim] = dcp->buf_step[idim+1] * bufcount[idim+1]; dcp->usr_step[idim] = dcp->usr_step[idim+1] * icvp->derv_icv_count[idim+1]; } /* Set sign of user steps for flipping, if needed */ for (idim=imgdim_low; idim <= imgdim_high; idim++) { if (icvp->derv_dim_flip[imgdim_high-idim]) dcp->usr_step[idim] *= (-1); } /* Get the pointers to the start of buffers and the number of pixels in each dimension (count a pixel as one expansion/compression - one time through the loop below) */ buffer_off = 0; values_off = 0; for (idim=0; idim <= fastdim; idim++) { if ((idim < imgdim_low) || (idim > imgdim_high)) { dcp->end[idim] = bufcount[idim]; buffer_index = 0; values_index = bufstart[idim] - icvp->derv_icv_start[idim]; } else { jdim = imgdim_high - idim; scale = icvp->derv_dim_scale[jdim]; offset = icvp->derv_dim_off[jdim]; if (icvp->derv_dim_grow[jdim]) { dcp->end[idim] = bufcount[idim]; buffer_index = 0; if (!icvp->derv_dim_flip[jdim]) values_index = bufstart[idim]*scale - icvp->derv_icv_start[idim] + offset; else values_index = (icvp->var_dim_size[jdim] - bufstart[idim])*scale - 1 - icvp->derv_icv_start[idim] + offset; } else { dcp->end[idim] = (bufcount[idim] - 1 + bufstart[idim]%scale) / scale + 1; buffer_index = -(bufstart[idim] % scale); if (!icvp->derv_dim_flip[jdim]) values_index = bufstart[idim]/scale - icvp->derv_icv_start[idim] + offset; else values_index = (icvp->var_dim_size[jdim] - bufstart[idim] - 1)/scale - icvp->derv_icv_start[idim] + offset; } } buffer_off += buffer_index * labs(dcp->buf_step[idim]); values_off += values_index * labs(dcp->usr_step[idim]); } /* Calculate arrays of offsets for compress/expand. */ if (dcp->do_compress || dcp->do_expand) { /* Initialize counters */ var_fd = icvp->user_num_imgdims-1; usr_fd = icvp->user_num_imgdims-1; if (icvp->var_is_vector && icvp->user_do_scalar) { var_fd++; var_dcount[var_fd]=0; var_dend[var_fd]=icvp->var_vector_size; } for (jdim=0; jdimuser_num_imgdims; jdim++) { idim=icvp->user_num_imgdims - jdim - 1; var_dcount[idim] = 0; usr_dcount[idim] = 0; var_dend[idim] = (icvp->derv_dim_grow[jdim] ? 1 : MIN(icvp->var_dim_size[jdim], icvp->derv_dim_scale[jdim])); usr_dend[idim] = (icvp->derv_dim_grow[jdim] ? icvp->derv_dim_scale[jdim] : 1); } /* Loop through variable buffer pixels */ pixcount=0; dshift = imgdim_low; for (ipix=0; ipixderv_var_pix_num; ipix++) { icvp->derv_var_pix_off[ipix] = pixcount; pixcount += dcp->buf_step[var_fd+dshift]; if ((++var_dcount[var_fd]) >= var_dend[var_fd]) { idim=var_fd; while ((idim>0) && (var_dcount[idim]>=var_dend[idim])) { var_dcount[idim]=0; idim--; var_dcount[idim]++; } for (idim=0, pixcount=0; idim<=var_fd; idim++) { pixcount += var_dcount[idim] * dcp->buf_step[idim+dshift]; } } } /* Loop through user buffer pixels */ pixcount=0; dshift = imgdim_low; for (ipix=0; ipixderv_usr_pix_num; ipix++) { icvp->derv_usr_pix_off[ipix] = pixcount; pixcount += dcp->usr_step[usr_fd+dshift]; if ((++usr_dcount[usr_fd]) >= usr_dend[usr_fd]) { idim=usr_fd; while ((idim>0) && (usr_dcount[idim]>=usr_dend[idim])) { usr_dcount[idim]=0; idim--; usr_dcount[idim]++; } for (idim=0, pixcount=0; idim<=var_fd; idim++) { pixcount += usr_dcount[idim] * dcp->usr_step[idim+dshift]; } } } /* Correct buffer steps for compress/expand */ for (idim=imgdim_low; idim <= imgdim_high; idim++) { jdim = imgdim_high-idim; if (icvp->derv_dim_grow[jdim]) dcp->usr_step[idim] *= icvp->derv_dim_scale[jdim]; else dcp->buf_step[idim] *= icvp->derv_dim_scale[jdim]; } } /* if compress/expand */ /* Set input and output variables */ if (operation==MI_PRIV_GET) { /* For a GET */ dcp->in_pix_num = icvp->derv_var_pix_num; dcp->in_pix_off = icvp->derv_var_pix_off; dcp->in_pix_first = buffer; dcp->in_pix_last = (void *) ((char *)buffer + buffer_len - 1); dcp->out_pix_num = icvp->derv_usr_pix_num; dcp->out_pix_off = icvp->derv_usr_pix_off; dcp->out_pix_first = values; dcp->out_pix_last = (void *) ((char *)values + values_len - 1); dcp->intype = icvp->var_type; dcp->insign = icvp->var_sign; dcp->outtype = icvp->user_type; dcp->outsign = icvp->user_sign; dcp->istep = dcp->buf_step; dcp->ostep = dcp->usr_step; dcp->istart = (void *) ((char *) buffer + buffer_off); dcp->ostart = (void *) ((char *) values + values_off); } /* if GET */ else { /* For a PUT */ dcp->out_pix_num = icvp->derv_var_pix_num; dcp->out_pix_off = icvp->derv_var_pix_off; dcp->out_pix_first = buffer; dcp->out_pix_last = (void *) ((char *)buffer + buffer_len - 1); dcp->in_pix_num = icvp->derv_usr_pix_num; dcp->in_pix_off = icvp->derv_usr_pix_off; dcp->in_pix_first = values; dcp->in_pix_last = (void *) ((char *)values + values_len - 1); dcp->outtype = icvp->var_type; dcp->outsign = icvp->var_sign; dcp->intype = icvp->user_type; dcp->insign = icvp->user_sign; dcp->ostep = dcp->buf_step; dcp->istep = dcp->usr_step; dcp->ostart = (void *) ((char *) buffer + buffer_off); dcp->istart = (void *) ((char *) values + values_off); } /* if PUT */ MI_RETURN(MI_NOERROR); } minc-2.2.00/libsrc/image_conversion.c0000644000265600003100000017113112027132662014415 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : image_conversion.c @DESCRIPTION: File of functions to manipulate image conversion variables (icv). These variables allow conversion of netcdf variables (the MINC image variable, in particular) to a form more convenient for a program. @METHOD : Routines included in this file : public : miicv_create miicv_free miicv_setdbl miicv_setint miicv_setlong miicv_setstr miicv_inqdbl miicv_inqint miicv_inqlong miicv_inqstr miicv_ndattach miicv_detach miicv_get miicv_put semiprivate : MI_icv_chkid private : MI_icv_get_type MI_icv_get_vrange MI_get_default_range MI_icv_get_norm MI_icv_access MI_icv_zero_buffer MI_icv_coords_tovar MI_icv_calc_scale @CREATED : July 27, 1992. (Peter Neelin, Montreal Neurological Institute) @MODIFIED : * $Log: image_conversion.c,v $ * Revision 6.17 2010-03-02 12:23:14 rotor * * ported HDF calls to 1.8.x * * Makefile.am: updated for minccmp * * Revision 6.16 2008/01/17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.15 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.14 2007/12/12 20:55:26 rotor * * added a bunch of bug fixes from Claude. * * Revision 6.13 2004/12/14 23:53:46 bert * Get rid of compilation warnings * * Revision 6.12 2004/10/15 13:45:28 bert * Minor changes for Windows compatibility * * Revision 6.11 2004/04/27 15:40:22 bert * Revised logging/error handling * * Revision 6.10 2003/09/18 16:17:00 bert * Correctly cast double to nc_type * * Revision 6.9 2001/11/28 15:38:07 neelin * Removed limit on number of icvs that can exist at one time. * * Revision 6.8 2001/11/13 21:00:24 neelin * Modified icv scaling calculations for no normalization. When the icv * type is double, normalization is always done, regardless of the * normalization setting. When the external type is floating point, * normalization to the slice real range is done (essentially a valid * range scaling, but where the valid range for a float is the slice real * range). * * Revision 6.7 2001/11/13 14:15:17 neelin * Added functions miget_image_range and mivar_exists * * Revision 6.6 2001/08/20 13:16:53 neelin * Removed extraneous variables from MI_icv_get_vrange. * * Revision 6.5 2001/08/16 19:24:11 neelin * Fixes to the code handling valid_range values. * * Revision 6.4 2001/08/16 16:41:31 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.3 2001/08/16 13:32:18 neelin * Partial fix for valid_range of different type from image (problems * arising from double to float conversion/rounding). NOT COMPLETE. * * Revision 6.2 2001/04/17 18:40:12 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:07 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.3 1997/04/21 17:32:04 neelin * Fixed calculation of scale for icv so that values are not re-scaled * from real values to file floating-point values. * * Revision 3.2 1997/04/10 19:22:18 neelin * Removed redefinition of NULL and added pointer casts in appropriate places. * * Revision 3.1 1997/04/10 18:14:50 neelin * Fixed handling of invalid data when icv scale is zero. * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.3 1995/02/08 19:14:44 neelin * More changes for irix 5 lint. * * Revision 2.2 1995/02/08 19:01:06 neelin * Moved private function declarations from minc_routines.h to appropriate file. * * Revision 2.1 1994/12/09 09:12:30 neelin * Added test in miicv_detach to make sure that icv is attached before * detaching it. * * Revision 2.0 94/09/28 10:37:55 neelin * Release of minc version 0.2 * * Revision 1.18 94/09/28 10:37:06 neelin * Pre-release * * Revision 1.17 93/08/11 12:59:31 neelin * We need only increment the chunk pointer (see previous fix) if we are * not doing dimension conversion (dimension conversion handles the * offsets itself). * * Revision 1.16 93/08/11 11:49:36 neelin * Added RCS logging in source. * Fixed bug in MI_icv_access so that pointer to values buffer is incremented * as we loop through the chunks. This affected calls to miicv_get/put that * had MIimagemax/min varying over the values read in one call (ie. reading * or writing a volume with MIimagemax/min varying over slices will give * incorrect results if the volume is read with one call). * January 22, 1993 (P.N.) - Modified handling of icv properties with miicv_set. Removed routine miicv_set. Use routines miicv_setdbl, miicv_setint, miicv_setlong, miicv_setstr instead (this gives type checking at compile time). @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #include "type_limits.h" /* Private functions */ PRIVATE int MI_icv_get_type(mi_icv_type *icvp, int cdfid, int varid); PRIVATE int MI_icv_get_vrange(mi_icv_type *icvp, int cdfid, int varid); PRIVATE double MI_get_default_range(char *what, nc_type datatype, int sign); PRIVATE int MI_icv_get_norm(mi_icv_type *icvp, int cdfid, int varid); PRIVATE int MI_icv_access(int operation, mi_icv_type *icvp, long start[], long count[], void *values); PRIVATE int MI_icv_zero_buffer(mi_icv_type *icvp, long count[], void *values); PRIVATE int MI_icv_coords_tovar(mi_icv_type *icvp, long icv_start[], long icv_count[], long var_start[], long var_count[]); PRIVATE int MI_icv_calc_scale(int operation, mi_icv_type *icvp, long coords[]); /* Array of pointers to image conversion structures */ static int minc_icv_list_nalloc = 0; static mi_icv_type **minc_icv_list = NULL; /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_create @INPUT : (none) @OUTPUT : (none) @RETURNS : icv id or MI_ERROR when an error occurs @DESCRIPTION: Creates an image conversion variable (icv) and returns a handle to it. @METHOD : @GLOBALS : @CALLS : @CREATED : August 7, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_create() { int new_icv; /* Id of newly created icv */ mi_icv_type *icvp; /* Pointer to new icv structure */ int idim; int new_nalloc; MI_SAVE_ROUTINE_NAME("miicv_create"); /* Look for free slot */ for (new_icv=0; new_icv=minc_icv_list_nalloc) { /* How much space will be needed? */ new_nalloc = minc_icv_list_nalloc + MI_MAX_NUM_ICV; /* Check for first allocation */ if (minc_icv_list_nalloc == 0) { minc_icv_list = MALLOC(new_nalloc, mi_icv_type *); } else { minc_icv_list = REALLOC(minc_icv_list, new_nalloc, mi_icv_type *); } /* Check that the allocation was successful */ if (minc_icv_list == NULL) { MI_LOG_SYS_ERROR1("miicv_create"); MI_RETURN(MI_ERROR); } /* Put in NULL pointers */ for (new_icv=minc_icv_list_nalloc; new_icvdo_scale = FALSE; icvp->do_dimconvert = FALSE; icvp->do_fillvalue = FALSE; icvp->fill_valid_min = -DBL_MAX; icvp->fill_valid_max = DBL_MAX; /* User defaults */ icvp->user_type = NC_SHORT; icvp->user_typelen = nctypelen(icvp->user_type); icvp->user_sign = MI_PRIV_SIGNED; icvp->user_do_range = TRUE; icvp->user_vmax = MI_get_default_range(MIvalid_max, icvp->user_type, icvp->user_sign); icvp->user_vmin = MI_get_default_range(MIvalid_min, icvp->user_type, icvp->user_sign); icvp->user_do_norm = FALSE; icvp->user_user_norm = FALSE; icvp->user_maxvar = strdup(MIimagemax); icvp->user_minvar = strdup(MIimagemin); icvp->user_imgmax = MI_DEFAULT_MAX; icvp->user_imgmin = MI_DEFAULT_MIN; icvp->user_do_dimconv = FALSE; icvp->user_do_scalar = TRUE; icvp->user_xdim_dir = MI_ICV_POSITIVE; icvp->user_ydim_dir = MI_ICV_POSITIVE; icvp->user_zdim_dir = MI_ICV_POSITIVE; icvp->user_num_imgdims = 2; icvp->user_keep_aspect = TRUE; icvp->user_do_fillvalue = FALSE; icvp->user_fillvalue = -DBL_MAX; for (idim=0; idimuser_dim_size[idim]=MI_ICV_ANYSIZE; } /* Variable values */ icvp->cdfid = MI_ERROR; /* Set so that we can recognise an */ icvp->varid = MI_ERROR; /* unattached icv */ /* Values that can be read by user */ icvp->derv_imgmax = MI_DEFAULT_MAX; icvp->derv_imgmin = MI_DEFAULT_MIN; for (idim=0; idimderv_dim_step[idim] = 0.0; icvp->derv_dim_start[idim] = 0.0; } MI_RETURN(new_icv); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_free @INPUT : icvid @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Frees the image conversion variable (icv) @METHOD : @GLOBALS : @CALLS : @CREATED : August 7, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_free(int icvid) { mi_icv_type *icvp; MI_SAVE_ROUTINE_NAME("miicv_free"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN(MI_ERROR); /* Detach the icv if it is attached */ if (icvp->cdfid != MI_ERROR) { if (miicv_detach(icvid) < 0) { MI_RETURN(MI_ERROR); } } /* Free anything allocated at creation time */ FREE(icvp->user_maxvar); FREE(icvp->user_minvar); /* Free the structure */ FREE(icvp); minc_icv_list[icvid]=NULL; /* Delete entire structure if no longer in use. */ int new_icv; for (new_icv=0; new_icv=minc_icv_list_nalloc) { FREE(minc_icv_list); minc_icv_list_nalloc=0; } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_setdbl @INPUT : icvid - icv id icv_property - property of icv to set value - value to set it to @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Sets a property of an icv to a given double value Properties cannot be modified while the icv is attached to a cdf file and variable (see miicv_attach and miicv_detach). @METHOD : @GLOBALS : @CALLS : @CREATED : August 7, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_setdbl(int icvid, int icv_property, double value) { int ival, idim; mi_icv_type *icvp; MI_SAVE_ROUTINE_NAME("miicv_setdbl"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN(MI_ERROR); /* Check that the icv is not attached to a file */ if (icvp->cdfid != MI_ERROR) { milog_message(MI_MSG_ICVATTACHED); MI_RETURN(MI_ERROR); } /* Set the property */ switch (icv_property) { case MI_ICV_TYPE: icvp->user_type = (nc_type) (int) value; icvp->user_typelen= nctypelen(icvp->user_type); icvp->user_vmax = MI_get_default_range(MIvalid_max, icvp->user_type, icvp->user_sign); icvp->user_vmin = MI_get_default_range(MIvalid_min, icvp->user_type, icvp->user_sign); break; case MI_ICV_DO_RANGE: icvp->user_do_range = value; break; case MI_ICV_VALID_MAX: icvp->user_vmax = value; break; case MI_ICV_VALID_MIN: icvp->user_vmin = value; break; case MI_ICV_DO_NORM: icvp->user_do_norm = value; break; case MI_ICV_USER_NORM: icvp->user_user_norm = value; break; case MI_ICV_IMAGE_MAX: icvp->user_imgmax = value; break; case MI_ICV_IMAGE_MIN: icvp->user_imgmin = value; break; case MI_ICV_DO_FILLVALUE: icvp->user_do_fillvalue = value; break; case MI_ICV_FILLVALUE: icvp->user_fillvalue = value; break; case MI_ICV_DO_DIM_CONV: icvp->user_do_dimconv = value; break; case MI_ICV_DO_SCALAR: icvp->user_do_scalar = value; break; case MI_ICV_XDIM_DIR: ival = value; icvp->user_xdim_dir = ((ival==MI_ICV_POSITIVE) || (ival==MI_ICV_NEGATIVE)) ? ival : MI_ICV_ANYDIR; break; case MI_ICV_YDIM_DIR: ival = value; icvp->user_ydim_dir = ((ival==MI_ICV_POSITIVE) || (ival==MI_ICV_NEGATIVE)) ? ival : MI_ICV_ANYDIR; break; case MI_ICV_ZDIM_DIR: ival = value; icvp->user_zdim_dir = ((ival==MI_ICV_POSITIVE) || (ival==MI_ICV_NEGATIVE)) ? ival : MI_ICV_ANYDIR; break; case MI_ICV_NUM_IMGDIMS: ival = value; if ((ival<0) || (ival>MI_MAX_IMGDIMS)) { milog_message(MI_MSG_BADPROP, _("MI_ICV_NUM_IMGDIMS out of range")); MI_RETURN(MI_ERROR); } icvp->user_num_imgdims = ival; break; case MI_ICV_ADIM_SIZE: icvp->user_dim_size[0] = value; break; case MI_ICV_BDIM_SIZE: icvp->user_dim_size[1] = value; break; case MI_ICV_KEEP_ASPECT: icvp->user_keep_aspect = value; break; case MI_ICV_SIGN: case MI_ICV_MAXVAR: case MI_ICV_MINVAR: milog_message(MI_MSG_BADPROP, _("Can't store a number in a string value")); MI_RETURN(MI_ERROR); break; default: /* Check for image dimension properties */ if ((icv_property>=MI_ICV_DIM_SIZE) && (icv_propertyuser_dim_size[idim] = value; } else { milog_message(MI_MSG_BADPROP, "Unknown code"); MI_RETURN(MI_ERROR); } break; } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_setint @INPUT : icvid - icv id icv_property - property of icv to set value - value to set it to @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Sets a property of an icv to a given integer value. Properties cannot be modified while the icv is attached to a cdf file and variable (see miicv_attach and miicv_detach). @METHOD : @GLOBALS : @CALLS : @CREATED : August 7, 1992 (Peter Neelin) @MODIFIED : January 22, 1993 (P.N.) - modified handling of icv properties ---------------------------------------------------------------------------- */ MNCAPI int miicv_setint(int icvid, int icv_property, int value) { MI_SAVE_ROUTINE_NAME("miicv_setint"); if (miicv_setdbl(icvid, icv_property, (double) value) < 0) { MI_RETURN(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_setlong @INPUT : icvid - icv id icv_property - property of icv to set value - value to set it to @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Sets a property of an icv to a given long integer value. Properties cannot be modified while the icv is attached to a cdf file and variable (see miicv_attach and miicv_detach). @METHOD : @GLOBALS : @CALLS : @CREATED : January 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_setlong(int icvid, int icv_property, long value) { MI_SAVE_ROUTINE_NAME("miicv_setlong"); if (miicv_setdbl(icvid, icv_property, (double) value) < 0) { MI_RETURN(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_setstr @INPUT : icvid - icv id icv_property - property of icv to set value - value to set it to @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Sets a property of an icv to a given string value. Properties cannot be modified while the icv is attached to a cdf file and variable (see miicv_attach and miicv_detach). @METHOD : @GLOBALS : @CALLS : @CREATED : January 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_setstr(int icvid, int icv_property, char *value) { mi_icv_type *icvp; MI_SAVE_ROUTINE_NAME("miicv_setstr"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN(MI_ERROR); /* Check that the icv is not attached to a file */ if (icvp->cdfid != MI_ERROR) { milog_message(MI_MSG_ICVATTACHED); MI_RETURN(MI_ERROR); } /* Set the property */ switch (icv_property) { case MI_ICV_SIGN: icvp->user_sign = MI_get_sign_from_string(icvp->user_type, value); icvp->user_vmax = MI_get_default_range(MIvalid_max, icvp->user_type, icvp->user_sign); icvp->user_vmin = MI_get_default_range(MIvalid_min, icvp->user_type, icvp->user_sign); break; case MI_ICV_MAXVAR: if (value!=NULL) { FREE(icvp->user_maxvar); icvp->user_maxvar = strdup(value); } break; case MI_ICV_MINVAR: if (value!=NULL) { FREE(icvp->user_minvar); icvp->user_minvar = strdup(value); } break; case MI_ICV_TYPE: case MI_ICV_DO_RANGE: case MI_ICV_VALID_MAX: case MI_ICV_VALID_MIN: case MI_ICV_DO_NORM: case MI_ICV_USER_NORM: case MI_ICV_IMAGE_MAX: case MI_ICV_IMAGE_MIN: case MI_ICV_DO_DIM_CONV: case MI_ICV_DO_SCALAR: case MI_ICV_XDIM_DIR: case MI_ICV_YDIM_DIR: case MI_ICV_ZDIM_DIR: case MI_ICV_NUM_IMGDIMS: case MI_ICV_ADIM_SIZE: case MI_ICV_BDIM_SIZE: case MI_ICV_KEEP_ASPECT: milog_message(MI_MSG_BADPROP, "Can't store a string in a numeric property"); MI_RETURN(MI_ERROR); break; default: /* Check for image dimension properties */ if ((icv_property>=MI_ICV_DIM_SIZE) && (icv_propertyuser_type; break; case MI_ICV_DO_RANGE: *value = icvp->user_do_range; break; case MI_ICV_VALID_MAX: *value = icvp->user_vmax; break; case MI_ICV_VALID_MIN: *value = icvp->user_vmin; break; case MI_ICV_DO_NORM: *value = icvp->user_do_norm; break; case MI_ICV_USER_NORM: *value = icvp->user_user_norm; break; case MI_ICV_IMAGE_MAX: *value = icvp->user_imgmax; break; case MI_ICV_IMAGE_MIN: *value = icvp->user_imgmin; break; case MI_ICV_NORM_MAX: *value = icvp->derv_imgmax; break; case MI_ICV_NORM_MIN: *value = icvp->derv_imgmin; break; case MI_ICV_DO_FILLVALUE: *value = icvp->user_do_fillvalue; break; case MI_ICV_FILLVALUE: *value = icvp->user_fillvalue; break; case MI_ICV_DO_DIM_CONV: *value = icvp->user_do_dimconv; break; case MI_ICV_DO_SCALAR: *value = icvp->user_do_scalar; break; case MI_ICV_XDIM_DIR: *value = icvp->user_xdim_dir; break; case MI_ICV_YDIM_DIR: *value = icvp->user_ydim_dir; break; case MI_ICV_ZDIM_DIR: *value = icvp->user_zdim_dir; break; case MI_ICV_NUM_IMGDIMS: *value = icvp->user_num_imgdims; break; case MI_ICV_NUM_DIMS: *value = icvp->var_ndims; if (icvp->var_is_vector && icvp->user_do_scalar) (*value)--; break; case MI_ICV_CDFID: *value = icvp->cdfid; break; case MI_ICV_VARID: *value = icvp->varid; break; case MI_ICV_ADIM_SIZE: *value = icvp->user_dim_size[0]; break; case MI_ICV_BDIM_SIZE: *value = icvp->user_dim_size[1]; break; case MI_ICV_ADIM_STEP: *value = icvp->derv_dim_step[0]; break; case MI_ICV_BDIM_STEP: *value = icvp->derv_dim_step[1]; break; case MI_ICV_ADIM_START: *value = icvp->derv_dim_start[0]; break; case MI_ICV_BDIM_START: *value = icvp->derv_dim_start[1]; break; case MI_ICV_KEEP_ASPECT: *value = icvp->user_keep_aspect; break; case MI_ICV_SIGN: case MI_ICV_MAXVAR: case MI_ICV_MINVAR: milog_message(MI_MSG_BADPROP, _("Tried to get icv string property as a number")); MI_RETURN(MI_ERROR); break; default: /* Check for image dimension properties */ if ((icv_property>=MI_ICV_DIM_SIZE) && (icv_propertyuser_dim_size[idim]; } else if ((icv_property>=MI_ICV_DIM_STEP) && (icv_propertyderv_dim_step[idim]; } else if ((icv_property>=MI_ICV_DIM_START) && (icv_propertyderv_dim_start[idim]; } else { milog_message(MI_MSG_BADPROP, _("Tried to get unknown icv property")); MI_RETURN(MI_ERROR); } break; } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_inqint @INPUT : icvid - icv id icv_property - icv property to get @OUTPUT : value - value returned @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets the value of an icv property @METHOD : @GLOBALS : @CALLS : @CREATED : January 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_inqint(int icvid, int icv_property, int *value) { double dvalue; MI_SAVE_ROUTINE_NAME("miicv_inqint"); if (miicv_inqdbl(icvid, icv_property, &dvalue) < 0) { MI_RETURN(MI_ERROR); } *value = dvalue; MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_inqlong @INPUT : icvid - icv id icv_property - icv property to get @OUTPUT : value - value returned @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets the value of an icv property @METHOD : @GLOBALS : @CALLS : @CREATED : January 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_inqlong(int icvid, int icv_property, long *value) { double dvalue; MI_SAVE_ROUTINE_NAME("miicv_inqlong"); if (miicv_inqdbl(icvid, icv_property, &dvalue) < 0) { MI_RETURN(MI_ERROR); } *value = dvalue; MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_inqstr @INPUT : icvid - icv id icv_property - icv property to get @OUTPUT : value - value returned. Caller must allocate enough space for return string. @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets the value of an icv property @METHOD : @GLOBALS : @CALLS : @CREATED : @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_inqstr(int icvid, int icv_property, char *value) { mi_icv_type *icvp; MI_SAVE_ROUTINE_NAME("miicv_inqstr"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN(MI_ERROR); /* Set the property */ switch (icv_property) { case MI_ICV_SIGN: if (icvp->user_sign==MI_PRIV_SIGNED) (void) strcpy(value, MI_SIGNED); else if (icvp->user_sign==MI_PRIV_UNSIGNED) (void) strcpy(value, MI_UNSIGNED); else (void) strcpy(value, MI_EMPTY_STRING); break; case MI_ICV_MAXVAR: (void) strcpy(value, icvp->user_maxvar); break; case MI_ICV_MINVAR: (void) strcpy(value, icvp->user_minvar); break; case MI_ICV_TYPE: case MI_ICV_DO_RANGE: case MI_ICV_VALID_MAX: case MI_ICV_VALID_MIN: case MI_ICV_DO_NORM: case MI_ICV_USER_NORM: case MI_ICV_IMAGE_MAX: case MI_ICV_IMAGE_MIN: case MI_ICV_NORM_MAX: case MI_ICV_NORM_MIN: case MI_ICV_DO_DIM_CONV: case MI_ICV_DO_SCALAR: case MI_ICV_XDIM_DIR: case MI_ICV_YDIM_DIR: case MI_ICV_ZDIM_DIR: case MI_ICV_NUM_IMGDIMS: case MI_ICV_ADIM_SIZE: case MI_ICV_BDIM_SIZE: case MI_ICV_ADIM_STEP: case MI_ICV_BDIM_STEP: case MI_ICV_ADIM_START: case MI_ICV_BDIM_START: case MI_ICV_KEEP_ASPECT: case MI_ICV_NUM_DIMS: case MI_ICV_CDFID: case MI_ICV_VARID: milog_message(MI_MSG_BADPROP, _("Tried to get icv numeric property as a string")); MI_RETURN(MI_ERROR); break; default: /* Check for image dimension properties */ if (((icv_property>=MI_ICV_DIM_SIZE) && (icv_property=MI_ICV_DIM_STEP) && (icv_property=MI_ICV_DIM_START) && (icv_propertycdfid != MI_ERROR) { if (miicv_detach(icvid) < 0) { MI_RETURN(MI_ERROR); } } /* Inquire about the variable's type, sign and number of dimensions */ if (MI_icv_get_type(icvp, cdfid, varid) < 0) { MI_RETURN(MI_ERROR); } /* If not doing range calculations, just set derv_firstdim for MI_icv_access, otherwise, call routines to calculate range and normalization */ if (!icvp->user_do_range) { icvp->derv_firstdim = -1; } else { /* Get valid range */ if (MI_icv_get_vrange(icvp, cdfid, varid) < 0) { MI_RETURN(MI_ERROR); } /* Get normalization info */ if (MI_icv_get_norm(icvp, cdfid, varid) < 0) { MI_RETURN(MI_ERROR); } } /* Set other fields to defaults */ icvp->var_is_vector = FALSE; icvp->var_vector_size = 1; icvp->derv_do_zero = FALSE; icvp->derv_do_bufsize_step = FALSE; icvp->derv_var_pix_off = NULL; icvp->derv_usr_pix_off = NULL; for (idim=0; idimuser_num_imgdims; idim++) { icvp->derv_dim_flip[idim] = FALSE; icvp->derv_dim_grow[idim] = TRUE; icvp->derv_dim_scale[idim] = 1; icvp->derv_dim_off[idim] = 0; icvp->derv_dim_step[idim] = 0.0; icvp->derv_dim_start[idim] = 0.0; } /* Set the do_scale and do_dimconvert fields of icv structure We have to scale only if do_range is TRUE. If ranges don't match, or we have to do user normalization, or if we are normalizing and MIimagemax or MIimagemin vary over the variable. We don't have to scale if input and output are both floating point. */ icvp->do_scale = (icvp->user_do_range && ((icvp->user_vmax!=icvp->var_vmax) || (icvp->user_vmin!=icvp->var_vmin) || (icvp->user_do_norm && icvp->user_user_norm) || (icvp->user_do_norm && (icvp->derv_firstdim>=0))) ); if ((icvp->derv_usr_float && icvp->derv_var_float)) icvp->do_scale = FALSE; icvp->do_dimconvert = FALSE; /* Set the cdfid and varid fields */ icvp->cdfid = cdfid; icvp->varid = varid; MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_type @INPUT : icvp - pointer to icv structure cdfid - cdf file id varid - variable id @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets the type and sign of a variable for miicv_attach. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_get_type(mi_icv_type *icvp, int cdfid, int varid) { int oldncopts; /* For saving value of ncopts */ char stringa[MI_MAX_ATTSTR_LEN]; char *string=stringa; /* String for sign info */ MI_SAVE_ROUTINE_NAME("MI_icv_get_type"); /* Inquire about the variable */ if (ncvarinq(cdfid, varid, NULL, &(icvp->var_type), &(icvp->var_ndims), icvp->var_dim, NULL) < 0) { MI_RETURN(MI_ERROR); } /* Check that the variable type is numeric */ if (icvp->var_type==NC_CHAR) { milog_message(MI_MSG_VARNOTNUM); MI_RETURN(MI_ERROR); } /* Try to find out the sign of the variable using MIsigntype. */ oldncopts = ncopts; ncopts = 0; string=miattgetstr(cdfid, varid, MIsigntype, MI_MAX_ATTSTR_LEN, string); ncopts = oldncopts; icvp->var_sign = MI_get_sign_from_string(icvp->var_type, string); /* Get type lengths */ icvp->var_typelen = nctypelen(icvp->var_type); icvp->user_typelen = nctypelen(icvp->user_type); MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_vrange @INPUT : icvp - pointer to icv structure cdfid - cdf file id varid - variable id @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets the valid range of a variable @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_get_vrange(mi_icv_type *icvp, int cdfid, int varid) { double vrange[2]; /* Valid range buffer */ MI_SAVE_ROUTINE_NAME("MI_icv_get_vrange"); if (miget_valid_range(cdfid, varid, vrange) == MI_ERROR) { MI_RETURN(MI_ERROR); } icvp->var_vmin = vrange[0]; icvp->var_vmax = vrange[1]; MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_get_default_range @INPUT : what - MIvalid_min means get default min, MIvalid_min means get default min datatype - type of variable sign - sign of variable @OUTPUT : (none) @RETURNS : default maximum or minimum for the datatype @DESCRIPTION: Return the defaults maximum or minimum for a given datatype and sign. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE double MI_get_default_range(char *what, nc_type datatype, int sign) { double range[2]; MI_SAVE_ROUTINE_NAME("MI_get_default_range"); (void) miget_default_range(datatype, (sign == MI_PRIV_SIGNED), range); if (STRINGS_EQUAL(what, MIvalid_max)) { MI_RETURN(range[1]); } else if (STRINGS_EQUAL(what, MIvalid_min)) { MI_RETURN(range[0]); } else { ncopts = NC_VERBOSE | NC_FATAL; MI_LOG_PKG_ERROR2(-1,"MINC bug - this line should never be printed"); } MI_RETURN(MI_DEFAULT_MIN); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_get_norm @INPUT : icvp - pointer to icv structure cdfid - cdf file id varid - variable id @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets the normalization info for a variable @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_get_norm(mi_icv_type *icvp, int cdfid, int varid) /* ARGSUSED */ { int oldncopts; /* For saving value of ncopts */ int vid[2]; /* Variable ids for max and min */ int ndims; /* Number of dimensions for image max and min */ int dim[MAX_VAR_DIMS]; /* Dimensions */ int imm; /* Counter for looping through max and min */ double image_range[2]; int idim, i; MI_SAVE_ROUTINE_NAME("MI_icv_get_norm"); /* Check for floating point or double precision values for user or in variable - set flag to not do normalization if needed */ icvp->derv_var_float = ((icvp->var_type == NC_DOUBLE) || (icvp->var_type == NC_FLOAT)); icvp->derv_usr_float = ((icvp->user_type == NC_DOUBLE) || (icvp->user_type == NC_FLOAT)); /* Initialize first dimension over which MIimagemax or MIimagemin vary - assume that they don't vary at all */ icvp->derv_firstdim=(-1); /* Look for image max, image min variables */ oldncopts=ncopts; ncopts=0; icvp->imgmaxid=ncvarid(cdfid, icvp->user_maxvar); icvp->imgminid=ncvarid(cdfid, icvp->user_minvar); ncopts = oldncopts; /* Check to see if normalization to variable max, min should be done */ if (!icvp->user_do_norm) { icvp->derv_imgmax = MI_DEFAULT_MAX; icvp->derv_imgmin = MI_DEFAULT_MIN; } else { /* Get the image min and max, either from the user definition or from the file. */ if (icvp->user_user_norm) { icvp->derv_imgmax = icvp->user_imgmax; icvp->derv_imgmin = icvp->user_imgmin; } else { if (miget_image_range(cdfid, image_range) < 0) { MI_RETURN(MI_ERROR); } icvp->derv_imgmin = image_range[0]; icvp->derv_imgmax = image_range[1]; } /* Check each of the dimensions of image-min/max variables to see which is the fastest varying dimension of the image variable. */ vid[0]=icvp->imgminid; vid[1]=icvp->imgmaxid; if ((vid[0] != MI_ERROR) && (vid[1] != MI_ERROR)) { for (imm=0; imm < 2; imm++) { if (ncvarinq(cdfid, vid[imm], NULL, NULL, &ndims, dim, NULL) < 0) { MI_RETURN(MI_ERROR); } for (idim=0; idimvar_ndims; i++) { if (icvp->var_dim[i]==dim[idim]) icvp->derv_firstdim = MAX(icvp->derv_firstdim, i); } } } } } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_detach @INPUT : icvid - icv id @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Detaches the cdf file and variable from the image conversion variable, allowing modifications to the icv. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_detach(int icvid) { mi_icv_type *icvp; int idim; MI_SAVE_ROUTINE_NAME("miicv_detach"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN(MI_ERROR); /* Check that the icv is in fact attached */ if (icvp->cdfid == MI_ERROR) MI_RETURN(MI_NOERROR); /* Free the pixel offset arrays */ if (icvp->derv_var_pix_off != NULL) FREE(icvp->derv_var_pix_off); if (icvp->derv_usr_pix_off != NULL) FREE(icvp->derv_usr_pix_off); /* Reset values that are read-only (and set when attached) */ icvp->derv_imgmax = MI_DEFAULT_MAX; icvp->derv_imgmin = MI_DEFAULT_MIN; for (idim=0; idimderv_dim_step[idim] = 0.0; icvp->derv_dim_start[idim] = 0.0; } /* Set cdfid field to MI_ERROR to indicate that icv is detached */ icvp->cdfid = MI_ERROR; icvp->varid = MI_ERROR; MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_get @INPUT : icvid - icv id start - coordinates of start of hyperslab (see ncvarget) count - size of hyperslab (see ncvarget) @OUTPUT : values - array of values returned @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets a hyperslab of values from a netcdf variable through the image conversion variable (icvid) @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_get(int icvid, long start[], long count[], void *values) { mi_icv_type *icvp; MI_SAVE_ROUTINE_NAME("miicv_get"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN(MI_ERROR); /* Get the data */ if (MI_icv_access(MI_PRIV_GET, icvp, start, count, values) < 0) { MI_RETURN(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miicv_put @INPUT : icvid - icv id start - coordinates of start of hyperslab (see ncvarput) count - size of hyperslab (see ncvarput) values - array of values to store @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Stores a hyperslab of values in a netcdf variable through the image conversion variable (icvid) @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miicv_put(int icvid, long start[], long count[], void *values) { mi_icv_type *icvp; MI_SAVE_ROUTINE_NAME("miicv_put"); /* Check icv id */ if ((icvp=MI_icv_chkid(icvid)) == NULL) MI_RETURN(MI_ERROR); if (MI_icv_access(MI_PRIV_PUT, icvp, start, count, values) < 0) { MI_RETURN(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_access @INPUT : operation - MI_PRIV_GET or MI_PRIV_PUT icvid - icv id start - coordinates of start of hyperslab (see ncvarput) count - size of hyperslab (see ncvarput) values - array of values to put @OUTPUT : values - array of values to get @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Does the work of getting or putting values from an icv. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 11, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_access(int operation, mi_icv_type *icvp, long start[], long count[], void *values) { int *bufsize_step; /* Pointer to array giving increments for allocating variable buffer (NULL if we don't care) */ long chunk_count[MAX_VAR_DIMS]; /* Number of elements to get for chunk */ long chunk_start[MAX_VAR_DIMS]; /* Starting index for getting a chunk */ long chunk_size; /* Size of chunk in bytes */ void *chunk_values; /* Pointer to next chunk to get */ long var_start[MAX_VAR_DIMS]; /* Coordinates of first var element */ long var_count[MAX_VAR_DIMS]; /* Edge lengths in variable */ long var_end[MAX_VAR_DIMS]; /* Coordinates of last var element */ int firstdim; int idim, ndims; MI_SAVE_ROUTINE_NAME("MI_icv_access"); /* Check that icv is attached to a variable */ if (icvp->cdfid == MI_ERROR) { milog_message(MI_MSG_ICVNOTATTACHED); MI_RETURN(MI_ERROR); } /* Zero the user's buffer if needed */ if ((operation == MI_PRIV_GET) && (icvp->derv_do_zero)) if (MI_icv_zero_buffer(icvp, count, values) < 0) { MI_RETURN(MI_ERROR); } /* Translate icv coordinates to variable coordinates */ if (MI_icv_coords_tovar(icvp, start, count, var_start, var_count) < 0) { MI_RETURN(MI_ERROR); } /* Save icv coordinates for future reference (for dimension conversion routines) */ ndims = icvp->var_ndims; if (icvp->var_is_vector && icvp->user_do_scalar) ndims--; for (idim=0; idim < ndims; idim++) { icvp->derv_icv_start[idim] = start[idim]; icvp->derv_icv_count[idim] = count[idim]; } /* Do we care about getting variable in convenient increments ? Only if we are getting data and the icv structure wants it */ if ((operation==MI_PRIV_GET) && (icvp->derv_do_bufsize_step)) bufsize_step = icvp->derv_bufsize_step; else bufsize_step = NULL; /* Set up variables for looping through variable. The biggest chunk that we can get in one call is determined by the subscripts of MIimagemax and MIimagemin. These must be constant over the chunk that we get if we are doing normalization. */ for (idim=0; idimvar_ndims; idim++) { chunk_start[idim] = var_start[idim]; var_end[idim]=var_start[idim]+var_count[idim]; } (void) miset_coords(icvp->var_ndims, 1L, chunk_count); /* Get size of chunk in user's buffer. Dimension conversion routines don't need the buffer pointer incremented - they do it themselves */ if (!icvp->do_dimconvert) chunk_size = nctypelen(icvp->user_type); else chunk_size = 0; for (idim=MAX(icvp->derv_firstdim+1,0); idim < icvp->var_ndims; idim++) { chunk_count[idim]=var_count[idim]; chunk_size *= chunk_count[idim]; } firstdim = MAX(icvp->derv_firstdim, 0); /* Loop through variable */ chunk_values = values; while (chunk_start[0] < var_end[0]) { /* Set the do_fillvalue flag if the user wants it and we are doing a get. We must do it inside the loop since the scale factor calculation can change it if the scale is zero. (Fillvalue checking is always done if the the scale is zero.) */ icvp->do_fillvalue = icvp->user_do_fillvalue && (operation == MI_PRIV_GET); icvp->fill_valid_min = icvp->var_vmin; icvp->fill_valid_max = icvp->var_vmax; /* Calculate scale factor */ if (icvp->do_scale) { if (MI_icv_calc_scale(operation, icvp, chunk_start) < 0) { MI_RETURN(MI_ERROR); } } // fprintf(stderr, "Getting values at %p\n", chunk_start); /* Get the values */ if (MI_varaccess(operation, icvp->cdfid, icvp->varid, chunk_start, chunk_count, icvp->user_type, icvp->user_sign, chunk_values, bufsize_step, icvp) < 0) { MI_RETURN(MI_ERROR); } /* Increment the start counter */ chunk_start[firstdim] += chunk_count[firstdim]; for (idim=firstdim; (idim>0) && (chunk_start[idim]>=var_end[idim]); idim--) { chunk_start[idim]=var_start[idim]; chunk_start[idim-1]++; } /* Increment the pointer to values */ chunk_values = (void *) ((char *) chunk_values + (size_t) chunk_size); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_zero_buffer @INPUT : icvp - icv structure pointer count - count vector values - pointer to user's buffer @OUTPUT : @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Zeros the user's buffer, with a size given by the vector count. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 9, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_zero_buffer(mi_icv_type *icvp, long count[], void *values) { double zeroval, zerobuf; void *zerostart; int zerolen, idim, ndims; char *bufptr, *bufend, *zeroptr, *zeroend; long buflen; MI_SAVE_ROUTINE_NAME("MI_icv_zero_buffer"); /* Create a zero pixel and get its size */ zerostart = (void *) (&zerobuf); if (icvp->do_scale) zeroval = icvp->offset; else zeroval = 0.0; {MI_FROM_DOUBLE(zeroval, icvp->user_type, icvp->user_sign, zerostart)} zerolen = icvp->user_typelen; /* Get the buffer size */ ndims = icvp->var_ndims; if (icvp->var_is_vector && icvp->user_do_scalar) ndims--; buflen = zerolen; for (idim=0; idim= zeroend) zeroptr = (char *) zerostart; *bufptr = *zeroptr; } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_coords_tovar @INPUT : icvp - icv structure pointer icv_start - start vector for icv icv_count - count vector for icv @OUTPUT : var_start - start vector for variable var_count - count vector for variable @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Converts a start and count vector for referencing an icv to the corresponding vectors for referencing a NetCDF variable. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : September 1, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_coords_tovar(mi_icv_type *icvp, long icv_start[], long icv_count[], long var_start[], long var_count[]) { int i, j; int num_non_img_dims; long coord, last_coord, icv_dim_size; MI_SAVE_ROUTINE_NAME("MI_icv_coords_tovar"); /* Do we have to worry about dimension conversions? If not, then just copy the vectors and return. */ if (!icvp->do_dimconvert) { for (i=0; i < icvp->var_ndims; i++) { var_count[i] = icv_count[i]; var_start[i] = icv_start[i]; } MI_RETURN(MI_NOERROR); } /* Get the number of non image dimensions */ num_non_img_dims=icvp->var_ndims-icvp->user_num_imgdims; if (icvp->var_is_vector) num_non_img_dims--; /* Go through first, non-image dimensions */ for (i=0; i < num_non_img_dims; i++) { var_count[i] = icv_count[i]; var_start[i] = icv_start[i]; } /* Go through image dimensions */ for (i=num_non_img_dims, j=icvp->user_num_imgdims-1; i < num_non_img_dims+icvp->user_num_imgdims; i++, j--) { /* Check coordinates. */ icv_dim_size = (icvp->user_dim_size[j] > 0) ? icvp->user_dim_size[j] : icvp->var_dim_size[j]; last_coord = icv_start[i] + icv_count[i] - 1; if ((icv_start[i]<0) || (icv_start[i]>=icv_dim_size) || (last_coord<0) || (last_coord>=icv_dim_size) || (icv_count[i]<0)) { milog_message(MI_MSG_ICVCOORDS); MI_RETURN(MI_ERROR); } /* Remove offset */ coord = icv_start[i]-icvp->derv_dim_off[j]; /* Check for growing or shrinking */ if (icvp->derv_dim_grow[j]) { var_count[i] = (icv_count[i]+icvp->derv_dim_scale[j]-1) /icvp->derv_dim_scale[j]; coord /= icvp->derv_dim_scale[j]; } else { var_count[i] = icv_count[i]*icvp->derv_dim_scale[j]; coord *= icvp->derv_dim_scale[j]; } /* Check for flipping */ if (icvp->derv_dim_flip[j]) coord = icvp->var_dim_size[j] - coord - ((icv_count!=NULL) ? var_count[i] : 0L); var_start[i] = coord; /* Check for indices out of variable bounds (but in icv bounds) */ last_coord = var_start[i] + var_count[i]; if ((var_start[i]<0) || (last_coord>=icvp->var_dim_size[j])) { if (var_start[i]<0) var_start[i] = 0; if (last_coord>=icvp->var_dim_size[j]) last_coord = icvp->var_dim_size[j] - 1; var_count[i] = last_coord - var_start[i] + 1; } } /* Check for vector dimension */ if (icvp->var_is_vector) { if (icvp->user_do_scalar) { var_count[icvp->var_ndims-1] = icvp->var_vector_size; var_start[icvp->var_ndims-1] = 0; } else { var_count[icvp->var_ndims-1] = icv_count[icvp->var_ndims-1]; var_start[icvp->var_ndims-1] = icv_start[icvp->var_ndims-1]; } } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_calc_scale @INPUT : operation - MI_PRIV_GET or MI_PRIV_PUT icvp - icv structure pointer coords - coordinates of first value to get or put @OUTPUT : icvp - fields scale and offset set @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Calculates the scale and offset needed for getting or putting values, starting at index coords (assumes that scale is constant over that range). @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_icv_calc_scale(int operation, mi_icv_type *icvp, long coords[]) { long mmcoords[MAX_VAR_DIMS]; /* Coordinates for max/min variable */ double usr_imgmax, usr_imgmin; double var_imgmax, var_imgmin; double var_imgmax_true, var_imgmin_true; double usr_vmax, usr_vmin; double var_vmax, var_vmin; double slice_imgmax, slice_imgmin; double usr_scale; double denom; MI_SAVE_ROUTINE_NAME("MI_icv_calc_scale"); /* Set variable valid range */ var_vmax = icvp->var_vmax; var_vmin = icvp->var_vmin; /* Set image max/min for user and variable values depending on whether normalization should be done or not. Whenever floating-point values are involved, some type of normalization is done. When the icv type is floating point, normalization is always done. When the file type is floating point and the icv type is integer, slices are normalized to the real range of the slice (or chunk being read). */ if (!icvp->derv_var_float && !icvp->derv_usr_float && !icvp->user_do_norm) { usr_imgmax = var_imgmax = MI_DEFAULT_MAX; usr_imgmin = var_imgmin = MI_DEFAULT_MIN; } else { /* Get the real range for the slice or chunk that is being examined */ slice_imgmax = MI_DEFAULT_MAX; slice_imgmin = MI_DEFAULT_MIN; if ((!icvp->derv_var_float || !icvp->user_do_norm) && (icvp->imgmaxid!=MI_ERROR) && (icvp->imgminid!=MI_ERROR)) { if (mitranslate_coords(icvp->cdfid, icvp->varid, coords, icvp->imgmaxid, mmcoords) == NULL) MI_RETURN(MI_ERROR); if (mivarget1(icvp->cdfid, icvp->imgmaxid, mmcoords, NC_DOUBLE, NULL, &slice_imgmax) < 0) { MI_RETURN(MI_ERROR); } if (mitranslate_coords(icvp->cdfid, icvp->varid, coords, icvp->imgminid, mmcoords) == NULL) { MI_RETURN(MI_ERROR); } if (mivarget1(icvp->cdfid, icvp->imgminid, mmcoords, NC_DOUBLE, NULL, &slice_imgmin) < 0) { MI_RETURN(MI_ERROR); } } /* Get the user real range */ if (icvp->user_do_norm) { usr_imgmax = icvp->derv_imgmax; usr_imgmin = icvp->derv_imgmin; } else { usr_imgmax = slice_imgmax; usr_imgmin = slice_imgmin; } /* Get the file real range */ if (icvp->derv_var_float) { var_imgmax = var_vmax; var_imgmin = var_vmin; } else { var_imgmax = slice_imgmax; var_imgmin = slice_imgmin; } } /* Prevent scaling between file floats and real value */ if (icvp->derv_var_float) { var_imgmax = var_vmax; var_imgmin = var_vmin; } /* Get user valid range */ if (icvp->derv_usr_float) { usr_vmax = usr_imgmax; usr_vmin = usr_imgmin; } else { usr_vmax = icvp->user_vmax; usr_vmin = icvp->user_vmin; } /* Save real var_imgmin/max for fillvalue checking later */ var_imgmax_true = var_imgmax; var_imgmin_true = var_imgmin; /* Even though we have already carefully set the vmax/min and imgmax/min values to handle the floating point case, we can still have problems with the scale calculations (rounding errors) if full range max/min are used (-FLT_MAX to FLT_MAX). To avoid this, we just force the values to 0 and 1 which will give the correct scale. That is why we save the true values above. */ if (icvp->derv_usr_float) { usr_imgmax = usr_vmax = MI_DEFAULT_MAX; usr_imgmin = usr_vmin = MI_DEFAULT_MIN; } if (icvp->derv_var_float) { var_imgmax = var_vmax = MI_DEFAULT_MAX; var_imgmin = var_vmin = MI_DEFAULT_MIN; } /* Calculate scale and offset for MI_PRIV_GET */ /* Scale */ denom = usr_imgmax - usr_imgmin; if (denom!=0.0) usr_scale=(usr_vmax - usr_vmin) / denom; else usr_scale=0.0; denom = var_vmax - var_vmin; if (denom!=0.0) icvp->scale = usr_scale * (var_imgmax - var_imgmin) / denom; else icvp->scale = 0.0; /* Offset */ icvp->offset = usr_vmin - icvp->scale * var_vmin + usr_scale * (var_imgmin - usr_imgmin); /* If we want a MI_PRIV_PUT, invert */ if (operation==MI_PRIV_PUT) { if (icvp->scale!=0.0) { icvp->offset = (-icvp->offset) / icvp->scale; icvp->scale = 1.0/icvp->scale; } else { icvp->offset = var_vmin; icvp->scale = 0.0; } } /* Do fill value checking if scale is zero */ if (icvp->scale == 0.0) { /* Check for floating point on both sides of conversion. We should not be doing scaling in this case, but we will check to be safe. */ if (icvp->derv_var_float && icvp->derv_usr_float) { icvp->do_scale = FALSE; icvp->do_fillvalue = FALSE; } else { /* Not pure floating point */ icvp->do_fillvalue = TRUE; /* For output, set the range properly depending on whether the user type is floating point or not */ if (operation == MI_PRIV_PUT) { if (icvp->derv_usr_float) { icvp->fill_valid_min = var_imgmin_true; icvp->fill_valid_max = var_imgmax_true; } else if (usr_scale != 0.0) { icvp->fill_valid_min = usr_vmin + (var_imgmin_true - usr_imgmin) / usr_scale; icvp->fill_valid_max = usr_vmin + (var_imgmax_true - usr_imgmin) / usr_scale; } else { icvp->fill_valid_min = usr_vmin; icvp->fill_valid_max = usr_vmax; } } /* If output operation */ } /* If not pure floating point */ } /* If scale == 0.0 */ MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_icv_chkid @INPUT : icvid - icv id @OUTPUT : (none) @RETURNS : Pointer to icv structure if it exists, otherwise NULL. @DESCRIPTION: Checks that an icv id is valid and returns a pointer to the structure. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : August 7, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ SEMIPRIVATE mi_icv_type *MI_icv_chkid(int icvid) { MI_SAVE_ROUTINE_NAME("MI_icv_chkid"); /* Check icv id */ if ((icvid<0) || (icvid>=minc_icv_list_nalloc) || (minc_icv_list[icvid]==NULL)) { milog_message(MI_MSG_BADICV); MI_RETURN((void *) NULL); } MI_RETURN(minc_icv_list[icvid]); } minc-2.2.00/libsrc/minc_convenience.c0000644000265600003100000015343312027132662014375 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_convenience.c @DESCRIPTION: File of convenience functions following the minc standard. @METHOD : Routines included in this file : public : miget_datatype miget_default_range miget_valid_range miset_valid_range miget_image_range mivar_exists miattput_pointer miattget_pointer miadd_child micreate_std_variable micreate_group_variable miget_version miappend_history micreate_ident private : MI_create_dim_variable MI_create_dimwidth_variable MI_create_image_variable MI_create_imaxmin_variable MI_verify_maxmin_dims MI_create_root_variable MI_create_simple_variable MI_add_stdgroup MI_is_in_list @CREATED : July 27, 1992. (Peter Neelin, Montreal Neurological Institute) @MODIFIED : * $Log: minc_convenience.c,v $ * Revision 6.21 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.20 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.19 2007/12/03 14:19:35 rotor * * fixed history appending bug (Thanks Claude) * * updated version for release * * few more fixes for CMake build * * Revision 6.18 2004/12/14 23:53:46 bert * Get rid of compilation warnings * * Revision 6.17 2004/12/03 21:52:35 bert * Minor changes for Windows build * * Revision 6.16 2004/10/15 13:46:15 bert * Minor changes for Windows compatibility * * Revision 6.15 2004/08/26 16:14:21 bert * Fix up miappend_history() again * * Revision 6.14 2004/06/04 18:15:46 bert * Added micreate_ident() * * Revision 6.13 2004/04/27 15:49:17 bert * Use new logging, gettext preparation * * Revision 6.12 2004/03/24 20:53:48 bert * Increase att_length by one in miappend_history() in order to read the entire attribute * * Revision 6.11 2004/02/02 18:22:46 bert * Added miget_version() and miappend_history() * * Revision 6.10 2001/12/06 14:09:07 neelin * Corrected return from mivar_exists to use minc macro MI_RETURN so that * ncopts is properly restored. * * Revision 6.9 2001/11/13 14:15:18 neelin * Added functions miget_image_range and mivar_exists * * Revision 6.8 2001/10/17 14:32:20 neelin * Modified miset_valid_range to write out valid_range as double in all * cases except float. Unfortunately, writing out values in a type that * matched the type of the image variable caused problems with programs * linked against old minc libraries. * * Revision 6.7 2001/09/18 15:44:27 neelin * When output type is NC_BYTE, valid_range attribute should have type NC_SHORT. * * Revision 6.6 2001/08/20 13:19:14 neelin * Added function miattget_with_sign to allow the caller to specify the sign * of the input attribute since this information is ambiguous. This is * necessary for the valid_range attribute which should have the same sign * as the image data. Modified miget_valid_range to make use of this function. * * Revision 6.5 2001/08/16 19:24:11 neelin * Fixes to the code handling valid_range values. * * Revision 6.4 2001/08/16 16:41:32 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.3 2001/08/16 13:32:18 neelin * Partial fix for valid_range of different type from image (problems * arising from double to float conversion/rounding). NOT COMPLETE. * * Revision 6.2 2001/04/17 18:40:13 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:09 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.1 1995/02/08 19:01:06 neelin * Moved private function declarations from minc_routines.h to appropriate file. * * Revision 2.0 1994/09/28 10:38:02 neelin * Release of minc version 0.2 * * Revision 1.18 94/09/28 10:37:12 neelin * Pre-release * * Revision 1.17 93/08/11 12:06:19 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #include "type_limits.h" #include "minc_varlists.h" #include #if HAVE_UNISTD_H #include /* for getpid() */ #endif /* HAVE_UNISTD_H */ /* Private functions */ PRIVATE int MI_create_dim_variable(int cdfid, char *name, nc_type datatype, int ndims); PRIVATE int MI_create_dimwidth_variable(int cdfid, char *name, nc_type datatype, int ndims); PRIVATE int MI_create_image_variable(int cdfid, char *name, nc_type datatype, int ndims, int dim[]); PRIVATE int MI_create_imaxmin_variable(int cdfid, char *name, nc_type datatype, int ndims, int dim[]); PRIVATE int MI_verify_maxmin_dims(int cdfid, int image_ndims, int image_dim[], int maxmin_ndims, int maxmin_dim[]); PRIVATE int MI_create_root_variable(int cdfid, char *name); PRIVATE int MI_create_simple_variable(int cdfid, char *name); PRIVATE int MI_add_stdgroup(int cdfid, int varid); PRIVATE int MI_is_in_list(char *string, char *list[]); /* ----------------------------- MNI Header ----------------------------------- @NAME : miget_datatype @INPUT : cdfid - cdf file id imgid - image variable id @OUTPUT : datatype is_signed - TRUE if type is signed @RETURNS : MI_ERROR when an error occurs. @DESCRIPTION: Gets the datatype and sign of the image variable. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines. @CREATED : August 15, 2001 @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miget_datatype(int cdfid, int imgid, nc_type *datatype, int *is_signed) { int old_ncopts; int use_default_sign; char attstr[MI_MAX_ATTSTR_LEN]; MI_SAVE_ROUTINE_NAME("miget_datatype"); /* Get the type information for the variable */ if (ncvarinq(cdfid, imgid, NULL, datatype, NULL, NULL, NULL) == MI_ERROR) MI_RETURN(MI_ERROR); /* Save the ncopts value */ old_ncopts = ncopts; ncopts = 0; /* Get the sign information */ if ((miattgetstr(cdfid, imgid, MIsigntype, MI_MAX_ATTSTR_LEN, attstr) != NULL)) { use_default_sign = FALSE; if (strcmp(attstr, MI_SIGNED) == 0) *is_signed = TRUE; else if (strcmp(attstr, MI_UNSIGNED) == 0) *is_signed = FALSE; else use_default_sign = TRUE; } else { use_default_sign = TRUE; } /* Set a default sign if needed */ if (use_default_sign) { if (*datatype == NC_BYTE) *is_signed = FALSE; else *is_signed = TRUE; } /* Restore ncopts */ ncopts = old_ncopts; MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miget_default_range @INPUT : datatype is_signed - TRUE if type is signed @OUTPUT : default_range - array containing default range for variable @RETURNS : MI_NOERROR @DESCRIPTION: Gets the default range for a data type. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines. @CREATED : August 15, 2001 @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miget_default_range(nc_type datatype, int is_signed, double default_range[]) { MI_SAVE_ROUTINE_NAME("miget_default_range"); switch (datatype) { case NC_INT: default_range[0] = (is_signed) ? INT_MIN : 0; default_range[1] = (is_signed) ? INT_MAX : UINT_MAX; break; case NC_SHORT: default_range[0] = (is_signed) ? SHRT_MIN : 0; default_range[1] = (is_signed) ? SHRT_MAX : USHRT_MAX; break; case NC_BYTE: default_range[0] = (is_signed) ? SCHAR_MIN : 0; default_range[1] = (is_signed) ? SCHAR_MAX : UCHAR_MAX; break; case NC_FLOAT: default_range[0] = -FLT_MAX; default_range[1] = FLT_MAX; break; case NC_DOUBLE: default_range[0] = -DBL_MAX; default_range[1] = DBL_MAX; break; default: default_range[0]= MI_DEFAULT_MIN; default_range[1]= MI_DEFAULT_MAX; break; } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miget_valid_range @INPUT : cdfid - cdf file id imgid - image variable id @OUTPUT : valid_range - array containing valid min and max of image @RETURNS : MI_ERROR when an error occurs. @DESCRIPTION: Gets the valid range for an image variable. Ensures that the values are cast to the appropriate type to ensure that they are correctly truncated. This is particularly important for float images. If the range cannot be found, then use the default values. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines. @CREATED : August 15, 2001 @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miget_valid_range(int cdfid, int imgid, double valid_range[]) { int old_ncopts; int status; int length; nc_type datatype; int is_signed; char *att_sign; double temp; MI_SAVE_ROUTINE_NAME("miget_valid_range"); /* Get the type information for the variable */ if (miget_datatype(cdfid, imgid, &datatype, &is_signed) == MI_ERROR) MI_RETURN(MI_ERROR); /* Save the ncopts value */ old_ncopts = ncopts; ncopts = 0; /* Get the sign string for the attribute */ if (is_signed) att_sign = MI_SIGNED; else att_sign = MI_UNSIGNED; /* Get valid range */ status=miattget_with_sign(cdfid, imgid, MIvalid_range, att_sign, NC_DOUBLE, NULL, 2, valid_range, &length); /* If not there, look for the max and min */ if ((status==MI_ERROR) || (length!=2)) { /* Get the default range for the type */ (void) miget_default_range(datatype, is_signed, valid_range); /* Try to read the valid max */ (void) miattget_with_sign(cdfid, imgid, MIvalid_max, att_sign, NC_DOUBLE, NULL, 1, &valid_range[1], NULL); /* Try to read the valid min */ (void) miattget_with_sign(cdfid, imgid, MIvalid_min, att_sign, NC_DOUBLE, NULL, 1, &valid_range[0], NULL); } /* Restore the ncopts value */ ncopts = old_ncopts; /* Make sure that the first element is the minimum */ if (valid_range[1] < valid_range[0]) { temp = valid_range[0]; valid_range[0] = valid_range[1]; valid_range[1] = temp; } /* Cast to the appropriate type and back to make sure that things are rounded/truncated properly. This is only really needed for floats */ switch (datatype) { case NC_INT: case NC_SHORT: case NC_BYTE: if (is_signed) { valid_range[0] = (int) valid_range[0]; valid_range[1] = (int) valid_range[1]; } else { valid_range[0] = (unsigned int) valid_range[0]; valid_range[1] = (unsigned int) valid_range[1]; } break; case NC_FLOAT: valid_range[0] = (float) valid_range[0]; valid_range[1] = (float) valid_range[1]; break; } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miset_valid_range @INPUT : cdfid - cdf file id imgid - image variable id valid_range - array containing valid min and max of image @OUTPUT : (none) @RETURNS : MI_ERROR when an error occurs. @DESCRIPTION: Sets the valid range for an image variable. Ensures that the attribute types match the image variable type. This is particularly important for float images because of potential rounding when going from double to float. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines. @CREATED : August 15, 2001 @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miset_valid_range(int cdfid, int imgid, double valid_range[]) { nc_type datatype; int is_signed; int status; char *attname; float fval[2]; MI_SAVE_ROUTINE_NAME("miset_valid_range"); /* Get the type information for the variable */ if (miget_datatype(cdfid, imgid, &datatype, &is_signed) == MI_ERROR) MI_RETURN(MI_ERROR); /* Cast to the appropriate type and save. Originally, it was thought that casting to the type of the image variable would be a good idea because NetCDF says that it should. Unfortunately, this breaks compatibility in some cases with programs linked with old minc libraries, so we only cast for floats to avoid rounding problems (cast from double to float can put values out of range) - for everything else double is used. */ attname = MIvalid_range; switch (datatype) { case NC_FLOAT: fval[0] = valid_range[0]; fval[1] = valid_range[1]; status = ncattput(cdfid, imgid, attname, datatype, 2, fval); break; default: status = ncattput(cdfid, imgid, attname, NC_DOUBLE, 2, valid_range); break; } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miget_image_range @INPUT : cdfid - cdf file id @OUTPUT : image_range - array containing min and max of image-min/max for the entire file @RETURNS : MI_ERROR when an error occurs. @DESCRIPTION: Gets the image range for a file - that is, the maximum image-max value and the minimum image-min value. For float images, ensures that values are cast to float to ensure that they are correctly truncated. If the range cannot be found, then use the default values for int images and valid_range for floating-point images. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines. @CREATED : October 19, 2001 @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miget_image_range(int cdfid, double image_range[]) { int oldncopts; /* For saving value of ncopt */ int vid[2]; /* Variable ids for min and max */ int imgid; /* Image variable id */ nc_type datatype; /* Type of image variable */ int is_signed; /* Indicates if image variable is signed */ int is_float, no_range_found; /* Flags */ int imm; /* For looping over min and max */ int ndims; /* Number of dimensions of variable */ int idim; /* For looping over dimensions */ int dim[MAX_VAR_DIMS]; /* Dimension ids of variable */ long ientry; /* For stepping through values */ long size; /* Size of min and max variables */ long start[MAX_VAR_DIMS]; /* Start of variable */ long count[MAX_VAR_DIMS]; /* Dimension sizes */ double *buffer; /* Pointer to buffer for min/max values */ MI_SAVE_ROUTINE_NAME("miget_image_range"); /* Set default values for image_range */ image_range[0] = MI_DEFAULT_MIN; image_range[1] = MI_DEFAULT_MAX; /* Get the image-min/max variable ids */ oldncopts=ncopts; ncopts=0; vid[0] = ncvarid(cdfid, MIimagemin); vid[1] = ncvarid(cdfid, MIimagemax); ncopts = oldncopts; /* Get the type information for the image variable */ if ( ((imgid = ncvarid(cdfid, MIimage)) == MI_ERROR) || (miget_datatype(cdfid, imgid, &datatype, &is_signed) == MI_ERROR) ) MI_RETURN(MI_ERROR); /* No max/min variables, so use valid_range values for floats if it is set and defaults otherwise */ if ((vid[0] == MI_ERROR) || (vid[1] == MI_ERROR)) { /* Check for a floating-point type - if it is, try to get the valid_range. If the valid_range was set to full range for the type, then that means that the valid range was probably not set (and if it was, it was not particularly reasonable). */ is_float = (datatype == NC_FLOAT || datatype == NC_DOUBLE); no_range_found = FALSE; if (is_float) { if (miget_valid_range(cdfid, imgid, image_range) == MI_ERROR) MI_RETURN(MI_ERROR); no_range_found = (datatype == NC_FLOAT && image_range[1] == FLT_MAX) || (datatype == NC_DOUBLE && image_range[1] == DBL_MAX); } /* If it is not a float, or if the valid range was not set, then use the default. */ if (!is_float || no_range_found) { image_range[0] = MI_DEFAULT_MIN; image_range[1] = MI_DEFAULT_MAX; } } /* If the variables are there then get the max and min and fastest varying dimension */ else { /* Set initial values */ image_range[0] = DBL_MAX; image_range[1] = -DBL_MAX; /* Loop over min and max */ for (imm=0; imm<2; imm++) { /* Get dimension list */ MI_CHK_ERR(ncvarinq(cdfid, vid[imm], NULL, NULL, &ndims, dim, NULL)) /* Loop through dimensions, getting dimension sizes and total min/max variable size */ size=1; /* Size of MIimagemin/max variable */ for (idim=0; idim0) { if (ncattget(cdfid, parent_varid, MIchildren, child_list) == MI_ERROR) { FREE(child_list); milog_message(MI_MSG_READATTR, MIchildren); MI_RETURN(MI_ERROR); } if (child_list[child_list_size-1] == '\0') child_list_size--; /* Copy the child list element separator (only if there are other elements in the list */ (void) strcpy(&child_list[child_list_size], MI_CHILD_SEPARATOR); child_list_size += strlen(MI_CHILD_SEPARATOR); } /* Get pointer to name of new child */ new_child = &child_list[child_list_size]; /* Add the new child name to the list */ if (ncvarinq(cdfid, child_varid, new_child, NULL, NULL, NULL, NULL) == MI_ERROR) { FREE(child_list); MI_RETURN_ERROR(MI_ERROR); } /* Check for multiple copies of child */ if (strstr(child_list, new_child) != new_child) { child_list_size -= strlen(MI_CHILD_SEPARATOR); child_list[child_list_size] = '\0'; } /* Put the attribute MIchildren */ if (miattputstr(cdfid, parent_varid, MIchildren, child_list) == MI_ERROR) { FREE(child_list); MI_RETURN_ERROR(MI_ERROR); } /* Get the parent variable name */ if (ncvarinq(cdfid, parent_varid, child_list, NULL, NULL, NULL, NULL) == MI_ERROR) { FREE(child_list); MI_RETURN_ERROR(MI_ERROR); } /* Put the attribute MIparent */ if (miattputstr(cdfid, child_varid, MIparent, child_list) == MI_ERROR) { FREE(child_list); MI_RETURN_ERROR(MI_ERROR); } FREE(child_list); MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : micreate_std_variable @INPUT : cdfid - cdf file id name - name of standard variable to create datatype - type of data to store (see ncvardef) ndims - number of dimensions of variable (see ncvardef) dim - vector of variable dimensions (see ncvardef) @OUTPUT : (none) @RETURNS : id of created variable, or MI_ERROR if an error occurs @DESCRIPTION: Creates a standard MINC variable by calling ncvardef and then sets default attributes. The standard variables are identified by name, so an unrecognised name produces an error. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : August 5, 1992 @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int micreate_std_variable(int cdfid, char *name, nc_type datatype, int ndims, int dim[]) { int varid; /* Created variable id */ MI_SAVE_ROUTINE_NAME("micreate_std_variable"); /* Check to see if it is a standard dimension */ if (MI_is_in_list(name, dimvarlist)) { MI_CHK_ERR(varid=MI_create_dim_variable(cdfid, name, datatype, ndims)) } /* Check for a dimension width */ else if (MI_is_in_list(name, dimwidthlist)) { MI_CHK_ERR(varid=MI_create_dimwidth_variable(cdfid, name, datatype, ndims)) } /* Check for a standard variable or group */ else if (MI_is_in_list(name, varlist)) { if (STRINGS_EQUAL(name, MIimage)) MI_CHK_ERR(varid=MI_create_image_variable(cdfid, name, datatype, ndims, dim)) else if ((STRINGS_EQUAL(name, MIimagemax)) || (STRINGS_EQUAL(name, MIimagemin))) MI_CHK_ERR(varid=MI_create_imaxmin_variable(cdfid, name, datatype, ndims, dim)) else if (STRINGS_EQUAL(name, MIrootvariable)) MI_CHK_ERR(varid=MI_create_root_variable(cdfid, name)) else if (STRINGS_EQUAL(name, MIpatient)) MI_CHK_ERR(varid=MI_create_simple_variable(cdfid, name)) else if (STRINGS_EQUAL(name, MIstudy)) MI_CHK_ERR(varid=MI_create_simple_variable(cdfid, name)) else if (STRINGS_EQUAL(name, MIacquisition)) MI_CHK_ERR(varid=MI_create_simple_variable(cdfid, name)) else { milog_message(MI_MSG_VARNOTSTD, name); MI_RETURN(MI_ERROR); } } /* If not in any list, then return an error */ else { milog_message(MI_MSG_VARNOTSTD, name); MI_RETURN(MI_ERROR); } MI_RETURN(varid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_create_dim_variable @INPUT : cdfid - cdf file id name - name of standard variable to create datatype - type of data to store ndims - number of dimensions - must be 0 or 1 @OUTPUT : (none) @RETURNS : id of created variable, or MI_ERROR if an error occurs @DESCRIPTION: Creates a standard MINC dimension variable by calling ncvardef and then sets default attributes. The standard variables are identified by name, so an unrecognised name produces an error. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : August 5, 1992 @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_create_dim_variable(int cdfid, char *name, nc_type datatype, int ndims) { int dimid; /* Dimension id (for dimensions variables) */ int varid; /* Created variable id */ MI_SAVE_ROUTINE_NAME("MI_create_dim_variable"); /* Check for MIvector_dimension - no associated variable */ if (STRINGS_EQUAL(name, MIvector_dimension)) { milog_message(MI_MSG_VARNOTSTD, name); MI_RETURN(MI_ERROR); } /* Check for ndims being 0 or 1 */ if (ndims>1) { milog_message(MI_MSG_TOOMANYDIMS, 1); MI_RETURN(MI_ERROR); } /* Look for dimension and create the variable */ MI_CHK_ERR(dimid=ncdimid(cdfid, name)) MI_CHK_ERR(varid=ncvardef(cdfid, name, datatype, ndims, &dimid)) /* Standard attributes */ MI_CHK_ERR(miattputstr(cdfid, varid, MIvarid, MI_STDVAR)) MI_CHK_ERR(miattputstr(cdfid, varid, MIvartype, MI_DIMENSION)) MI_CHK_ERR(miattputstr(cdfid, varid, MIversion, MI_CURRENT_VERSION)) /* Add comments for spatial dimensions */ if (STRINGS_EQUAL(name, MIxspace)) {MI_CHK_ERR(miattputstr(cdfid, varid, MIcomments, _("X increases from patient left to right")))} else if (STRINGS_EQUAL(name, MIyspace)) {MI_CHK_ERR(miattputstr(cdfid, varid, MIcomments, _("Y increases from patient posterior to anterior")))} else if (STRINGS_EQUAL(name, MIzspace)) {MI_CHK_ERR(miattputstr(cdfid, varid, MIcomments, _("Z increases from patient inferior to superior")))} /* Dimension attributes */ if (ndims==0) { MI_CHK_ERR(miattputstr(cdfid, varid, MIspacing, MI_REGULAR)) } else { MI_CHK_ERR(miattputstr(cdfid, varid, MIspacing, MI_IRREGULAR)) } if (STRINGS_EQUAL(name, MItime)) MI_CHK_ERR(miattputstr(cdfid, varid, MIalignment, MI_START)) else MI_CHK_ERR(miattputstr(cdfid, varid, MIalignment, MI_CENTRE)) MI_RETURN(varid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_create_dimwidth_variable @INPUT : cdfid - cdf file id name - name of standard variable to create datatype - type of data to store ndims - number of dimensions - must be 0 or 1 @OUTPUT : (none) @RETURNS : id of created variable, or MI_ERROR if an error occurs @DESCRIPTION: Creates a standard MINC dimension width variable by calling ncvardef and then sets default attributes. The standard variables are identified by name, so an unrecognised name produces an error. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : August 5, 1992 @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_create_dimwidth_variable(int cdfid, char *name, nc_type datatype, int ndims) { int dimid; /* Dimension id (for dimensions variables) */ int varid; /* Created variable id */ char string[MAX_NC_NAME]; /* String for dimension name */ char *str; MI_SAVE_ROUTINE_NAME("MI_create_dimwidth_variable"); /* Look for dimension name in name (remove width suffix) */ if ((str=strstr(strcpy(string, name),MI_WIDTH_SUFFIX)) == NULL) { milog_message(MI_MSG_DIMWIDTH); MI_RETURN(MI_ERROR); } *str='\0'; /* Check for ndims being 0 or 1 */ if (ndims>1) { milog_message(MI_MSG_TOOMANYDIMS, 1); MI_RETURN(MI_ERROR); } /* Look for the dimension */ MI_CHK_ERR(dimid=ncdimid(cdfid, string)) /* Create the variable and set defaults */ MI_CHK_ERR(varid=ncvardef(cdfid, name, datatype, ndims, &dimid)) MI_CHK_ERR(miattputstr(cdfid, varid, MIvarid, MI_STDVAR)) MI_CHK_ERR(miattputstr(cdfid, varid, MIvartype, MI_DIM_WIDTH)) MI_CHK_ERR(miattputstr(cdfid, varid, MIversion, MI_CURRENT_VERSION)) if (ndims==0) { MI_CHK_ERR(miattputstr(cdfid, varid, MIspacing, MI_REGULAR)) } else { MI_CHK_ERR(miattputstr(cdfid, varid, MIspacing, MI_IRREGULAR)) } MI_CHK_ERR(miattputstr(cdfid, varid, MIfiltertype, MI_SQUARE)) MI_RETURN(varid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_create_image_variable @INPUT : cdfid - cdf file id name - name of standard variable to create datatype - type of data to store (see ncvardef) ndims - number of dimensions of variable (see ncvardef) dim - vector of variable dimensions (see ncvardef) @OUTPUT : (none) @RETURNS : id of created variable, or MI_ERROR if an error occurs @DESCRIPTION: Creates a standard MINC image variable by calling ncvardef and then sets default attributes. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : August 6, 1992 @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_create_image_variable(int cdfid, char *name, nc_type datatype, int ndims, int dim[]) { int varid; /* Created variable id */ int max_varid; /* Variable id for dimensional attribute */ int min_varid; /* Variable id for dimensional attribute */ int maxmin_ndims; /* Number of dimensions in max/min variable */ int maxmin_dim[MAX_VAR_DIMS]; /* Dimensions of max/min variable */ int oldncopts; /* For saving and restoring ncopts */ MI_SAVE_ROUTINE_NAME("MI_create_image_variable"); /* Look to see if MIimagemax or MIimagemin exist for dimension checking and pointers */ oldncopts=ncopts; ncopts=0; max_varid=ncvarid(cdfid, MIimagemax); min_varid=ncvarid(cdfid, MIimagemin); ncopts=oldncopts; if (max_varid != MI_ERROR) { /* Get MIimagemax dimensions */ MI_CHK_ERR(ncvarinq(cdfid, max_varid, NULL, NULL, &maxmin_ndims, maxmin_dim, NULL)) MI_CHK_ERR(MI_verify_maxmin_dims(cdfid, ndims, dim, maxmin_ndims, maxmin_dim)) } if (min_varid != MI_ERROR) { /* Get MIimagemin dimensions */ MI_CHK_ERR(ncvarinq(cdfid, min_varid, NULL, NULL, &maxmin_ndims, maxmin_dim, NULL)) MI_CHK_ERR(MI_verify_maxmin_dims(cdfid, ndims, dim, maxmin_ndims, maxmin_dim)) } /* Create the variable */ MI_CHK_ERR(varid=ncvardef(cdfid, name, datatype, ndims, dim)) /* Standard attributes */ MI_CHK_ERR(MI_add_stdgroup(cdfid, varid)) /* Create pointers to MIimagemax and MIimagemin if they exist */ if (max_varid!=MI_ERROR) MI_CHK_ERR(miattput_pointer(cdfid, varid, MIimagemax, max_varid)) if (min_varid!=MI_ERROR) MI_CHK_ERR(miattput_pointer(cdfid, varid, MIimagemin, min_varid)) MI_RETURN(varid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_create_imaxmin_variable @INPUT : cdfid - cdf file id name - name of standard variable to create datatype - type of data to store (see ncvardef) ndims - number of dimensions of variable (see ncvardef) dim - vector of variable dimensions (see ncvardef) @OUTPUT : (none) @RETURNS : id of created variable, or MI_ERROR if an error occurs @DESCRIPTION: Creates a standard MINC image maximum or minimum dimensional attribute variable by calling ncvardef and then sets default attributes. If MIimage exists, then dimensions are checked (MIimagemax and MIimagemin cannot vary over the first two dimensions of MIimage (or first three if the first is MIvector_dimension)), and a pointer attribute is added to MIimage. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : August 6, 1992 @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_create_imaxmin_variable(int cdfid, char *name, nc_type datatype, int ndims, int dim[]) { int varid; /* Created variable id */ int image_varid; /* Variable id for image */ int image_ndims; /* Number of image dimensions */ int image_dim[MAX_VAR_DIMS]; /* Image dimensions */ void *fillp; /* Pointer to fill value */ int oldncopts; /* For saving and restoring ncopts */ int index; static char fill_b[]={0,1}; static short fill_s[]={0,1}; static int fill_i[]={0,1}; static float fill_f[]={0.0,1.0}; static double fill_d[]={0.0,1.0}; MI_SAVE_ROUTINE_NAME("MI_create_imaxmin_variable"); /* Look to see if MIimage exists for dimension checking and pointers */ oldncopts=ncopts; ncopts=0; image_varid=ncvarid(cdfid, MIimage); ncopts=oldncopts; if (image_varid != MI_ERROR) { /* Get image dimensions */ MI_CHK_ERR(ncvarinq(cdfid, image_varid, NULL, NULL, &image_ndims, image_dim, NULL)) MI_CHK_ERR(MI_verify_maxmin_dims(cdfid, image_ndims, image_dim, ndims, dim)) } /* Create the variable */ MI_CHK_ERR(varid=ncvardef(cdfid, name, datatype, ndims, dim)) /* Standard attributes */ MI_CHK_ERR(miattputstr(cdfid, varid, MIvarid, MI_STDVAR)) MI_CHK_ERR(miattputstr(cdfid, varid, MIvartype, MI_VARATT)) MI_CHK_ERR(miattputstr(cdfid, varid, MIversion, MI_CURRENT_VERSION)) /* Attribute for setting default values to something reasonable */ index = STRINGS_EQUAL(name, MIimagemax) ? 1 : 0; fillp = ((datatype==NC_BYTE) ? (void *) &fill_b[index] : (datatype==NC_SHORT) ? (void *) &fill_s[index] : (datatype==NC_INT) ? (void *) &fill_i[index] : (datatype==NC_FLOAT) ? (void *) &fill_f[index] : (datatype==NC_DOUBLE) ? (void *) &fill_d[index] : (void *) NULL); if (fillp != NULL) { MI_CHK_ERR(ncattput(cdfid, varid, MI_FillValue, datatype, 1, fillp)) } /* Create pointer from MIimage to max or min if MIimage exists */ if (image_varid != MI_ERROR) MI_CHK_ERR(miattput_pointer(cdfid, image_varid, name, varid)) MI_RETURN(varid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_verify_maxmin_dims @INPUT : cdfid - cdf file id image_ndims - number of MIimage dimensions image_dim - image dimensions maxmin_ndims - number of MIimagemax or MIimagemin dimensions maxmin_dim - max/min dimensions @OUTPUT : (none) @RETURNS : MI_ERROR if dimensions don't agree @DESCRIPTION: Verifies that MIimage dimensions and MIimagemax/MIimagemin dimensions agree. MIimagemax/MIimagemin cannot vary over the two fastest varying (last) dimensions of MIimage - three fastest dimensions if MIvector_dimension is the fastest varying dimension of MIimage (this maintains the image nature of MIimage and its dimensional attributes MIimagemax and MIimagemin). @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : August 7, 1992 @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_verify_maxmin_dims(int cdfid, int image_ndims, int image_dim[], int maxmin_ndims, int maxmin_dim[]) { char dimname[MAX_NC_NAME]; int i,j; int nbaddims = 2; /* Number of dimension over which max/min should not vary */ MI_SAVE_ROUTINE_NAME("MI_verify_maxmin_dims"); /* Check to see if last dimension is MIvectordimension */ MI_CHK_ERR(ncdiminq(cdfid, image_dim[image_ndims-1], dimname, NULL)) if (STRINGS_EQUAL(dimname, MIvector_dimension)) nbaddims++; /* Loop through illegal image dimensions (last nbaddims) checking dimensions against maxmin_dim */ for (i=MAX(0,image_ndims-nbaddims); i 0 ) { if (att_val[att_len-1] != '\n') { att_val[att_len] = '\n'; att_len++; } } } /* Append the new history. */ strcpy(att_val + att_len, tm_stamp); r = miattputstr(fd, NC_GLOBAL, MIhistory, att_val); free(att_val); return (r); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_is_in_list @INPUT : string - string for which to look list - list in which to look (must be NULL terminated) @OUTPUT : (none) @RETURNS : TRUE if found, FALSE if not @DESCRIPTION: Searches a list of character strings for string and returns TRUE if the string is in the list. @METHOD : @GLOBALS : @CALLS : @CREATED : August 5, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_is_in_list(char *string, char *list[]) { int i; MI_SAVE_ROUTINE_NAME("MI_is_in_list"); for (i=0; list[i] != NULL; i++) { if (STRINGS_EQUAL(string, list[i])) MI_RETURN(TRUE); } MI_RETURN(FALSE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miget_version @INPUT : (none) @OUTPUT : const char * @RETURNS : A string describing the MINC library version. @DESCRIPTION: Just returns a fixed string. @METHOD : @GLOBALS : @CALLS : @CREATED : December 8 2003 @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI const char * miget_version(void) { return (VERSION); } /* ----------------------------- MNI Header ----------------------------------- @NAME : micreate_ident @INPUT : (none) @OUTPUT : int @RETURNS : The length of the ID string @DESCRIPTION: Creates a (hopefully) unique identifier to associate with a MINC file, by concatenating various information about the system, process, etc. @METHOD : @GLOBALS : @CALLS : @CREATED : 2004-May-11 @MODIFIED : ---------------------------------------------------------------------------- */ #define MI_IDENT_SEP ':' MNCAPI int micreate_ident( char * id_str, size_t length ) { static int identx = 1; /* Static ID counter */ time_t now; struct tm tm_buf; char host_str[128]; char user_str[128]; char *temp_ptr; char time_str[26]; int result; if (gethostname(host_str, sizeof(host_str)) != 0) { strcpy(host_str, "unknown"); } temp_ptr = getenv("LOGNAME"); if (temp_ptr != NULL) { strcpy(user_str, temp_ptr); } else { strcpy(user_str, "nobody"); } time(&now); #ifdef _MSC_VER memcpy(&tm_buf, localtime(&now), sizeof(tm_buf)); #else localtime_r(&now, &tm_buf); #endif strftime(time_str, sizeof(time_str), "%Y.%m.%d.%H.%M.%S", &tm_buf); result = snprintf(id_str, length, "%s%c%s%c%s%c%u%c%u", user_str, MI_IDENT_SEP, host_str, MI_IDENT_SEP, time_str, MI_IDENT_SEP, getpid(), MI_IDENT_SEP, identx++); return (result); } minc-2.2.00/libsrc/minc_error.c0000644000265600003100000002563312027132662013232 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_error.c @DESCRIPTION: File containing routines to do error handling for MINC package. Should be called through macros in minc_private.h @GLOBALS : @CALLS : @CREATED : August 7, 1992 (Peter Neelin) @MODIFIED : * $Log: minc_error.c,v $ * Revision 6.8 2009-01-20 11:58:13 rotor * * CMakeLists.txt: updated version * * Updated Changelog to include releases * * Warning cleanups below * * conversion/dcm2mnc/minc_file.c: fixed printf type * * conversion/dcm2mnc/siemens_to_dicom.c: fixed printf type * * conversion/ecattominc/machine_indep.c: added string.h and fixed * 2 fprintf missing format args * * conversion/micropet/upet2mnc.c: fixed two fprintf format args * * conversion/minctoecat/ecat_write.c: added string.h * * conversion/minctoecat/minctoecat.c: added missing argument to fprintf * * conversion/nifti1/mnc2nii.c: fixed incorrect printf type * * progs/mincview/invert_raw_image.c: added fwrite checking * * Revision 6.7 2008/04/11 05:15:00 rotor * * rewrote error code (Claude) to remove global defs that were * causing build problems with DYLIB on OSX * * Revision 6.6 2008/01/17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.5 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.4 2004/10/15 13:46:15 bert * Minor changes for Windows compatibility * * Revision 6.3 2004/04/27 15:47:25 bert * Move most message text into this file * * Revision 6.2 2001/04/17 18:40:13 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:09 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:38:04 neelin * Release of minc version 0.2 * * Revision 1.7 94/09/28 10:37:16 neelin * Pre-release * * Revision 1.6 93/08/11 12:06:24 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include struct mierror_entry { int level; char *msgfmt; }; /* MINC routine name variable, call depth counter (for keeping track of minc routines calling minc routines) and variable for keeping track of callers ncopts. All of these are for error logging. */ static char *minc_routine_name = "MINC"; static int minc_call_depth = 0; static int minc_trash_var = 0; static struct mierror_entry mierror_table[] = { { MI_MSG_ERROR, "Cannot uncompress the file" }, /* MI_MSG_UNCMPFAIL */ { MI_MSG_ERROR, "Can't write compressed file" }, /* MI_MSG_NOWRITECMP */ { MI_MSG_ERROR, "Unable to open file '%s'" }, /* MI_MSG_OPENFILE */ { MI_MSG_ERROR, "Unable to create file '%s'"}, /* MI_MSG_CREATEFILE */ { MI_MSG_ERROR, "Error closing file"}, /* MI_MSG_CLOSEFILE */ { MI_MSG_WARNING, "Attribute '%s' not found"}, /* MI_MSG_FINDATTR */ { MI_MSG_ERROR, "Attribute '%s' is non-numeric"}, /* MI_MSG_ATTRNOTNUM */ { MI_MSG_ERROR, "Can't read attribute '%s'"}, /* MI_MSG_READATTR */ { MI_MSG_FATAL, "No memory for attribute '%s'"}, /* MI_MSG_NOMEMATTR */ { MI_MSG_ERROR, "Conversion error for attribute '%s'"}, /* MI_MSG_CONVATTR */ { MI_MSG_ERROR, "Attribute '%s' is not a scalar"}, /* MI_MSG_ATTRNOTSCALAR */ { MI_MSG_ERROR, "Attribute '%s' is not a string"}, /* MI_MSG_ATTRNOTSTR */ { MI_MSG_ERROR, "Can't write attribute '%s'"}, /* MI_MSG_WRITEATTR */ { MI_MSG_ERROR, "Can't read variable ID# %d"}, /* MI_MSG_READVAR */ { MI_MSG_ERROR, "Can't write variable ID# %d"}, /* MI_MSG_WRITEVAR */ { MI_MSG_ERROR, "Can't find variable ID# %d"}, /* MI_MSG_FINDVAR */ { MI_MSG_ERROR, "Can't read attribute count"}, /* MI_MSG_ATTRCOUNT */ { MI_MSG_ERROR, "Can't read attribute name"}, /* MI_MSG_ATTRNAME */ { MI_MSG_ERROR, "Can't copy attribute '%s'"}, /* MI_MSG_COPYATTR */ { MI_MSG_ERROR, "Can't read variable information"}, /* MI_MSG_VARINQ */ { MI_MSG_ERROR, "Can't get unlimited dimension"}, /* MI_MSG_UNLIMDIM */ { MI_MSG_ERROR, "Can't get dimension information"}, /* MI_MSG_DIMINQ */ { MI_MSG_ERROR, "Variable already defined with different size"}, /* MI_MSG_VARCONFLICT */ { MI_MSG_ERROR, "Can't define dimension '%s'"}, /* MI_MSG_DIMDEF */ { MI_MSG_ERROR, "Can't define variable '%s'"}, /* MI_MSG_VARDEF */ { MI_MSG_ERROR, "Variables do not match for value copy"}, /* MI_MSG_VARMISMATCH */ { MI_MSG_ERROR, "Variables have dimensions of different size"}, /* MI_MSG_VARDIFFSIZE */ { MI_MSG_ERROR, "Can't read variable count"}, /* MI_MSG_VARCOUNT */ { MI_MSG_ERROR, "Variable '%s' not copied"}, /* MI_MSG_OUTPUTVAR */ { MI_MSG_ERROR, "Error copying variable"}, /* MI_MSG_COPYVAR */ { MI_MSG_ERROR, "Non-numeric datatype"}, /* MI_MSG_VARNOTNUM */ { MI_MSG_FATAL, "Can't allocate %d bytes"}, /* MI_MSG_OUTOFMEM */ { MI_MSG_ERROR, "Attribute '%s' is not a pointer"}, /* MI_MSG_ATTRNOTPTR */ { MI_MSG_ERROR, "Variable '%s' is not a standard MINC variable"}, /* MI_MSG_VARNOTSTD */ { MI_MSG_ERROR, "Bad dimension width suffix"}, /* MI_MSG_DIMWIDTH */ { MI_MSG_ERROR, "Imagemax/min dimensions vary over image dimensions"}, /* MI_MSG_MAXMINVARY */ { MI_MSG_FATAL, "Should not happen!"}, /* MI_MSG_SNH */ { MI_MSG_FATAL, "Unknown integer size %d"}, /* MI_MSG_INTSIZE */ { MI_MSG_FATAL, "Unknown float size %d"}, /* MI_MSG_FLTSIZE */ { MI_MSG_FATAL, "Unknown type class %d"}, /* MI_MSG_TYPECLASS */ { MI_MSG_ERROR, "Function '%s' not implemented"}, /* MI_MSG_NOTIMPL */ { MI_MSG_FATAL, "Unknown type %d"}, /* MI_MSG_BADTYPE */ { MI_MSG_ERROR, "Can't open dataset %s"}, /* MI_MSG_OPENDSET */ { MI_MSG_ERROR, "Can't read dataset %s"}, /* MI_MSG_READDSET */ { MI_MSG_ERROR, "Can't write dataset %s"}, /* MI_MSG_WRITEDSET */ { MI_MSG_ERROR, "Can't use more than %d dimensions"}, /* MI_MSG_TOOMANYDIMS */ { MI_MSG_ERROR, "Attempt to modify an attached image conversion variable"}, /* MI_MSG_ICVATTACHED */ { MI_MSG_ERROR, "Illegal ICV identifier"}, /* MI_MSG_BADICV */ { MI_MSG_ERROR, "Error setting ICV property: %s"}, /* MI_MSG_BADPROP */ { MI_MSG_ERROR, "ICV is not attached"}, /* MI_MSG_ICVNOTATTACHED */ { MI_MSG_ERROR, "Invalid ICV coordinates"}, /* MI_MSG_ICVCOORDS */ { MI_MSG_ERROR, "Illegal variable access operation" } /* MI_MSG_BADOP */ }; SEMIPRIVATE int MI_save_routine_name(char *name) { /* no idea what peter was up to here */ /* minc_trash_var = (((minc_call_depth++)==0) ? MI_save_routine_name(name) : * MI_NOERROR)) */ if( (minc_call_depth++)==0 ) { minc_routine_name = name; minc_trash_var = TRUE; } else { minc_trash_var = MI_NOERROR; } return(TRUE); } SEMIPRIVATE int MI_return(void) { /* no idea what peter was up to here */ /* return( (((--minc_call_depth)!=0) || MI_return()) ? (value) : (value)) */ return( ((--minc_call_depth)!=0) || TRUE ); } SEMIPRIVATE int MI_return_error(void) { /* no idea what peter was up to here */ /* return( (((--minc_call_depth)!=0) || MI_return_error()) ? (error) : (error)) */ if( (--minc_call_depth)==0 ) { MI_LOG_PKG_ERROR2(0, "MINC package entry point"); } return( TRUE ); } SEMIPRIVATE void MI_log_pkg_error2(int p1, char *p2) { (void) fprintf(stderr, "%s: ", minc_routine_name); (void) fprintf(stderr, "%s", p2); (void) fputc('\n', stderr); (void) fflush(stderr); } SEMIPRIVATE void MI_log_pkg_error3(int p1, char *p2, char *p3) { (void) fprintf(stderr, "%s: ", minc_routine_name); (void) fprintf(stderr, p2, p3); (void) fputc('\n', stderr); (void) fflush(stderr); } SEMIPRIVATE void MI_log_sys_error1(char *p1) { char *message; int errnum = errno; (void) fprintf(stderr, "%s", minc_routine_name); (void) fprintf(stderr, "%s", p1); if (errnum == 0) { (void) fputc('\n', stderr); } else { message = strerror(errnum); if (message == NULL) message = "Unknown error"; (void) fprintf(stderr, ": %s\n", message); } (void) fflush(stderr); } /* By default, print all messages of severity error, or worse. */ static struct { int level; char prog[128]; FILE *fp; } _MI_log = { MI_MSG_ERROR, {""}, NULL }; MNCAPI void milog_init(const char *name) { char *fname_str = miget_cfg_str(MICFG_LOGFILE); int level = miget_cfg_int(MICFG_LOGLEVEL); if (fname_str == NULL) { _MI_log.fp = stderr; } else if (!strcmp(fname_str, "stdout") || !strcmp(fname_str, "-")) { _MI_log.fp = stdout; } else { if (*fname_str == '+') { _MI_log.fp = fopen(fname_str + 1, "w+"); } else { _MI_log.fp = fopen(fname_str, "w"); } } if (level != 0) { _MI_log.level = level; } strncpy(_MI_log.prog, name, sizeof (_MI_log.prog)); if (fname_str != NULL) { free(fname_str); } } MNCAPI int milog_set_verbosity(int lvl) { int lvl_prev = _MI_log.level; _MI_log.level = lvl; return (lvl_prev); } MNCAPI int milog_message(mimsgcode_t code, ...) { va_list ap; int lvl; const char *fmt; if (_MI_log.fp == NULL) { _MI_log.fp = stderr; } lvl = mierror_table[code-MI_MSG_BASE].level; fmt = mierror_table[code-MI_MSG_BASE].msgfmt; /* Log the message if the the message priority * is less than the configured priority. Always log fatal errors. */ if ((lvl <= _MI_log.level) || lvl == MI_MSG_FATAL) { if (_MI_log.prog[0] != '\0') { fprintf(_MI_log.fp, "%s ", _MI_log.prog); } fprintf(_MI_log.fp, "(from %s): ", minc_routine_name); va_start(ap, code); vfprintf(_MI_log.fp, fmt, ap); va_end(ap); fprintf(_MI_log.fp, "\n"); fflush(_MI_log.fp); } /* For fatal messages, give up and exit. */ if (lvl == MI_MSG_FATAL) { exit(-1); } return (MI_ERROR); /* Just for convenience */ } minc-2.2.00/libsrc/nd_loop.c0000644000265600003100000001406512027132662012522 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : nd_loop.c @DESCRIPTION: File containing routines for doing n-dimensional looping @METHOD : @GLOBALS : @CREATED : March 10, 1994 (Peter Neelin) @MODIFIED : * $Log: nd_loop.c,v $ * Revision 6.4 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.3 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.2 2004/10/15 13:47:13 bert * Minor changes for Windows compatibility * * Revision 6.1 2002/01/14 21:28:26 neelin * Moved nd_loop, voxel_loop, ParseArgv and time_stamp from ../progs/Proglib * in order to include them in the main minc library. * * Revision 6.1 1999/10/19 14:45:13 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 1.3 1995/02/08 19:31:47 neelin * Moved ARGSUSED statements for irix 5 lint. * * Revision 1.2 1994/12/02 09:19:59 neelin * Added comments to clarify use of routines. * * Revision 1.1 94/12/02 08:40:12 neelin * Initial revision * @COPYRIGHT : Copyright 1994 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #include "nd_loop.h" /* ----------------------------- MNI Header ----------------------------------- @NAME : nd_begin_looping @INPUT : start - vector of indices specifying starting subscript for each dimension ndims - number of dimensions in vector @OUTPUT : current - vector of indices giving current subscript @RETURNS : (none) @DESCRIPTION: Sets up current variable for looping @METHOD : @GLOBALS : @CALLS : @CREATED : October 28, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void nd_begin_looping(long start[], long current[], int ndims) { int idim; for (idim=0; idim < ndims; idim++) { current[idim] = start[idim]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : nd_end_of_loop @INPUT : current - vector of indices giving current subscript end - vector of indices specifying last subscripts plus one ndims - number of dimensions in vector @OUTPUT : (none) @RETURNS : TRUE if end of loop. @DESCRIPTION: Tests for end of a multi-dimensional loop. @METHOD : @GLOBALS : @CALLS : @CREATED : March 10, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int nd_end_of_loop(long current[], long end[], int ndims) /* ARGSUSED */ { return (current[0] >= end[0]); } /* ----------------------------- MNI Header ----------------------------------- @NAME : nd_update_current_count @INPUT : current - vector of indices giving current subscript increment - vector of indices specifying increment for each dimension end - vector of indices specifying last subscripts plus one ndims - number of dimensions in vector @OUTPUT : current_count - vector of indices giving count for current position @RETURNS : (none) @DESCRIPTION: Sets the count so that we don't go past end @METHOD : @GLOBALS : @CALLS : @CREATED : October 28, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void nd_update_current_count(long current[], long increment[], long end[], long current_count[], int ndims) { int idim; for (idim=0; idim < ndims; idim++) { current_count[idim] = increment[idim]; if ((current[idim] + current_count[idim]) > end[idim]) { current_count[idim] = end[idim] - current[idim]; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : nd_increment_loop @INPUT : current - vector of indices giving current subscript start - vector of indices specifying starting subscript for each dimension increment - vector of indices specifying increment for each dimension end - vector of indices specifying last subscripts plus one ndims - number of dimensions in vector @OUTPUT : current - vector of indices giving new subscript @RETURNS : (none) @DESCRIPTION: Does incrementing for multi-dimensional loop @METHOD : @GLOBALS : @CALLS : @CREATED : March 10, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void nd_increment_loop(long current[], long start[], long increment[], long end[], int ndims) { int idim; idim = ndims-1; current[idim] += increment[idim]; while ( (idim>0) && (current[idim] >= end[idim])) { current[idim] = start[idim]; idim--; current[idim] += increment[idim]; } } minc-2.2.00/libsrc/netcdf_convenience.c0000644000265600003100000020121712027132662014704 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : netcdf_convenience.c @DESCRIPTION: File of convenience functions for netcdf routines. There is nothing MINC specific about these routines, they just provide convenient ways of getting netcdf data. The routines MI_convert_type, mivarget and mivarget1 break this rule by making use of the MINC variable attribute MIsigntype to determine the sign of an integer variable. @METHOD : Routines included in this file : public : miexpand_file miopen micreate miclose miattget miattget1 miattgetstr miattputint miattputdbl miattputstr mivarget mivarget1 mivarput mivarput1 miset_coords mitranslate_coords micopy_all_atts micopy_var_def micopy_var_values micopy_all_var_defs micopy_all_var_values micreate_tempfile miget_cfg_bool miget_cfg_int miget_cfg_str private : execute_decompress_command MI_vcopy_action @CREATED : July 27, 1992. (Peter Neelin, Montreal Neurological Institute) @MODIFIED : * $Log: netcdf_convenience.c,v $ * Revision 6.21 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.20 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.19 2005/08/26 21:04:58 bert * Use #if rather than #ifdef with MINC2 symbol * * Revision 6.18 2005/05/20 16:49:51 bert * Avoid direct usage of H5Fis_hdf5(), replace with hdf_access() function * * Revision 6.17 2005/05/20 15:39:45 bert * Remove and/or conditionalize test code for memory-mapped files (see HDF5_MMAP_TEST) * * Revision 6.16 2004/12/14 23:53:46 bert * Get rid of compilation warnings * * Revision 6.15 2004/12/03 21:52:35 bert * Minor changes for Windows build * * Revision 6.14 2004/10/15 13:48:33 bert * Minor changes for Windows compatibility * * Revision 6.13 2004/06/04 18:16:25 bert * Create and add an 'ident' attribute when a file is created * * Revision 6.12 2004/04/30 18:57:39 bert * Explicitly cast return values of NULL to char * where appropriate to make IRIX MIPSpro compiler happy * * Revision 6.11 2004/04/27 15:50:41 bert * The full 2.0 treatment * * Revision 6.10 2004/03/23 21:16:05 bert * Conditionally include fcntl.h * * Revision 6.9 2003/12/01 22:45:58 stever * Check for fork(); use for file decompression if available * * Revision 6.8 2003/03/17 16:15:33 bert * Added micreate_tempfile() to resolve issues with tempfile naming and creation, especially to suppress those annoying GNU linker messages about tempnam() and tmpnam(). * * Revision 6.7 2001/08/20 13:19:15 neelin * Added function miattget_with_sign to allow the caller to specify the sign * of the input attribute since this information is ambiguous. This is * necessary for the valid_range attribute which should have the same sign * as the image data. Modified miget_valid_range to make use of this function. * * Revision 6.6 2001/04/24 14:49:39 neelin * In execute_decompress_command, close all file handles in child after * fork to avoid problems with buffer flushing. * * Revision 6.5 2001/04/17 18:40:14 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.4 2000/09/13 14:02:00 neelin * Added support for bzip files. (Modified patch from Steve Robbins) * * Revision 6.3 2000/02/02 18:43:29 neelin * Fixed bug in miexpand_file that would call fclose with a NULL file handle. * For newer versions of glibc, this would cause a seg fault. * * Revision 6.2 1999/10/19 14:45:11 neelin * Fixed Log subsitutions for CVS * * Revision 6.1 1997/10/06 12:54:08 neelin * Changed call to tmpnam to tempnam so that TMPDIR variable is checked when * creating temporary files. * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.3 1997/04/10 19:22:18 neelin * Removed redefinition of NULL and added pointer casts in appropriate places. * * Revision 3.2 1995/09/29 14:34:09 neelin * Modified micopy_all_atts to handle MI_ERROR being passed in as a varid. * * Revision 3.1 1995/06/12 20:43:52 neelin * Modified miexpand_file and miopen to try adding compression exetensions * to filenames if the first open fails. * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.6 1995/03/14 14:36:35 neelin * Got rid of broken pipe messages from miexpand_file by using exec * in system call. * * Revision 2.5 1995/02/08 19:14:44 neelin * More changes for irix 5 lint. * * Revision 2.4 1995/02/08 19:01:06 neelin * Moved private function declarations from minc_routines.h to appropriate file. * * Revision 2.3 1995/01/24 08:34:11 neelin * Added optional tempfile argument to miexpand_file. * * Revision 2.2 95/01/23 08:28:19 neelin * Changed name of midecompress_file to miexpand_file. * * Revision 2.1 95/01/20 15:20:33 neelin * Added midecompress_file with ability to decompress only the header of a file. * * Revision 2.0 94/09/28 10:38:13 neelin * Release of minc version 0.2 * * Revision 1.11 94/09/28 10:37:19 neelin * Pre-release * * Revision 1.10 93/11/03 12:28:04 neelin * Added miopen, micreate, miclose routines. * miopen will uncompress files before opening them, if needed. * * Revision 1.9 93/08/11 12:06:28 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #if HAVE_UNISTD_H #include #endif #if HAVE_SYS_WAIT_H #include #endif #if HAVE_SYS_STAT_H #include /* For S_IREAD, S_IWRITE */ #endif #include #if MINC2 #undef ncopen #undef ncclose #undef nccreate #include "hdf_convenience.h" #endif /* MINC2 defined */ #if HAVE_FCNTL_H #include #endif /* Private functions */ PRIVATE int execute_decompress_command(char *command, char *infile, char *outfile, int header_only); PRIVATE int MI_vcopy_action(int ndims, long start[], long count[], long nvalues, void *var_buffer, void *caller_data); #if MINC2 /* These flags are used to count miopen() calls which open either an HDF5 * file or a NetCDF file. The exact count is not important; the library * will automatically choose to create a HDF5 output file if only HDF5 * files have been opened. */ static int mi_nc_files = 0; static int mi_h5_files = 0; #endif /* MINC2 defined */ /* ----------------------------- MNI Header ----------------------------------- @NAME : execute_decompress_command @INPUT : command - command to execute infile - input file outfile - output file header_only - ignored @OUTPUT : (none) @RETURNS : status of decompress command (zero = success) @DESCRIPTION: Routine to execute a decompression command on a minc file. The command must take a file name argument and must send to standard output. @METHOD : @GLOBALS : @CALLS : NetCDF routines, external decompression programs @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int execute_decompress_command(char *command, char *infile, char *outfile, int header_only) { char whole_command[1024]; int status; #if !(HAVE_WORKING_FORK && HAVE_SYSTEM && HAVE_POPEN) fprintf(stderr,"Can't decompress %s because system is not available!\n",infile); return 1; #else /* Unix */ /* we now ignore header_only and always uncompress the whole * file as the previous "header only" hack that used to work * on MINC1 files doesn't work reliably with MINC2 */ (void) sprintf(whole_command, "exec %s %s > %s 2> /dev/null", command, infile, outfile); status = system(whole_command); /* Return the status */ return status; #endif /* ifndef unix else */ } /* ----------------------------- MNI Header ----------------------------------- @NAME : miexpand_file @INPUT : path - name of file to open. tempfile - user supplied name for temporary file. If NULL, then the routine generates its own name. header_only - TRUE if only the header needs to be expanded. @OUTPUT : created_tempfile - TRUE if a temporary file was created, FALSE if no file was created (either because the original file was not compressed or because of an error). @RETURNS : name of uncompressed file (either original or a temporary file) or NULL if an error occurred during decompression. The caller must free the string. If a system error occurs on file open or the decompression type is unknown, then the original file name is returned. @DESCRIPTION: Routine to expand a compressed minc file. If the original file is not compressed then its name is returned. If the name of a temporary file is returned, then *created_tempfile is set to TRUE. If header_only is TRUE, then only the header part of the file will be expanded - the data part may or may not be present. @METHOD : @GLOBALS : @CALLS : NetCDF routines, external decompression programs @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI char *miexpand_file(char *path, char *tempfile, int header_only, int *created_tempfile) { typedef enum {BZIPPED, GZIPPED, COMPRESSED, PACKED, ZIPPED, UNKNOWN} Compress_type; int status, oldncopts, first_ncerr, iext; char *newfile, *extension, *compfile; FILE *fp; Compress_type compress_type; static struct { char *extension; Compress_type type; } compression_code_list[] = { {".bz", BZIPPED}, {".bz2", BZIPPED}, {".gz", GZIPPED}, {".Z", COMPRESSED}, {".z", PACKED}, {".zip", ZIPPED} }; static int complist_length = sizeof(compression_code_list) / sizeof(compression_code_list[0]); static int max_compression_code_length = 5; MI_SAVE_ROUTINE_NAME("miexpand_file"); /* We have not created a temporary file yet */ *created_tempfile = FALSE; #if MINC2 if (hdf_access(path)) { newfile = strdup(path); MI_RETURN(newfile); } #endif /* MINC2 defined */ /* Try to open the file (close it again immediately) */ oldncopts = ncopts; ncopts = 0; status = ncopen(path, NC_NOWRITE); if (status != MI_ERROR) { (void) ncclose(status); } ncopts = oldncopts; /* If there is no error then return the original file name */ if (status != MI_ERROR) { newfile = strdup(path); MI_RETURN(newfile); } /* Save the error code */ first_ncerr = ncerr; /* Check for the system error that doesn't show */ if (first_ncerr == NC_NOERR) { fp = fopen(path, "r"); if (fp == NULL) { first_ncerr = NC_SYSERR; } else { (void) fclose(fp); } } /* Get the file extension */ extension = strrchr(path, '.'); if (extension == NULL) { extension = &path[strlen(path)]; } /* Determine the type */ compress_type = UNKNOWN; for (iext = 0; iext < complist_length; iext++) { if (STRINGS_EQUAL(extension, compression_code_list[iext].extension)) { compress_type = compression_code_list[iext].type; break; } } /* If there was a system error and it's not already a compressed file, then maybe there exists a compressed version (with appropriate extension). Loop through the list of extensions. */ compfile = NULL; if ((first_ncerr == NC_SYSERR) && (compress_type == UNKNOWN)) { compfile = MALLOC(strlen(path) + max_compression_code_length + 2, char); for (iext=0; iext < complist_length; iext++) { (void) strcat(strcpy(compfile, path), compression_code_list[iext].extension); fp = fopen(compfile, "r"); if (fp != NULL) { (void) fclose(fp); break; } } if (iext >= complist_length) { FREE(compfile); newfile = strdup(path); MI_RETURN(newfile); } compress_type = compression_code_list[iext].type; path = compfile; } /* If there was a system error or we don't know what to do with the file, then return the original file name */ else if ((first_ncerr == NC_SYSERR) || (compress_type == UNKNOWN)) { newfile = strdup(path); MI_RETURN(newfile); } /* Create a temporary file name */ if (tempfile == NULL) { newfile = micreate_tempfile(); } else { newfile = strdup(tempfile); } *created_tempfile = TRUE; /* Try to use gunzip */ if ((compress_type == GZIPPED) || (compress_type == COMPRESSED) || (compress_type == PACKED) || (compress_type == ZIPPED)) { status = execute_decompress_command("gunzip -c", path, newfile, header_only); } else if (compress_type == BZIPPED) { status = execute_decompress_command("bunzip2 -c", path, newfile, header_only); } /* If that doesn't work, try something else */ if (status != 0) { if (compress_type == COMPRESSED) { status = execute_decompress_command("zcat", path, newfile, header_only); } else if (compress_type == PACKED) { status = execute_decompress_command("pcat", path, newfile, header_only); } } /* Free the compressed file name, if necessary */ if (compfile != NULL) { FREE(compfile); path = NULL; } /* Check for failure to uncompress the file */ if (status != 0) { (void) remove(newfile); *created_tempfile = FALSE; FREE(newfile); milog_message(MI_MSG_UNCMPFAIL); MI_RETURN((char *)NULL); /* Explicit cast needed for MIPSpro cc */ } /* Return the new file name */ MI_RETURN(newfile); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miopen @INPUT : path - name of file to open mode - NC_WRITE or NC_NOWRITE to indicate whether file should be opened for write or read-only. @OUTPUT : (nothing) @RETURNS : file id or MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine ncopen, but will de-compress (temporarily) read-only files as needed. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : November 2, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miopen(char *path, int mode) { int status, oldncopts, created_tempfile; char *tempfile; #if MINC2 int hmode; #endif /* MINC2 defined */ MI_SAVE_ROUTINE_NAME("miopen"); /* Try to open the file */ oldncopts = ncopts; ncopts = 0; status = ncopen(path, mode); ncopts = oldncopts; #if MINC2 if (status != MI_ERROR) { mi_nc_files++; /* Count open netcdf files */ MI_RETURN(status); } if (mode & NC_WRITE) { hmode = H5F_ACC_RDWR; } else { hmode = H5F_ACC_RDONLY; } #if HDF5_MMAP_TEST hmode = (mode & 0x8000); /* !!!! Pass along magic memory-mapping bit */ #endif /* HDF5_MMAP_TEST */ status = hdf_open(path, hmode); /* If there is no error then return */ if (status >= 0) { mi_h5_files++; /* Count open HDF5 files */ MI_RETURN(status); } #endif /* MINC2 defined */ /* If the user wants to modify the file then return an error, since * we don't allow write access to compressed files. */ if (mode & NC_WRITE) { milog_message(MI_MSG_NOWRITECMP); MI_RETURN(MI_ERROR); } /* Try to expand the file */ tempfile = miexpand_file(path, NULL, FALSE, &created_tempfile); /* Check for error */ if (tempfile == NULL) { MI_RETURN(MI_ERROR); } /* Open the temporary file and unlink it so that it will disappear when the file is closed */ oldncopts = ncopts; ncopts = 0; status = ncopen(tempfile, mode); ncopts = oldncopts; #if MINC2 if (status == MI_ERROR) { status = hdf_open(tempfile, hmode); if (status >= 0) { mi_h5_files++; } } else { mi_nc_files++; } #endif /* MINC2 defined */ if (created_tempfile) { (void) remove(tempfile); } if (status < 0) { milog_message(MI_MSG_OPENFILE, tempfile); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : micreate @INPUT : path - name of file to create cmode - NC_CLOBBER or NC_NOCLOBBER @OUTPUT : (nothing) @RETURNS : file id or MI_ERROR (=-1) when an error occurs @DESCRIPTION: A wrapper for routine nccreate, allowing future enhancements. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : November 2, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ #if MINC2 MNCAPI int micreatex(char *path, int cmode, struct mi2opts *opts_ptr) { int fd; MI_SAVE_ROUTINE_NAME("micreate"); if ((cmode & MI2_CREATE_V1) != 0) { fd = nccreate(path, cmode); } else if (miget_cfg_bool(MICFG_FORCE_V2) || (cmode & MI2_CREATE_V2) != 0) { fd = hdf_create(path, cmode, opts_ptr); } else { if (mi_nc_files == 0 && mi_h5_files != 0) { /* Create an HDF5 file. */ fd = hdf_create(path, cmode, opts_ptr); } else { /* Create a NetCDF file. */ fd = nccreate(path, cmode); } } if (fd < 0) { milog_message(MI_MSG_CREATEFILE, path); } else { char ident[128]; micreate_ident(ident, sizeof(ident)); miattputstr(fd, NC_GLOBAL, "ident", ident); miattputstr(fd, NC_GLOBAL, "minc_version", VERSION); } MI_RETURN(fd); } MNCAPI int micreate(char *path, int cmode) { MI_SAVE_ROUTINE_NAME("micreate"); MI_RETURN(micreatex(path, cmode, NULL)); } #else MNCAPI int micreate(char *path, int cmode) { int fd; MI_SAVE_ROUTINE_NAME("micreate"); /* Create a NetCDF file. */ fd = nccreate(path, cmode); if (fd < 0) { milog_message(MI_MSG_CREATEFILE, path); } MI_RETURN(fd); } #endif /* MINC2 not defined */ /* ----------------------------- MNI Header ----------------------------------- @NAME : miclose @INPUT : cdfid - id of file to close @OUTPUT : (nothing) @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: A wrapper for routine ncclose, allowing future enhancements. read-only files as needed. @METHOD : @GLOBALS : @CALLS : NetCDF routines @CREATED : November 2, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miclose(int cdfid) { int status; MI_SAVE_ROUTINE_NAME("miclose"); #if MINC2 if (MI2_ISH5OBJ(cdfid)) { status = hdf_close(cdfid); } else { status = ncclose(cdfid); } #else status = ncclose(cdfid); #endif /* MINC2 not defined */ if (status < 0) { milog_message(MI_MSG_CLOSEFILE); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miattget @INPUT : cdfid - cdf file id varid - variable id name - name of attribute datatype - type that calling routine wants (one of the valid netcdf data types, excluding NC_CHAR) max_length - maximum length to return (number of elements) @OUTPUT : value - value of attribute att_length - actual length of attribute (number of elements) If NULL, then no value is returned. @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine ncattget, but the calling routine specifies the form in which data should be returned (datatype), as well as the maximum number of elements to get. The datatype can only be a numeric type. If the attribute in the file is of type NC_CHAR, then an error is returned. The actual length of the vector is returned in att_length. @METHOD : @GLOBALS : @CALLS : miattget_with_sign @CREATED : July 27, 1992 (Peter Neelin) @MODIFIED : August 20, 2001 (P.N.) - changed to call miattget_with_sign ---------------------------------------------------------------------------- */ MNCAPI int miattget(int cdfid, int varid, char *name, nc_type datatype, int max_length, void *value, int *att_length) { int status; MI_SAVE_ROUTINE_NAME("miattget"); status = miattget_with_sign(cdfid, varid, name, NULL, datatype, NULL, max_length, value, att_length); MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miattget_with_sign @INPUT : cdfid - cdf file id varid - variable id name - name of attribute insign - sign of input attribute. If NULL, then use default. datatype - type that calling routine wants (one of the valid netcdf data types, excluding NC_CHAR) outsign - sign of type for calling routine. If NULL, then use default max_length - maximum length to return (number of elements) @OUTPUT : value - value of attribute att_length - actual length of attribute (number of elements) If NULL, then no value is returned. @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine miattget, but the calling routine specifies the sign of the attribute in the file (which may be ambiguous) as well as the sign of the return type. Sign strings can be MI_SIGNED, MI_UNSIGNED, an empty string or NULL - the latter two mean use the default for the type. @METHOD : @GLOBALS : @CALLS : NetCDF routines and MI_convert_type @CREATED : August 20, 2001 (Peter Neelin) - slightly modified version of old miattget @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miattget_with_sign(int cdfid, int varid, char *name, char *insign, nc_type datatype, char *outsign, int max_length, void *value, int *att_length) { nc_type att_type; /* Type of attribute */ int actual_length; /* Actual length of attribute */ void *att_value; /* Pointer to attribute value */ int status; /* Status of nc routine */ int att_sign, data_sign; /* Integer sign values */ MI_SAVE_ROUTINE_NAME("miattget_with_sign"); /* Inquire about the attribute */ status = ncattinq(cdfid, varid, name, &att_type, &actual_length); if (status < 0) { milog_message(MI_MSG_FINDATTR, name); MI_RETURN(MI_ERROR); } /* Save the actual length of the attribute */ if (att_length != NULL) *att_length = actual_length; /* Check that the attribute type is numeric */ if ((datatype==NC_CHAR) || (att_type==NC_CHAR)) { milog_message(MI_MSG_ATTRNOTNUM, name); MI_RETURN(MI_ERROR); } /* Check to see if the type requested is the same as the attribute type and that the length is less than or equal to max_length. If it is, just get the value. */ if ((datatype == att_type) && (actual_length <= max_length)) { status = ncattget(cdfid, varid, name, value); if (status < 0) { milog_message(MI_MSG_READATTR, name); } MI_RETURN(status); } /* Otherwise, get space for the attribute */ if ((att_value = MALLOC(actual_length * nctypelen(att_type), char)) == NULL) { milog_message(MI_MSG_NOMEMATTR, name); MI_RETURN(MI_ERROR); } /* Get the attribute */ if (ncattget(cdfid, varid, name, att_value)==MI_ERROR) { FREE(att_value); milog_message(MI_MSG_READATTR, name); MI_RETURN(MI_ERROR); } /* Get the signs */ att_sign = MI_get_sign_from_string(att_type, insign); data_sign = MI_get_sign_from_string(datatype, outsign); /* Get the values. Call MI_convert_type with : MI_convert_type(number_of_values, intype, insign, invalues, outtype, outsign, outvalues, icvp) */ status=MI_convert_type(MIN(max_length, actual_length), att_type, att_sign, att_value, datatype, data_sign, value, NULL); FREE(att_value); if (status < 0) { milog_message(MI_MSG_CONVATTR, name); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miattget1 @INPUT : cdfid - cdf file id varid - variable id name - name of attribute datatype - type that calling routine wants (one of the valid netcdf data types, excluding NC_CHAR) @OUTPUT : value - value of attribute @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine miattget, but the its gets only one value of an attribute. If the attribute is longer, then an error occurs. @METHOD : @GLOBALS : @CALLS : NetCDF routines and miattget @CREATED : July 27, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miattget1(int cdfid, int varid, char *name, nc_type datatype, void *value) { int att_length; /* Actual length of the attribute */ int status; MI_SAVE_ROUTINE_NAME("miattget1"); /* Get the attribute value and its actual length */ status = miattget(cdfid, varid, name, datatype, 1, value, &att_length); if (status < 0) { milog_message(MI_MSG_FINDATTR, name); MI_RETURN(MI_ERROR); } /* Check that the length is 1 */ if (att_length != 1) { milog_message(MI_MSG_ATTRNOTSCALAR, name); MI_RETURN(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miattgetstr @INPUT : cdfid - cdf file id varid - variable id name - name of attribute maxlen - maximum length of string to be copied @OUTPUT : value - string returned @RETURNS : pointer to string value or NULL if an error occurred. @DESCRIPTION: Gets a character attribute, copying up to maxlen characters into value and adding a terminating '\0' if necessary. A pointer to the string is returned to facilitate use. If the attribute is non-character, a NULL pointer is returned. @METHOD : @GLOBALS : @CALLS : NetCDF routines. @CREATED : July 28, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI char *miattgetstr(int cdfid, int varid, char *name, int maxlen, char *value) { nc_type att_type; /* Type of attribute */ int att_length; /* Length of attribute */ char *att_value; /* Pointer to attribute value */ MI_SAVE_ROUTINE_NAME("miattgetstr"); /* Inquire about the attribute */ if (ncattinq(cdfid, varid, name, &att_type, &att_length)==MI_ERROR) { milog_message(MI_MSG_FINDATTR, name); MI_RETURN((char *)NULL); /* Explicit cast for MIPSpro cc */ } /* Check that the attribute type is character */ if (att_type!=NC_CHAR) { milog_message(MI_MSG_ATTRNOTSTR, name); MI_RETURN((char *)NULL); /* Explicit cast for MIPSpro cc */ } /* Check to see if the attribute length is less than maxlen. If it is, just get the value. */ if (att_length <= maxlen) { if (ncattget(cdfid, varid, name, value) == MI_ERROR) { milog_message(MI_MSG_READATTR, name); MI_RETURN((char *)NULL); /* Explicit cast for MIPSpro cc */ } /* Check the last character for a '\0' */ if (value[att_length-1] != '\0') { if (att_length==maxlen) value[att_length-1] = '\0'; else value[att_length] = '\0'; } MI_RETURN(value); } /* Otherwise, get space for the attribute */ if ((att_value = MALLOC(att_length * nctypelen(att_type), char)) ==NULL) { milog_message(MI_MSG_NOMEMATTR, name); MI_RETURN((char *)NULL); /* Explicit cast for MIPSpro cc */ } /* Get the attribute */ if (ncattget(cdfid, varid, name, att_value)==MI_ERROR) { FREE(att_value); milog_message(MI_MSG_READATTR, name); MI_RETURN((char *)NULL); } /* Copy the attribute */ (void) strncpy(value, att_value, (size_t) maxlen-1); value[maxlen-1] = '\0'; /* Free the string */ FREE(att_value); /* Return a pointer to the string */ MI_RETURN(value); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miattputint @INPUT : cdfid - cdf file id varid - variable id name - name of attribute value - integer value for attribute @OUTPUT : (none) @RETURNS : MI_ERROR (=-1) if an error occurs @DESCRIPTION: Convenience routine for calling ncattput with integers. @METHOD : @GLOBALS : @CALLS : NetCDF routines. @CREATED : November 25, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miattputint(int cdfid, int varid, char *name, int value) { int lvalue; int status; MI_SAVE_ROUTINE_NAME("miattputint"); lvalue = value; status = ncattput(cdfid, varid, name, NC_INT, 1, (void *) &lvalue); if (status < 0) { milog_message(MI_MSG_WRITEATTR, name); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miattputdbl @INPUT : cdfid - cdf file id varid - variable id name - name of attribute value - double value for attribute @OUTPUT : (none) @RETURNS : MI_ERROR (=-1) if an error occurs @DESCRIPTION: Convenience routine for calling ncattput with doubles. @METHOD : @GLOBALS : @CALLS : NetCDF routines. @CREATED : August 5, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miattputdbl(int cdfid, int varid, char *name, double value) { int status; MI_SAVE_ROUTINE_NAME("miattputdbl"); status = ncattput(cdfid, varid, name, NC_DOUBLE, 1, (void *) &value); if (status < 0) { milog_message(MI_MSG_WRITEATTR, name); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miattputstr @INPUT : cdfid - cdf file id varid - variable id name - name of attribute value - string value for attribute @OUTPUT : (none) @RETURNS : MI_ERROR (=-1) if an error occurs @DESCRIPTION: Convenience routine for calling ncattput with character strings. @METHOD : @GLOBALS : @CALLS : NetCDF routines. @CREATED : July 28, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int miattputstr(int cdfid, int varid, char *name, char *value) { int status; MI_SAVE_ROUTINE_NAME("miattputstr"); status = ncattput(cdfid, varid, name, NC_CHAR, strlen(value) + 1, (void *) value); if (status < 0) { milog_message(MI_MSG_WRITEATTR, name); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mivarget @INPUT : cdfid - cdf file id varid - variable id start - vector of coordinates of corner of hyperslab count - vector of edge lengths of hyperslab datatype - type that calling routine wants (one of the valid netcdf data types, excluding NC_CHAR) sign - sign that calling routine wants (one of EMPTY_STRING (or NULL) = use default sign MI_SIGNED = signed values MI_UNSIGNED = unsigned values @OUTPUT : values - value of variable @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine ncvarget, but the calling routine specifies the form in which data should be returned (datatype), as well as the sign. The datatype can only be a numeric type. If the variable in the file is of type NC_CHAR, then an error is returned. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int mivarget(int cdfid, int varid, long start[], long count[], nc_type datatype, char *sign, void *values) { int status; MI_SAVE_ROUTINE_NAME("mivarget"); status = MI_varaccess(MI_PRIV_GET, cdfid, varid, start, count, datatype, MI_get_sign_from_string(datatype, sign), values, NULL, NULL); if (status < 0) { milog_message(MI_MSG_READVAR, varid); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mivarget1 @INPUT : cdfid - cdf file id varid - variable id mindex - vector of coordinates of value to get datatype - type that calling routine wants (one of the valid netcdf data types, excluding NC_CHAR) sign - sign that calling routine wants (one of EMPTY_STRING (or NULL) = use default sign MI_SIGNED = signed values MI_UNSIGNED = unsigned values @OUTPUT : value - value of variable @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine ncvarget1, but the calling routine specifies the form in which data should be returned (datatype), as well as the sign. The datatype can only be a numeric type. If the variable in the file is of type NC_CHAR, then an error is returned. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int mivarget1(int cdfid, int varid, long mindex[], nc_type datatype, char *sign, void *value) { int status; long count[MAX_VAR_DIMS]; MI_SAVE_ROUTINE_NAME("mivarget1"); status = MI_varaccess(MI_PRIV_GET, cdfid, varid, mindex, miset_coords(MAX_VAR_DIMS, 1L, count), datatype, MI_get_sign_from_string(datatype, sign), value, NULL, NULL); if (status < 0) { milog_message(MI_MSG_READVAR, varid); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mivarput @INPUT : cdfid - cdf file id varid - variable id start - vector of coordinates of corner of hyperslab count - vector of edge lengths of hyperslab datatype - type that calling routine is passing (one of the valid netcdf data types, excluding NC_CHAR) sign - sign that calling routine is passing (one of EMPTY_STRING (or NULL) = use default sign MI_SIGNED = signed values MI_UNSIGNED = unsigned values values - value of variable @OUTPUT : (none) @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine ncvarput, but the calling routine specifies the form in which data is passes (datatype), as well as the sign. The datatype can only be a numeric type. If the variable in the file is of type NC_CHAR, then an error is returned. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int mivarput(int cdfid, int varid, long start[], long count[], nc_type datatype, char *sign, void *values) { int status; MI_SAVE_ROUTINE_NAME("mivarput"); status = MI_varaccess(MI_PRIV_PUT, cdfid, varid, start, count, datatype, MI_get_sign_from_string(datatype, sign), values, NULL, NULL); if (status < 0) { milog_message(MI_MSG_WRITEVAR, varid); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mivarput1 @INPUT : cdfid - cdf file id varid - variable id mindex - vector of coordinates of value to put datatype - type that calling routine is passing (one of the valid netcdf data types, excluding NC_CHAR) sign - sign that calling routine is passing (one of EMPTY_STRING (or NULL) = use default sign MI_SIGNED = signed values MI_UNSIGNED = unsigned values @OUTPUT : value - value of variable @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Similar to routine ncvarput1, but the calling routine specifies the form in which data is passed (datatype), as well as the sign. The datatype can only be a numeric type. If the variable in the file is of type NC_CHAR, then an error is returned. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int mivarput1(int cdfid, int varid, long mindex[], nc_type datatype, char *sign, void *value) { int status; long count[MAX_VAR_DIMS]; MI_SAVE_ROUTINE_NAME("mivarput1"); status = MI_varaccess(MI_PRIV_PUT, cdfid, varid, mindex, miset_coords(MAX_VAR_DIMS, 1L, count), datatype, MI_get_sign_from_string(datatype, sign), value, NULL, NULL); if (status < 0) { milog_message(MI_MSG_WRITEVAR, varid); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : miset_coords @INPUT : nvals - number of values in coordinate vector to set value - value to which coordinates should be set @OUTPUT : coords - coordinate vector @RETURNS : pointer to coords. @DESCRIPTION: Sets nvals entries of the vector coords to value. @METHOD : @GLOBALS : @CALLS : @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI long *miset_coords(int nvals, long value, long coords[]) { int i; MI_SAVE_ROUTINE_NAME("miset_coords"); for (i=0; iincdfid, ptr->invarid, start, count, var_buffer); if (status < 0) { MI_RETURN(MI_ERROR); } /* Put values to output variable */ status = ncvarput(ptr->outcdfid, ptr->outvarid, start, count, var_buffer); if (status < 0) { MI_RETURN(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : micopy_all_var_defs @INPUT : incdfid - input cdf file id outcdfid - output cdf file id nexclude - number of values in array excluded_vars excluded_vars - array of variable id's in incdfid that should not be copied @OUTPUT : (none) @RETURNS : MI_ERROR (=-1) if an error occurs. @DESCRIPTION: Copies all variable definitions in file incdfid to file outcdfid (including attributes), excluding the variable id's listed in array excluded_vars. File outcdfid must be in define mode. @METHOD : @GLOBALS : @CALLS : NetCDF routines. @CREATED : August 3, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int micopy_all_var_defs(int incdfid, int outcdfid, int nexclude, int excluded_vars[]) { int num_vars; /* Number of variables in input file */ int varid; /* Variable id counter */ int i; int status; MI_SAVE_ROUTINE_NAME("micopy_all_var_defs"); /* Find out how many variables there are in the file and loop through them */ status = ncinquire(incdfid, NULL, &num_vars, NULL, NULL); if (status < 0) { MI_RETURN(MI_ERROR); } /* Loop through variables, copying them */ for (varid=0; varid=nexclude) { status = micopy_var_def(incdfid, varid, outcdfid); if (status < 0) { MI_RETURN(MI_ERROR); } } } /* Copy global attributes */ for (i=0; i=nexclude) { status = micopy_all_atts(incdfid, NC_GLOBAL, outcdfid, NC_GLOBAL); } MI_RETURN(status); } /* ----------------------------- MNI Header ----------------------------------- @NAME : micopy_all_var_values @INPUT : incdfid - input cdf file id outcdfid - output cdf file id nexclude - number of values in array excluded_vars excluded_vars - array of variable id's in incdfid that should not be copied @OUTPUT : (none) @RETURNS : MI_ERROR (=-1) if an error occurs. @DESCRIPTION: Copies all variable values in file incdfid to file outcdfid, excluding the variable id's listed in array excluded_vars. File outcdfid must be in data mode. Usually called after micopy_all_var_defs with the same arguments. If a variable to be copied is not defined properly in outcdfid, then an error occurs. @METHOD : @GLOBALS : @CALLS : NetCDF routines. @CREATED : @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int micopy_all_var_values(int incdfid, int outcdfid, int nexclude, int excluded_vars[]) { int num_vars; /* Number of variables in input file */ int varid; /* Variable id counter */ int outvarid; /* Output variable id */ char name[MAX_NC_NAME]; /*Variable name */ int i; int status; MI_SAVE_ROUTINE_NAME("micopy_all_var_values"); /* Find out how many variables there are in the file and loop through them */ status = ncinquire(incdfid, NULL, &num_vars, NULL, NULL); if (status < 0) { milog_message(MI_MSG_VARCOUNT); MI_RETURN(MI_ERROR); } /* Loop through variables, copying them */ for (varid=0; varid=nexclude) { /* Get the input variable's name */ status = ncvarinq(incdfid, varid, name, NULL, NULL, NULL, NULL); if (status < 0) { milog_message(MI_MSG_VARINQ); MI_RETURN(MI_ERROR); } /* Look for it in the output file */ outvarid = ncvarid(outcdfid, name); if (outvarid < 0) { milog_message(MI_MSG_OUTPUTVAR, name); MI_RETURN(MI_ERROR); } /* Copy the values */ status = micopy_var_values(incdfid, varid, outcdfid, outvarid); if (status < 0) { MI_RETURN(MI_ERROR); } } } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : micreate_tempfile @INPUT : void @OUTPUT : (none) @RETURNS : Pointer to filename (which must be freed), or NULL if an error occurs. @DESCRIPTION: Creates a temporary file (which is initially CLOSED). @METHOD : Unnecessarily convoluted, I suppose... See comments. @GLOBALS : @CALLS : Standard POSIX/UNIX routines @CREATED : 07-March-2003 by bert@bic.mni.mcgill.ca @MODIFIED : ---------------------------------------------------------------------------- */ /* Force P_tmpdir to be something reasonable. */ #if !defined(P_tmpdir) #define P_tmpdir "/var/tmp" #endif /* P_tmpdir not defined */ MNCAPI char * micreate_tempfile(void) { int tmp_fd; char *tmpfile_ptr; #if defined (HAVE_MKSTEMP) /* Best-case scenario (so far...) * mkstemp() creates a file immediately, minimizing the race * conditions that exist when using the other functions. These race * conditions can lead to small security holes (and large, annoying * GNU linker messages). * * The only catch is that mkstemp() does not automatically put the * file in the TMPDIR directory (or some other appropriate place). * So I more-or-less emulate that behavior here. */ const char pat_str[] = "/minc-XXXXXX"; char *tmpdir_ptr; if ((tmpdir_ptr = getenv("TMPDIR")) == NULL) { tmpdir_ptr = P_tmpdir; } tmpfile_ptr = malloc(strlen(tmpdir_ptr) + sizeof (pat_str)); if (tmpfile_ptr == NULL) { return (NULL); } strcpy(tmpfile_ptr, tmpdir_ptr); strcat(tmpfile_ptr, pat_str); tmp_fd = mkstemp(tmpfile_ptr); /* Creates the file if possible. */ #elif defined (HAVE_TEMPNAM) /* Second-best case. While not completely avoiding the race condition, * this approach should at least have the nice property of putting the * tempfile in the right directory (on IRIX and Linux, at least - on * some systems tempnam() may not consult the TMPDIR environment variable). */ tmpfile_ptr = tempnam(NULL, "minc-"); if (tmpfile_ptr == NULL) { return (NULL); } tmp_fd = open(tmpfile_ptr, O_CREAT | O_EXCL | O_RDWR, S_IWRITE | S_IREAD); #elif defined (HAVE_TMPNAM) /* Worst case. tmpnam() is apparently the worst of all possible worlds * here. It doesn't allow any way to force a particular directory, * and it doesn't avoid the race condition. But volume_io used it for * years, so I see no reason to disallow this case for systems that * might not define the above two functions (whether any such systems * exist is unclear to me). */ tmpfile_ptr = malloc(L_tmpnam + 1); if (tmpfile_ptr == NULL) { return (NULL); } if (tmpnam(tmpfile_ptr) == NULL) { free(tmpfile_ptr); return (NULL); } tmp_fd = open(tmpfile_ptr, O_CREAT | O_EXCL | O_RDWR, S_IWRITE | S_IREAD); #else #error "System defines neither mkstemp(), tempnam(), nor tmpnam()" #endif /* Neither HAVE_MKSTEMP, HAVE_TEMPNAM, or HAVE_TMPNAM defined. */ /* If we get here, tmp_fd should have been opened and the file * created. Now go ahead and close the file. */ if (tmp_fd >= 0) { close(tmp_fd); } else { free(tmpfile_ptr); tmpfile_ptr = NULL; } return (tmpfile_ptr); } /** Simple function to read a user's .mincrc file, if present. */ static int miread_cfg(const char *name, char *buffer, int maxlen) { FILE *fp; int result = 0; char *home_ptr = getenv("HOME"); char path[256]; if (home_ptr != NULL) { strcpy(path, home_ptr); } else { path[0] = '\0'; } strcat(path, "/.mincrc"); if ((fp = fopen(path, "r")) != NULL) { while (fgets(buffer, maxlen, fp)) { if (buffer[0] == '#') { continue; } if (!strncasecmp(buffer, name, strlen(name))) { char *tmp = strchr(buffer, '='); if (tmp != NULL) { tmp++; while (isspace(*tmp)) { tmp++; } strncpy(buffer, tmp, maxlen); result = 1; break; } } } fclose(fp); } return (result); } int miget_cfg_bool(const char *name) { char buffer[128]; char *var_ptr; if ((var_ptr = getenv(name)) != NULL) { strncpy(buffer, var_ptr, sizeof (buffer)); } else { if (!miread_cfg(name, buffer, sizeof (buffer))) { return (0); } } return (atoi(buffer) != 0); } int miget_cfg_int(const char *name) { char buffer[128]; char *var_ptr; if ((var_ptr = getenv(name)) != NULL) { strncpy(buffer, var_ptr, sizeof (buffer)); } else { if (!miread_cfg(name, buffer, sizeof(buffer))) { return (0); } } return (atoi(buffer)); } char * miget_cfg_str(const char *name) { char buffer[256]; char *var_ptr; if ((var_ptr = getenv(name)) != NULL) { strncpy(buffer, var_ptr, sizeof(buffer)); } else { if (!miread_cfg(name, buffer, sizeof(buffer))) { return (NULL); } } return (strdup(buffer)); }minc-2.2.00/libsrc/time_stamp.c0000644000265600003100000000743612027132662013236 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : time_stamp.c @DESCRIPTION: File containing routine to create a time stamp string. @METHOD : @CREATED : February 1, 1993 (Peter Neelin) @MODIFIED : * $Log: time_stamp.c,v $ * Revision 6.4 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.3 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.2 2004/10/15 13:46:51 bert * Minor changes for Windows compatibility * * Revision 6.1 2002/01/14 21:28:26 neelin * Moved nd_loop, voxel_loop, ParseArgv and time_stamp from ../progs/Proglib * in order to include them in the main minc library. * * Revision 6.2 1999/10/19 15:57:18 neelin * Fixed log message containing log substitution * * Revision 6.1 1999/10/19 14:45:14 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:34:30 neelin * Release of minc version 0.2 * * Revision 1.4 94/09/28 10:34:20 neelin * Pre-release * * Revision 1.3 93/08/04 13:03:56 neelin * Added RCS Log to keep track of modifications in source * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #include #include /* ----------------------------- MNI Header ----------------------------------- @NAME : time_stamp @INPUT : argc - number of arguments argv - list of arguments @OUTPUT : @RETURNS : pointer to string containing time stamp. @DESCRIPTION: Function to produce a time stamp string for a program. Returns a string of the form "date > command". The command is simply the concatenation of argv elements. @METHOD : @GLOBALS : @CALLS : @CREATED : February 1, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ char *time_stamp(int argc, char *argv[]) { char *str, *the_time; int length, i, last; static char separator[]={">>>"}; time_t timer; /* Get the time, overwriting newline */ timer = time(NULL); the_time = ctime(&timer); /* Get the total length of the string and allocate space */ length=strlen(the_time) + strlen(separator) + 2; for(i=0; i #include "type_limits.h" /* Private functions */ PRIVATE int MI_var_action(int ndims, long var_start[], long var_count[], long nvalues, void *var_buffer, void *caller_data); PRIVATE int MI_get_sign(nc_type datatype, int sign); /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_varaccess @INPUT : operation - either MI_PRIV_GET or MI_PRIV_PUT, indicating whether the routine should get or put data from/to a cdf file cdfid - cdf file id varid - variable id start - vector of coordinates of corner of hyperslab count - vector of edge lengths of hyperslab datatype - type that calling routine wants (one of the valid netcdf data types, excluding NC_CHAR) sign - sign that the calling routine wants (one of MI_PRIV_SIGNED, MI_PRIV_UNSIGNED, MI_PRIV_DEFAULT). bufsize_step - vector of buffer size steps wanted by caller (MI_var_loop will try, but no guarantees); if NULL, then 1 is assumed. For the first index that cannot be read in one piece, the allocated buffer will tend to have the count of as a multiple of the corresponding value in this vector. icvp - pointer to icv structure (image conversion variable) If NULL, then icvp->do_scale and icvp->do_dimconvert are assumed to be FALSE. icvp->do_scale - boolean indicating whether scaling should be done. If so, then outvalue = icvp->scale * (double) invalue + icvp->offset icvp->scale - (see do_scale) icvp->offset - (see do_scale) icvp->do_dimconvert - boolean indicating whether the dimension conversion routine should be called icvp->dimconvert_func - dimension conversion routine values - values to store in variable (for put) @OUTPUT : values - values to get from variable (for get) @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Routine to do work for getting/putting and converting the type of variable values. Similar to routine ncvarget/ ncvarput but the calling routine specifies the form in which data should be returned/passed (datatype), as well as the sign. The datatype can only be a numeric type. If the variable in the file is of type NC_CHAR, then an error is returned. Values can optionally be scaled (for image conversion routines) by setting icvp->do_scale to TRUE and using icvp->scale and icvp->offset. Dimensional conversion can be done be setting icvp->do_dimconvert to TRUE and passing a function to be called (icvp->dimconvert_func). @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ SEMIPRIVATE int MI_varaccess(int operation, int cdfid, int varid, long start[], long count[], nc_type datatype, int sign, void *values, int *bufsize_step, mi_icv_type *icvp) { mi_varaccess_type strc; /* Structure of values for functions */ int ndims; /* Number of variable dimensions */ char stringa[MI_MAX_ATTSTR_LEN]; /* String for attribute value */ char *string = stringa; int oldncopts; /* Save old value of ncopts */ MI_SAVE_ROUTINE_NAME("MI_varaccess"); /* Check to see if ivc structure was passed and set variables needed by this routine */ if (icvp == NULL) { strc.do_scale = FALSE; strc.do_dimconvert = FALSE; strc.do_fillvalue = FALSE; } else { strc.do_scale = icvp->do_scale; strc.do_dimconvert = icvp->do_dimconvert; strc.do_fillvalue = icvp->do_fillvalue; } /* Inquire about the variable */ MI_CHK_ERR(ncvarinq(cdfid, varid, NULL, &(strc.var_type), &ndims, NULL, NULL)) /* Check that the variable type is numeric */ if ((datatype==NC_CHAR) || (strc.var_type==NC_CHAR)) { milog_message(MI_MSG_VARNOTNUM); MI_RETURN(MI_ERROR); } /* Try to find out the sign of the variable using MIsigntype. To avoid programs dying unexpectedly, we must change ncopts, then restore it */ oldncopts = ncopts; ncopts = 0; string=miattgetstr(cdfid, varid, MIsigntype, MI_MAX_ATTSTR_LEN, string); ncopts = oldncopts; /* Get the signs */ strc.var_sign = MI_get_sign_from_string(strc.var_type, string); strc.call_sign = MI_get_sign(datatype, sign); /* Check to see if the type requested is the same as the variable type, the signs are the same and no dimension conversion is needed. If so, just get/put the values */ if ((datatype == strc.var_type) && (strc.call_sign == strc.var_sign) && !strc.do_scale && !strc.do_dimconvert && !strc.do_fillvalue) { switch (operation) { case MI_PRIV_GET: MI_CHK_ERR(ncvarget(cdfid, varid, start, count, values)) break; case MI_PRIV_PUT: MI_CHK_ERR(ncvarput(cdfid, varid, start, count, values)) break; default: milog_message(MI_MSG_BADOP); MI_RETURN(MI_ERROR); } MI_RETURN(MI_NOERROR); } /* Otherwise, we have to loop through data. Set up structure and call MI_var_loop */ strc.operation=operation; strc.cdfid=cdfid; strc.varid=varid; strc.call_type=datatype; strc.var_value_size=nctypelen(strc.var_type); strc.call_value_size=nctypelen(strc.call_type); strc.icvp=icvp; strc.start=start; strc.count=count; strc.values=values; MI_CHK_ERR( MI_var_loop(ndims, start, count, strc.var_value_size, bufsize_step, MI_MAX_VAR_BUFFER_SIZE, (void *) &strc, MI_var_action) ) MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_var_action @INPUT : ndims - number of dimensions var_start - coordinate vector of corner of hyperslab var_count - vector of edge lengths of hyperslab nvalues - number of values in hyperslab var_buffer - pointer to variable buffer caller_data - pointer to data from MI_varaccess @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Buffer action routine to be called by MI_var_loop, for use by MI_varaccess. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : July 30, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_var_action(int ndims, long var_start[], long var_count[], long nvalues, void *var_buffer, void *caller_data) /* ARGSUSED */ { mi_varaccess_type *ptr; /* Pointer to data from MI_varaccess */ int status; /* Status returned by function call */ MI_SAVE_ROUTINE_NAME("MI_var_action"); ptr=(mi_varaccess_type *) caller_data; /* Get/put values and do conversions, etc. */ switch (ptr->operation) { case MI_PRIV_GET: status=ncvarget(ptr->cdfid, ptr->varid, var_start, var_count, var_buffer); if (status != MI_ERROR) { /* If doing dimension conversion, let dimconvert function do all the work, including type conversion */ if (!ptr->do_dimconvert) { status=MI_convert_type(nvalues, ptr->var_type, ptr->var_sign, var_buffer, ptr->call_type, ptr->call_sign, ptr->values, ptr->icvp); } else { status=(*(ptr->icvp->dimconvert_func))(ptr->operation, ptr->icvp, ptr->start, ptr->count, ptr->values, var_start, var_count, var_buffer); } } break; case MI_PRIV_PUT: /* If doing dimension conversion, let dimconvert function do all the work, including type conversion */ if (!ptr->do_dimconvert) { status=MI_convert_type(nvalues, ptr->call_type, ptr->call_sign, ptr->values, ptr->var_type, ptr->var_sign, var_buffer, ptr->icvp); } else { status=(*(ptr->icvp->dimconvert_func))(ptr->operation, ptr->icvp, ptr->start, ptr->count, ptr->values, var_start, var_count, var_buffer); } if (status != MI_ERROR) { status=ncvarput(ptr->cdfid, ptr->varid, var_start, var_count, var_buffer); } break; default: milog_message(MI_MSG_BADOP); status=MI_ERROR; } /* Check for an error */ MI_CHK_ERR(status) /* Increment the values pointer */ if (!ptr->do_dimconvert) { ptr->values = (void *) ((char *) ptr->values + nvalues*ptr->call_value_size); } MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_var_loop @INPUT : ndims - number of dimensions in variable start - vector of coordinates of corner of hyperslab count - vector of edge lengths of hyperslab value_size - size (in bytes) of each value to be buffered bufsize_step - vector of buffer size steps wanted by caller (MI_var_loop will try, but no guarantees); if NULL, then 1 is assumed. For the first index that cannot be read in one piece, the allocated buffer will tend to have the count of as a multiple of the corresponding value in this vector. max_buffer_size - maximum size (in bytes) of buffer caller_data - pointer to a structure of data to pass to functions action_func - function to do something with each buffer @OUTPUT : (none) @RETURNS : MI_ERROR (=-1) when an error occurs @DESCRIPTION: Routine to loop through a variable's indices, getting data into a buffer and doing something to it. A function pointer is passed that will perform these functions on each buffer. @METHOD : @GLOBALS : @CALLS : NetCDF and MINC routines @CREATED : July 29, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ SEMIPRIVATE int MI_var_loop(int ndims, long start[], long count[], int value_size, int *bufsize_step, long max_buffer_size, void *caller_data, int (*action_func) (int, long [], long [], long, void *, void *)) { long nvalues, newnvalues; /* Number of values in fastest varying dims. Note that any dimensional subscript variables should be long */ int firstdim; /* First dimension that doesn't fit in buffer */ long ntimes; /* Number of firstdim elements that fit in buf */ void *var_buffer; /* Pointer to buffer for variable data */ long var_count[MAX_VAR_DIMS]; /* Count, start and end coordinate */ long var_start[MAX_VAR_DIMS]; /* vectors for getting buffers */ long var_end[MAX_VAR_DIMS]; int i; /* Looping variable - only used for dimension number, not dimension subscript */ MI_SAVE_ROUTINE_NAME("MI_var_loop"); /* Find out how much space we need and then allocate a buffer. To do this we find out how many dimensions will fit in our maximum buffer size. firstdim is the index of the first dimension that won't fit. nvalues is the number of values in the first dimensions that do fit in the buffer. ntimes is the number of times that the first dimensions fit in the buffer. To make things simpler, dimension 0 is always considered to not fit, even if it does. */ nvalues=newnvalues=1; for (firstdim=ndims-1; firstdim>=1; firstdim--) { newnvalues *= count[firstdim]; if (newnvalues*value_size > max_buffer_size) break; nvalues = newnvalues; } if (firstdim<0) { /* Check for 0-dim variable */ firstdim=0; ntimes=1; } else { ntimes = MIN(MI_MAX_VAR_BUFFER_SIZE/(nvalues*value_size), count[firstdim]); /* Try to make ntimes an convenient multiple for the caller */ if ((ntimes != count[firstdim]) && (bufsize_step != NULL)) { ntimes = MAX(1, ntimes - (ntimes % bufsize_step[firstdim])); } } /* Allocate space for variable values */ if ((var_buffer = MALLOC(ntimes*nvalues*value_size, char)) == NULL) { milog_message(MI_MSG_OUTOFMEM); MI_RETURN(MI_ERROR); } /* Create a count variable for the var buffer, with 1s for dimensions that vary slower than firstdim and count[i] for dimensions that vary faster. Set a start variable for the var buffer, equal to start. Set an end variable for the var buffer. */ if (ndims <= 0) { /* Handle zero-dimension variable */ var_start[0]=0; var_end[0]=1; var_count[0]=1; } for (i=0; ifirstdim) ? count[i] : (i==firstdim) ? ntimes : 1; var_start[i] = start[i]; var_end[i] = start[i] + count[i]; } /* Loop through the dimensions, copying buffers, etc. Exit when the slowest varying dimension reaches its limit. */ while (var_start[0] < var_end[0]) { var_count[firstdim] = MIN(ntimes, var_end[firstdim] - var_start[firstdim]); /* Do the stuff on the buffer */ if ((*action_func)(ndims, var_start, var_count, var_count[firstdim]*nvalues, var_buffer, caller_data) == MI_ERROR) { FREE(var_buffer); MI_RETURN_ERROR(MI_ERROR); } /* Increment the start counters */ var_start[firstdim] += var_count[firstdim]; i=firstdim; while ( (i>0) && (var_start[i] >= var_end[i])) { var_start[i] = start[i]; i--; var_start[i]++; } } /* Free the buffer and return */ FREE(var_buffer); MI_RETURN(MI_NOERROR); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_get_sign_from_string @INPUT : type - type of value sign - sign of value (one of MI_EMPTY_STRING, MI_SIGNED or MI_UNSIGNED) @OUTPUT : (none) @RETURNS : either MI_PRIV_SIGNED or MI_PRIV_UNSIGNED @DESCRIPTION: Converts sign string to either MI_PRIV_SIGNED or MI_PRIV_UNSIGNED, as appropriate, by calling MI_get_sign. @METHOD : @GLOBALS : (none) @CALLS : MI_get_sign @CREATED : July 30, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ SEMIPRIVATE int MI_get_sign_from_string(nc_type datatype, char *sign) { MI_SAVE_ROUTINE_NAME("MI_get_sign_from_string"); MI_RETURN(MI_get_sign(datatype, (sign == NULL) || (*sign == '\0') ? MI_PRIV_DEFSIGN : (STRINGS_EQUAL(sign, MI_SIGNED)) ? MI_PRIV_SIGNED : (STRINGS_EQUAL(sign, MI_UNSIGNED)) ? MI_PRIV_UNSIGNED : MI_PRIV_DEFSIGN)); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_get_sign @INPUT : type - type of value sign - sign of value (one of MI_PRIV_DEFSIGN, MI_PRIV_SIGNED or MI_PRIV_UNSIGNED) @OUTPUT : (none) @RETURNS : either MI_PRIV_SIGNED or MI_PRIV_UNSIGNED @DESCRIPTION: Converts sign variable to either MI_PRIV_SIGNED or MI_PRIV_UNSIGNED, as appropriate, if its value is MI_PRIV_DEFSIGN, otherwise the value of sign is returned as is. The default signs are byte : unsigned short : signed int : signed float : signed double : signed @METHOD : @GLOBALS : @CALLS : @CREATED : July 27, 1992 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int MI_get_sign(nc_type datatype, int sign) { MI_SAVE_ROUTINE_NAME("MI_get_sign"); MI_RETURN( ((datatype==NC_FLOAT) || (datatype==NC_DOUBLE)) ? MI_PRIV_SIGNED : ((sign==MI_PRIV_SIGNED) || (sign==MI_PRIV_UNSIGNED)) ? sign : (datatype==NC_BYTE) ? MI_PRIV_UNSIGNED : (datatype==NC_SHORT) ? MI_PRIV_SIGNED : (datatype==NC_INT) ? MI_PRIV_SIGNED : MI_PRIV_SIGNED ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : MI_convert_type @INPUT : number_of_values - number of values to copy intype - type of input values insign - sign of input values (one of MI_PRIV_DEFSIGN, MI_PRIV_SIGNED or MI_PRIV_UNSIGNED) invalues - vector of values outtype - type of output values outsign - sign of output values icvp - pointer to icv structure (if NULL, then icvp->do_scale is assumed to be FALSE) icvp->do_scale - boolean indicating whether scaling should be done. If so, then outvalue = icvp->scale * (double) invalue + icvp->offset icvp->scale - (see do_scale) icvp->offset - (see do_scale) @OUTPUT : outvalues - output values @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Converts the invalues to outvalues according to their type. Types must be numeric. Values out of range are truncated to the nearest value in range. The sign of integer values is given by insign and outsign, which must have values MI_PRIV_DEFSIGN, MI_PRIV_SIGNED or MI_PRIV_UNSIGNED. If it is MI_PRIV_DEFSIGN then the default signs are used (from MI_get_sign) : byte : unsigned short : signed int : signed Note that if a conversion must take place, then all input values are converted to double. Values can be scaled through icvp->scale and icvp->offset by setting icvp->do_scale to TRUE. @METHOD : @GLOBALS : @CALLS : @CREATED : July 27, 1992 (Peter Neelin) @MODIFIED : August 28, 1992 (P.N.) - replaced type conversions with macros ---------------------------------------------------------------------------- */ SEMIPRIVATE int MI_convert_type(long number_of_values, nc_type intype, int insign, void *invalues, nc_type outtype, int outsign, void *outvalues, mi_icv_type *icvp) { int inincr, outincr; /* Pointer increments for arrays */ int insgn, outsgn; /* Signs for input and output */ long i; double dvalue=0.0; /* Temporary double for conversion */ void *inptr, *outptr; /* Pointers to input and output values */ int do_scale; /* Should scaling be done? */ int do_fillvalue; /* Should fillvalue checking be done? */ double fillvalue; /* Value to fill with */ double dmax, dmin; /* Range of legal values */ double epsilon; /* Epsilon for legal values comparisons */ MI_SAVE_ROUTINE_NAME("MI_convert_type"); /* Check to see if icv structure was passed and set variables needed */ if (icvp == NULL) { do_scale=FALSE; do_fillvalue = FALSE; dmax = dmin = 0.0; fillvalue = 0.0; } else { do_scale=icvp->do_scale; do_fillvalue=icvp->do_fillvalue; fillvalue = icvp->user_fillvalue; dmax = icvp->fill_valid_max; dmin = icvp->fill_valid_min; epsilon = (dmax - dmin) * FILLVALUE_EPSILON; epsilon = fabs(epsilon); dmax += epsilon; dmin -= epsilon; } /* Check the types and get their size */ if ((intype==NC_CHAR) || (outtype==NC_CHAR)) { milog_message(MI_MSG_VARNOTNUM); MI_RETURN(MI_ERROR); } if (((inincr =nctypelen(intype ))==MI_ERROR) || ((outincr=nctypelen(outtype))==MI_ERROR)) { MI_RETURN(MI_ERROR); } /* Get the sign of input and output values */ insgn = MI_get_sign(intype, insign); outsgn = MI_get_sign(outtype, outsign); /* Check to see if a conversion needs to be made. If not, just copy the memory */ if ((intype==outtype) && (insgn==outsgn) && !do_scale && !do_fillvalue) { (void) memcpy(outvalues, invalues, (size_t) number_of_values*inincr); } /* Otherwise, loop through */ else { /* Step through values */ inptr=invalues; outptr=outvalues; for (i=0 ; i dmax))) { dvalue = fillvalue; } else if (do_scale) { dvalue = icvp->scale * dvalue + icvp->offset; } /* Truncate if necessary and assign the value */ {MI_FROM_DOUBLE(dvalue, outtype, outsgn, outptr)} inptr = (void *) ((char *)inptr + inincr); outptr = (void *) ((char *)outptr + outincr); } /* End of for loop */ } /* End of else */ MI_RETURN(MI_NOERROR); } minc-2.2.00/libsrc/voxel_loop.c0000644000265600003100000037526312030075003013255 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : voxel_loop.c @DESCRIPTION: Routines to loop through a file doing an operation on a single voxel. @METHOD : @GLOBALS : @CREATED : January 10, 1994 (Peter Neelin) @MODIFIED : * $Log: voxel_loop.c,v $ * Revision 6.14 2010-03-02 23:24:40 rotor * * libsrc/hdf_convenience.c: removed spurious debug output * * libsrc/minc.h: replaced MAX_NC_OPEN with 32 * * libsrc/voxel_loop.c: replaced MAX_NC_OPEN with MI_MAX_NUM_ICV * * Revision 6.13 2010-03-02 12:23:14 rotor * * ported HDF calls to 1.8.x * * Makefile.am: updated for minccmp * * Revision 6.12 2008/01/17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.11 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.10 2008/01/13 04:30:28 stever * Add braces around static initializers. * * Revision 6.9 2008/01/12 19:08:14 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.8 2006/04/09 15:40:25 bert * Minor change * * Revision 6.7 2005/08/26 21:04:58 bert * Use #if rather than #ifdef with MINC2 symbol * * Revision 6.6 2004/11/01 22:23:14 bert * Get rid of minc_def.h, use standard MALLOC() macro * * Revision 6.5 2004/10/15 13:46:52 bert * Minor changes for Windows compatibility * * Revision 6.4 2004/04/27 15:43:29 bert * Support MINC 2.0 format * * Revision 6.3 2003/11/14 16:52:24 stever * More last-minute fixes. * * Revision 6.2 2003/09/18 16:49:46 bert * Use fabs instead of ABS * * Revision 6.1 2002/01/14 21:28:26 neelin * Moved nd_loop, voxel_loop, ParseArgv and time_stamp from ../progs/Proglib * in order to include them in the main minc library. * * Revision 6.9 2002/01/14 20:02:39 neelin * Force the input buffers to have a minimum size so that large images do * not force excessive reading of the input file. * * Revision 6.8 2001/11/28 18:39:16 neelin * Added get_info_vxoel_index to allow users to get the full multi-dimensional * file index of the current voxel. * Modifications to allow arg_string to be NULL. * * Revision 6.7 2001/09/18 15:32:27 neelin * Create image variable last to allow big images and to fix compatibility * problems with 2.3 and 3.x. * * Revision 6.6 2001/08/16 16:41:32 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.5 2001/08/16 13:32:27 neelin * Partial fix for valid_range of different type from image (problems * arising from double to float conversion/rounding). NOT COMPLETE. * * Revision 6.4 2001/04/24 13:38:40 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.3 2001/04/17 18:40:15 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.2 2000/09/19 14:36:05 neelin * Added ability for caller to specify functions for allocating and freeing * voxel buffers used in loop. This is particularly useful for embedding * the voxel_loop code in other programs, such as Python, which manage memory * in their own way. * * Revision 6.1 1999/10/19 14:45:15 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.2 1997/06/20 13:58:35 neelin * Fixed bug: when doing accumulation with no output file and with * 4D input (or more), had problem setting input start vector. This broke * mincconcat for 4D input files. * * Revision 4.1 1997/05/22 12:41:40 neelin * Loosened up checking of start coordinates so that we look at error * relative to the total extent of the volume (nelements*step) instead of * relative to start value (which may be close to zero). * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 1.6 1995/05/11 12:31:29 neelin * Removed error messages from ncattdel. * * Revision 1.5 1995/05/02 16:05:32 neelin * Fixed bug in handling more than 30 files (needed to detach from icv). * Added more checking of dimensions. * Fixed bug in allocation of space for global max/min. * * Revision 1.4 1995/05/01 20:04:50 neelin * Fixed memory leak - not freeing global_minimum/maximum. * * Revision 1.3 1995/03/21 15:33:07 neelin * Changed call to voxel_function to always use proper vector length and * set num_voxels to the number of voxels, not multiplying by vector length. * * Revision 1.2 1995/03/21 14:06:39 neelin * Improved interface and added lots of functionality (much for the benefit * of mincconcat). * * Revision 1.1 94/12/14 10:17:19 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #include #include #include "voxel_loop.h" #include "nd_loop.h" /* Minimum number of voxels to put in a buffer. If this is too small, then for large images excessive reading can result. If it is too large, then for large images too much memory will be used. */ #define MIN_VOXELS_IN_BUFFER 1024 /* Default ncopts values for error handling */ #define NC_OPTS_VAL NC_VERBOSE | NC_FATAL /* Epsilon for coordinate comparisons */ #define COORD_EPSILON (FLT_EPSILON * 10.0) /* Typedefs */ typedef struct Loopfile_Info Loopfile_Info; /* Structure definitions */ struct Loop_Info { int current_file; int current_index; long start[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS]; long dimvoxels[MAX_VAR_DIMS]; /* Number of voxels skipped by a step of one in each dimension */ Loopfile_Info *loopfile_info; }; struct Loop_Options { int verbose; int clobber; nc_type datatype; int is_signed; double valid_range[2]; int max_open_files; int check_all_input_dim_info; int convert_input_to_scalar; int output_vector_size; /* 0 = same as input size */ int input_mincid; long total_copy_space; char *loop_dimension; int num_all_inputs; VoxelInputFileFunction input_file_function; VoxelOutputFileFunction output_file_function; int copy_all_header_info; int do_accumulate; int num_extra_buffers; VoxelStartFunction start_function; VoxelFinishFunction finish_function; VoxelFunction voxel_function; void *caller_data; Loop_Info *loop_info; int is_floating_type; AllocateBufferFunction allocate_buffer_function; #if MINC2 int v2format; #endif /* MINC2 */ }; struct Loopfile_Info { int cflags; /* creation flags */ int num_input_files; int num_output_files; char **input_files; char **output_files; int input_all_open; int output_all_open; int *input_mincid; int *output_mincid; int *input_icvid; int *output_icvid; int current_input_file_number; int current_output_file_number; int headers_only; int want_headers_only; int sequential_access; int can_open_all_input; }; /* Function prototypes */ PRIVATE int get_loop_dim_size(int inmincid, Loop_Options *loop_options); PRIVATE void translate_input_coords(int inmincid, long chunk_cur[], long input_cur[], long chunk_curcount[], long input_curcount[], int *loop_dim_index, Loop_Options *loop_options); PRIVATE void check_input_files(Loop_Options *loop_options, Loopfile_Info *loopfile_info); PRIVATE int input_image_varinq(int mincid, int imgid, char *name, nc_type *datatype, int *ndims, int dim[], int *natts, Loop_Options *loop_options); PRIVATE void get_dim_info(int mincid, int *ndims, long size[], char dimname[][MAX_NC_NAME], double start[], double step[], double dircos[][3], int is_regular[], Loop_Options *loop_options); PRIVATE void setup_output_files(Loop_Options *loop_options, Loopfile_Info *loopfile_info, char *arg_string); PRIVATE long get_vector_length(int mincid, Loop_Options *loop_options); PRIVATE void setup_variables(int inmincid, int outmincid, int output_curfile, char *arg_string, Loop_Options *loop_options); PRIVATE void update_history(int mincid, char *arg_string); PRIVATE void setup_icvs(Loop_Options *loop_options, Loopfile_Info *loopfile_info); PRIVATE void do_voxel_loop(Loop_Options *loop_options, Loopfile_Info *loopfile_info); PRIVATE void setup_looping(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int *ndims, long block_start[], long block_end[], long block_incr[], long *block_num_voxels, long chunk_incr[], long *chunk_num_voxels); PRIVATE void initialize_file_and_index(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int do_loop, int *ifile, int *dim_index, int *dummy_index); PRIVATE int finish_file_and_index(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int do_loop, int ifile, int dim_index, int dummy_index); PRIVATE void increment_file_and_index(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int do_loop, int *ifile, int *dim_index, int *dummy_index); PRIVATE Loopfile_Info *initialize_loopfile_info(int num_input_files, char *input_files[], int num_output_files, char *output_files[], Loop_Options *loop_options); PRIVATE void cleanup_loopfile_info(Loopfile_Info *loopfile_info); PRIVATE int get_input_numfiles(Loopfile_Info *loopfile_info); PRIVATE int get_output_numfiles(Loopfile_Info *loopfile_info); PRIVATE char *get_input_filename(Loopfile_Info *loopfile_info, int file_num); PRIVATE void set_input_headers_only(Loopfile_Info *loopfile_info, int headers_only); PRIVATE void set_input_sequential(Loopfile_Info *loopfile_info, int sequential_access); PRIVATE int get_input_mincid(Loopfile_Info *loopfile_info, int file_num); PRIVATE int get_output_mincid(Loopfile_Info *loopfile_info, int file_num); PRIVATE int create_output_file(Loopfile_Info *loopfile_info, int file_num); PRIVATE int get_input_icvid(Loopfile_Info *loopfile_info, int file_num); PRIVATE int get_output_icvid(Loopfile_Info *loopfile_info, int file_num); PRIVATE int create_input_icvid(Loopfile_Info *loopfile_info, int file_num); PRIVATE int create_output_icvid(Loopfile_Info *loopfile_info, int file_num); PRIVATE Loop_Info *create_loop_info(void); PRIVATE void initialize_loop_info(Loop_Info *loop_info); PRIVATE void free_loop_info(Loop_Info *loop_info); PRIVATE void set_info_shape(Loop_Info *loop_info, long start[], long count[]); PRIVATE void set_info_current_file(Loop_Info *loop_info, int current_file); PRIVATE void set_info_current_index(Loop_Info *loop_info, int current_index); PRIVATE void set_info_loopfile_info(Loop_Info *loop_info, Loopfile_Info *loopfile_info); /* ----------------------------- MNI Header ----------------------------------- @NAME : voxel_loop @INPUT : num_input_files - number of input files. input_files - array of names of input files. num_output_files - number of output files. output_files - array of names of output files. arg_string - string for history. loop_options - pointer to structure containing loop options. voxel_function - user function to process a group of voxels. See description in header file. caller_data - data that will be passed to voxel_function @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to loop through the voxels of a file and call a function to operate on each voxel. @METHOD : @GLOBALS : @CALLS : @CREATED : January 10, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void voxel_loop(int num_input_files, char *input_files[], int num_output_files, char *output_files[], char *arg_string, Loop_Options *loop_options, VoxelFunction voxel_function, void *caller_data) { Loopfile_Info *loopfile_info; int need_to_free_loop_options; int old_ncopts; //(void)fprintf(stderr, "About to loop, max_buffer is %d\n", loop_options->total_copy_space); /* Save ncopts and set it to default value */ old_ncopts = ncopts; ncopts = NC_OPTS_VAL; /* Check that there is at least one input file */ if (num_input_files < 1) { (void) fprintf(stderr, "There must be at least one input file.\n"); exit(EXIT_FAILURE); } if (num_output_files < 0) { (void) fprintf(stderr, "Negative number of output files!\n"); exit(EXIT_FAILURE); } /* Initialize loop options if needed */ need_to_free_loop_options = FALSE; if (loop_options == NULL) { loop_options = create_loop_options(); need_to_free_loop_options = TRUE; } loop_options->voxel_function = voxel_function; loop_options->caller_data = caller_data; /* Make sure that Loop_Info structure is initialized */ initialize_loop_info(loop_options->loop_info); /* Initialize looping info */ loopfile_info = initialize_loopfile_info(num_input_files, input_files, num_output_files, output_files, loop_options); /* Check that input files match */ set_input_headers_only(loopfile_info, TRUE); check_input_files(loop_options, loopfile_info); set_input_headers_only(loopfile_info, FALSE); /* Set up variables in output file */ setup_output_files(loop_options, loopfile_info, arg_string); /* Setup icv's */ setup_icvs(loop_options, loopfile_info); /* Loop through the voxels */ do_voxel_loop(loop_options, loopfile_info); /* Clean up looping info */ cleanup_loopfile_info(loopfile_info); /* Free loop options if needed */ if (need_to_free_loop_options) { free_loop_options(loop_options); } /* Restore ncopts */ ncopts = old_ncopts; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_loop_dim_size @INPUT : inmincid - input minc id loop_options - Options for loops @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to get the size of the looping dimension for the given input file @METHOD : @GLOBALS : @CALLS : @CREATED : January 24, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int get_loop_dim_size(int inmincid, Loop_Options *loop_options) { int dimid; long dim_length; int ndims, dim[MAX_VAR_DIMS]; int found; int idim; /* Look for dimension */ dimid = MI_ERROR; if (loop_options->loop_dimension != NULL) { ncopts = 0; dimid = ncdimid(inmincid, loop_options->loop_dimension); ncopts = NC_OPTS_VAL; } if (dimid == MI_ERROR) return 1; (void) ncdiminq(inmincid, dimid, NULL, &dim_length); /* Get image variable info */ (void) ncvarinq(inmincid, ncvarid(inmincid, MIimage), NULL, NULL, &ndims, dim, NULL); /* Check to see if the dimension subscripts the image */ found = FALSE; for (idim=0; idim < ndims; idim++) { if (dimid == dim[idim]) found = TRUE; } /* Return appropriate value */ if (found) return dim_length; else return 1; } /* ----------------------------- MNI Header ----------------------------------- @NAME : translate_input_coords @INPUT : inmincid - input minc id chunk_cur - start for current chunk chunk_curcount - count for current chunk loop_options - Options for loops @OUTPUT : input_cur - start for input file input_curcount - count for input file loop_dim_index - index in input_cur for looping dimension @RETURNS : (nothing) @DESCRIPTION: Routine to translate the input hyperslab coords from those excluding the looping dimension to ones appropriate for the input file. Also returns the index (offset in input_cur) for the looping dimension (so that the caller can modify this index). @METHOD : @GLOBALS : @CALLS : @CREATED : January 24, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void translate_input_coords(int inmincid, long chunk_cur[], long input_cur[], long chunk_curcount[], long input_curcount[], int *loop_dim_index, Loop_Options *loop_options) { int dimid; int ndims, dim[MAX_VAR_DIMS]; int idim, jdim; /* Look for dimension */ dimid = MI_ERROR; if (loop_options->loop_dimension != NULL) { ncopts = 0; dimid = ncdimid(inmincid, loop_options->loop_dimension); ncopts = NC_OPTS_VAL; } /* Get image variable info */ (void) ncvarinq(inmincid, ncvarid(inmincid, MIimage), NULL, NULL, &ndims, dim, NULL); /* Copy the hyperslab coordinates and get the index */ *loop_dim_index = ndims; jdim = 0; for (idim=0; idim < ndims; idim++) { if (dimid != dim[idim]) { input_cur[idim] = chunk_cur[jdim]; input_curcount[idim] = chunk_curcount[jdim]; jdim++; } else { input_cur[idim] = 0; input_curcount[idim] = 1; *loop_dim_index = idim; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_input_files @INPUT : loop_options - Options for loops loopfile_info - Information describing looping stuff and files @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to check input files for consistency. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void check_input_files(Loop_Options *loop_options, Loopfile_Info *loopfile_info) { int ifile, idim, jdim; int first_ndims, ndims; int input_mincid; long first_size[MAX_VAR_DIMS], size[MAX_VAR_DIMS]; char first_dimname[MAX_VAR_DIMS][MAX_NC_NAME]; char dimname[MAX_VAR_DIMS][MAX_NC_NAME]; double extent; double first_start[MAX_VAR_DIMS], start[MAX_VAR_DIMS]; double first_step[MAX_VAR_DIMS], step[MAX_VAR_DIMS]; double start_diff, step_diff; double first_dircos[MAX_VAR_DIMS][3], dircos[MAX_VAR_DIMS][3]; double dircos_diff, dircos_cumdiff; int first_is_regular[MAX_VAR_DIMS], is_regular[MAX_VAR_DIMS]; /* Keep track of number of inputs (files and looping dimension) */ loop_options->num_all_inputs = 0; /* Loop over files. For the first file, we only get the dimension info, we don't check it. */ for (ifile = 0; ifile < get_input_numfiles(loopfile_info); ifile++) { /* Get mincid */ input_mincid = get_input_mincid(loopfile_info, ifile); /* Add up number of inputs */ loop_options->num_all_inputs += get_loop_dim_size(input_mincid, loop_options); /* Get dimension information for this file */ if (ifile == 0) { get_dim_info(input_mincid, &first_ndims, first_size, first_dimname, first_start, first_step, first_dircos, first_is_regular, loop_options); } else { get_dim_info(input_mincid, &ndims, size, dimname, start, step, dircos, is_regular, loop_options); /* Check number of dimensions */ if (ndims != first_ndims) { (void) fprintf(stderr, "Files %s and %s have different numbers of dimensions\n", get_input_filename(loopfile_info,ifile), get_input_filename(loopfile_info,0)); exit(EXIT_FAILURE); } /* Loop over dimensions */ for (idim = 0; idim < first_ndims; idim++) { /* Check dimension sizes */ if (size[idim] != first_size[idim]) { (void) fprintf(stderr, "Files %s and %s have different sizes of dimensions\n", get_input_filename(loopfile_info,ifile), get_input_filename(loopfile_info,0)); exit(EXIT_FAILURE); } /* Check optional dimension stuff */ if (loop_options->check_all_input_dim_info) { /* Check names */ if (strcmp(dimname[idim], first_dimname[idim]) != 0) { (void) fprintf(stderr, "Files %s and %s have different dimension names\n", get_input_filename(loopfile_info,ifile), get_input_filename(loopfile_info,0)); exit(EXIT_FAILURE); } /* Check coordinates */ start_diff = start[idim] - first_start[idim]; extent = ((double) first_size[idim]) * first_step[idim]; if (extent != 0.0) start_diff /= extent; step_diff = step[idim] - first_step[idim]; if (first_step[idim] != 0.0) step_diff /= first_step[idim]; dircos_cumdiff = 0.0; for (jdim=0; jdim < 3; jdim++) { dircos_diff = first_dircos[idim][jdim] - dircos[idim][jdim]; if (first_dircos[idim][jdim] != 0.0) dircos_diff /= first_dircos[idim][jdim]; dircos_cumdiff += fabs(dircos_diff); } if (fabs(start_diff) > COORD_EPSILON) { (void) fprintf(stderr, "Files %s and %s have different start coordinates (%s)\n", get_input_filename(loopfile_info,ifile), get_input_filename(loopfile_info,0), first_dimname[idim]); exit(EXIT_FAILURE); } if (fabs(step_diff) > COORD_EPSILON) { (void) fprintf(stderr, "Files %s and %s have different step coordinates (%s)\n", get_input_filename(loopfile_info,ifile), get_input_filename(loopfile_info,0), first_dimname[idim]); exit(EXIT_FAILURE); } if (dircos_cumdiff > COORD_EPSILON) { (void) fprintf(stderr, "Files %s and %s have different direction cosines (%s)\n", get_input_filename(loopfile_info,ifile), get_input_filename(loopfile_info,0), first_dimname[idim]); exit(EXIT_FAILURE); } if (first_is_regular[idim] != is_regular[idim]) { (void) fprintf(stderr, "Files %s and %s have different coordinate spacings (%s)\n", get_input_filename(loopfile_info,ifile), get_input_filename(loopfile_info,0), first_dimname[idim]); exit(EXIT_FAILURE); } } /* If check all dimension info */ } /* End of loop over dimensions */ } /* End of if ifile == 0 else */ /* Call the user's function if needed */ if (loop_options->input_file_function != NULL) { set_info_current_file(loop_options->loop_info, ifile); set_info_loopfile_info(loop_options->loop_info, loopfile_info); loop_options->input_file_function(loop_options->caller_data, input_mincid, ifile, loop_options->loop_info); set_info_loopfile_info(loop_options->loop_info, NULL); } } /* End of loop over files */ } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_image_varinq @INPUT : mincid - Minc id of file imgid - id of image variable loop_options - structure containing looping options @OUTPUT : name - name of variable datatype - type of variable ndims - number of dimensions dim - array of dimension ids natts - number of attributes @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Routine to call ncvarinq for the image variable, suppressing the dimension specified in loop_options. @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int input_image_varinq(int mincid, int imgid, char *name, nc_type *datatype, int *ndims, int dim[], int *natts, Loop_Options *loop_options) { int dimid; int old_ncopts; int idim, jdim; int status; int nimgdims; char dimname[MAX_NC_NAME]; /* Get loop dimension id */ dimid = MI_ERROR; if (loop_options->loop_dimension != NULL) { old_ncopts = ncopts; ncopts = 0; dimid = ncdimid(mincid, loop_options->loop_dimension); ncopts = old_ncopts; } /* Call ncvarinq. If there is no loop dim, or an error occurred, then return. */ status = ncvarinq(mincid, imgid, name, datatype, ndims, dim, natts); if ((dimid == MI_ERROR) || (status == MI_ERROR)) return status; /* Get number of image dimensions */ nimgdims = 2; if (*ndims > 0) { (void) ncdiminq(mincid, dim[*ndims-1], dimname, NULL); if (strcmp(dimname, MIvector_dimension) == 0) nimgdims++; } /* Look for the loop dimension */ jdim = 0; for (idim=0; idim < *ndims; idim++) { if (dim[idim] != dimid) { dim[jdim] = dim[idim]; jdim++; } else if (idim >= *ndims-nimgdims) { (void) fprintf(stderr, "Don't use an image dimension as a loop dimension.\n"); exit(EXIT_FAILURE); } } /* Save number of dimensions */ *ndims = jdim; return status; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dim_info @INPUT : mincid - Minc id of file @OUTPUT : ndims - number of dimensions size - array of sizes of dimensions dimname - array of dimension names start - array of starts for dimensions step - array of steps for dimensions dircos - array of direction cosines is_regular - array of flags indicating whether dimension is regularly spaced or not loop_options - looping options @RETURNS : (nothing) @DESCRIPTION: Routine to get dimension information for a file. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void get_dim_info(int mincid, int *ndims, long size[], char dimname[][MAX_NC_NAME], double start[], double step[], double dircos[][3], int is_regular[], Loop_Options *loop_options) { int imgid, varid; int idim, jdim; int dim[MAX_VAR_DIMS]; int att_length; char string[MAX_NC_NAME]; char *thename; int old_ncopts; enum {XAXIS, YAXIS, ZAXIS, OAXIS} dimtype; static double default_dircos[][3] = { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 0.0, 0.0 } }; char regstring[MI_MAX_ATTSTR_LEN]; /* Get image variable info */ imgid = ncvarid(mincid, MIimage); (void) input_image_varinq(mincid, imgid, NULL, NULL, ndims, dim, NULL, loop_options); /* Loop through dimensions */ for (idim=0; idim < *ndims; idim++) { if (dimname == NULL) thename = string; else thename = dimname[idim]; (void) ncdiminq(mincid, dim[idim], thename, &size[idim]); /* Set default coordinate info */ if (start != NULL) start[idim] = 0.0; if (step != NULL) step[idim] = 1.0; if (dircos != NULL) { if ((strcmp(thename, MIxspace) == 0) || (strcmp(thename, MIxfrequency) == 0)) dimtype = XAXIS; else if ((strcmp(thename, MIyspace) == 0) || (strcmp(thename, MIyfrequency) == 0)) dimtype = YAXIS; else if ((strcmp(thename, MIzspace) == 0) || (strcmp(thename, MIzfrequency) == 0)) dimtype = ZAXIS; else dimtype = OAXIS; for (jdim=0; jdim < 3; jdim++) dircos[idim][jdim] = default_dircos[dimtype][jdim]; } if (is_regular != NULL) is_regular[idim] = TRUE; /* Get the coordinate info */ old_ncopts = ncopts; ncopts = 0; varid = ncvarid(mincid, thename); if (varid != MI_ERROR) { if (start != NULL) (void) miattget1(mincid, varid, MIstart, NC_DOUBLE, &start[idim]); if (step != NULL) (void) miattget1(mincid, varid, MIstep, NC_DOUBLE, &step[idim]); if (dircos != NULL) (void) miattget(mincid, varid, MIdirection_cosines, NC_DOUBLE, 3, dircos[idim], &att_length); if (is_regular != NULL) { if (miattgetstr(mincid, varid, MIspacing, sizeof(regstring), regstring) != NULL) { if (strcmp(regstring, MI_REGULAR) == 0) is_regular[idim] = TRUE; else if (strcmp(regstring, MI_IRREGULAR) == 0) is_regular[idim] = FALSE; } } } ncopts = old_ncopts; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_output_files @INPUT : loop_options - Options controlling looping loopfile_info - Looping information arg_string - string for history @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to setup the the output files @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void setup_output_files(Loop_Options *loop_options, Loopfile_Info *loopfile_info, char *arg_string) { int inmincid, outmincid; int ifile; /* Get mincid for first input file */ inmincid = get_input_mincid(loopfile_info, 0); /* Create output files */ for (ifile=0; ifile < get_output_numfiles(loopfile_info); ifile++) { outmincid = create_output_file(loopfile_info, ifile); setup_variables(inmincid, outmincid, ifile, arg_string, loop_options); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_vector_length @INPUT : mincid - minc file id loop_options - looping options (if NULL, uses ncvarinq) @OUTPUT : (none) @RETURNS : Length of vector dimension or zero if no such dimension. @DESCRIPTION: Routine to get the length of the vector dimension in a minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE long get_vector_length(int mincid, Loop_Options *loop_options) { int imgid; int ndims; int dim[MAX_VAR_DIMS]; char dimname[MAX_NC_NAME]; long vector_length; /* Get image variable id */ imgid = ncvarid(mincid, MIimage); /* Get the image dimension info */ if (loop_options != NULL) { (void) input_image_varinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL, loop_options); } else { (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); } /* Check for vector dimension */ (void) ncdiminq(mincid, dim[ndims-1], dimname, &vector_length); if ((strcmp(dimname, MIvector_dimension) != 0) || (ndims <= 2)) { vector_length = 0; } return vector_length; } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_variables @INPUT : inmincid - input minc file id outmincid - output minc file id output_curfile - current output file number (counting from zero) arg_string - string for history loop_options - options controlling loop behaviour @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to setup the variables in the output file. @METHOD : @GLOBALS : @CALLS : @CREATED : January 10, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void setup_variables(int inmincid, int outmincid, int output_curfile, char *arg_string, Loop_Options *loop_options) { int inimgid, outimgid, maxid, minid, varid; int indim[MAX_VAR_DIMS], outdim[MAX_VAR_DIMS]; nc_type datatype; int idim, odim, ivar, in_ndims, out_ndims, in_nimgdims, out_nimgdims; char dimname[MAX_NC_NAME]; int nvars, varlist[MAX_VAR_DIMS*2]; long dimlength; int input_vector_length; int changing_vector_dim; double valid_range[2]; /* Get image variable id for input file */ inimgid = ncvarid(inmincid, MIimage); /* Get the list of dimensions subscripting the image variable */ (void) input_image_varinq(inmincid, inimgid, NULL, &datatype, &in_ndims, indim, NULL, loop_options); /* Get the length of the input vector dimension */ input_vector_length = get_vector_length(inmincid, loop_options); if (loop_options->convert_input_to_scalar && (input_vector_length > 0)) { input_vector_length = 0; in_ndims--; } /* Get the number of image dimensions in the input file */ in_nimgdims = (input_vector_length == 0 ? 2 : 3); /* Are we changing the length of the vector dimension (or removing it?). For an output vector size of 1, we don't want an output vector dimension. */ changing_vector_dim = ((loop_options->output_vector_size != 0) && (loop_options->output_vector_size != input_vector_length)); if (loop_options->output_vector_size == 1) changing_vector_dim = (input_vector_length != 0); /* Work out number of output dimensions and image dimensions */ out_ndims = in_ndims; out_nimgdims = in_nimgdims; if (changing_vector_dim && (input_vector_length == 0)) { out_ndims++; out_nimgdims++; } else if (changing_vector_dim && (loop_options->output_vector_size <= 1)) { out_ndims--; out_nimgdims--; } /* Set up the output minc file */ /* Loop, creating output dimensions */ odim = 0; nvars = 0; for (idim=0; idim < in_ndims; idim++) { /* Check for a change in vector dimension length */ if ((idim != in_ndims-1) || (input_vector_length == 0) || !changing_vector_dim) { /* Copy the dimension */ (void) ncdiminq(inmincid, indim[idim], dimname, &dimlength); outdim[odim] = ncdimdef(outmincid, dimname, dimlength); /* Copy the dimension variables if we are not copying the whole header */ if (!loop_options->copy_all_header_info) { ncopts = 0; for (ivar=0; ivar < 2; ivar++) { if (ivar == 1) (void) strcat(dimname, "_width"); varlist[nvars] = ncvarid(inmincid, dimname); if (varlist[nvars] != MI_ERROR) { (void) micopy_var_def(inmincid, varlist[nvars], outmincid); nvars++; } } ncopts = NC_OPTS_VAL; } odim++; } } /* Create the output vector dimension if needed */ if (changing_vector_dim && (loop_options->output_vector_size > 1)) { outdim[odim] = ncdimdef(outmincid, MIvector_dimension, (long) loop_options->output_vector_size); } /* Copy other variables in file, if appropriate */ if (loop_options->copy_all_header_info) { nvars = 0; ncopts = 0; varlist[nvars] = inimgid; if (varlist[nvars] != MI_ERROR) nvars++; varlist[nvars] = ncvarid(inmincid, MIimagemax); if (varlist[nvars] != MI_ERROR) nvars++; varlist[nvars] = ncvarid(inmincid, MIimagemin); if (varlist[nvars] != MI_ERROR) nvars++; if (loop_options->loop_dimension != NULL) { (void) strcpy(dimname, loop_options->loop_dimension); varlist[nvars] = ncvarid(inmincid, dimname); if (varlist[nvars] != MI_ERROR) nvars++; (void) strcat(dimname, "_width"); varlist[nvars] = ncvarid(inmincid, dimname); if (varlist[nvars] != MI_ERROR) nvars++; } (void) micopy_all_var_defs(inmincid, outmincid, nvars, varlist); ncopts = NC_OPTS_VAL; } /* Add the time stamp to the history */ update_history(outmincid, arg_string); /* Call the user's function if needed */ if (loop_options->output_file_function != NULL) { set_info_current_file(loop_options->loop_info, 0); loop_options->output_file_function(loop_options->caller_data, outmincid, output_curfile, loop_options->loop_info); } /* Create the image-min/max variables */ maxid = micreate_std_variable(outmincid, MIimagemax, NC_DOUBLE, out_ndims-out_nimgdims, outdim); minid = micreate_std_variable(outmincid, MIimagemin, NC_DOUBLE, out_ndims-out_nimgdims, outdim); ncopts = 0; (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemax), outmincid, maxid); (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemin), outmincid, minid); ncopts = NC_OPTS_VAL; /* Create the image variable */ if (loop_options->datatype != MI_ORIGINAL_TYPE) { datatype = loop_options->datatype; } loop_options->is_floating_type = ((datatype == NC_FLOAT) || (datatype == NC_DOUBLE)); outimgid = micreate_std_variable(outmincid, MIimage, datatype, out_ndims, outdim); (void) micopy_all_atts(inmincid, inimgid, outmincid, outimgid); if (loop_options->is_floating_type) { ncopts = 0; (void) ncattdel(outmincid, outimgid, MIsigntype); ncopts = NC_OPTS_VAL; valid_range[0] = 0; valid_range[1] = 1; (void) miset_valid_range(outmincid, outimgid, valid_range); } else if (loop_options->datatype != MI_ORIGINAL_TYPE) { if (loop_options->is_signed) (void) miattputstr(outmincid, outimgid, MIsigntype, MI_SIGNED); else (void) miattputstr(outmincid, outimgid, MIsigntype, MI_UNSIGNED); if ((loop_options->valid_range[1] > loop_options->valid_range[0])) { (void) miset_valid_range(outmincid, outimgid, loop_options->valid_range); } else { ncopts = 0; (void) ncattdel(outmincid, outimgid, MIvalid_range); ncopts = NC_OPTS_VAL; } } (void) miattputstr(outmincid, outimgid, MIcomplete, MI_FALSE); /* Put the file in data mode */ (void) ncsetfill(outmincid, NC_NOFILL); (void) ncendef(outmincid); /* Copy over variable values */ ncopts = 0; if (loop_options->copy_all_header_info) { (void) micopy_all_var_values(inmincid, outmincid, nvars, varlist); } else { for (ivar=0; ivar < nvars; ivar++) { (void) ncvarinq(inmincid, varlist[ivar], dimname, NULL, NULL, NULL, NULL); varid = ncvarid(outmincid, dimname); if (varid != MI_ERROR) { (void) micopy_var_values(inmincid, varlist[ivar], outmincid, varid); } } } ncopts = NC_OPTS_VAL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_history @INPUT : mincid - id of output minc file arg_string - string giving list of arguments @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to update the history global variable in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void update_history(int mincid, char *arg_string) { nc_type datatype; int att_length; char *string; if (arg_string == NULL) return; /* Get the history attribute length */ ncopts=0; if ((ncattinq(mincid, NC_GLOBAL, MIhistory, &datatype, &att_length) == MI_ERROR) || (datatype != NC_CHAR)) att_length = 0; att_length += strlen(arg_string) + 1; /* Allocate a string and get the old history */ string = MALLOC(att_length, char); string[0] = '\0'; (void) miattgetstr(mincid, NC_GLOBAL, MIhistory, att_length, string); ncopts = NC_OPTS_VAL; /* Add the new command and put the new history. */ (void) strcat(string, arg_string); (void) miattputstr(mincid, NC_GLOBAL, MIhistory, string); FREE(string); } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_icvs @INPUT : loop_options - loop option info loopfile_info - looping information @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up the input and output icv's. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void setup_icvs(Loop_Options *loop_options, Loopfile_Info *loopfile_info) { int ifile; int icvid; /* Loop through input icv's, setting their values. Attaching is done by get_input_icvid. */ for (ifile=0; ifile < get_input_numfiles(loopfile_info); ifile++) { icvid = create_input_icvid(loopfile_info, ifile); (void) miicv_setint(icvid, MI_ICV_TYPE, NC_DOUBLE); (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_DO_FILLVALUE, TRUE); if (loop_options->convert_input_to_scalar) { (void) miicv_setint(icvid, MI_ICV_DO_DIM_CONV, TRUE); (void) miicv_setint(icvid, MI_ICV_DO_SCALAR, TRUE); (void) miicv_setint(icvid, MI_ICV_XDIM_DIR, MI_ICV_ANYDIR); (void) miicv_setint(icvid, MI_ICV_YDIM_DIR, MI_ICV_ANYDIR); (void) miicv_setint(icvid, MI_ICV_ZDIM_DIR, MI_ICV_ANYDIR); (void) miicv_setint(icvid, MI_ICV_KEEP_ASPECT, FALSE); } } /* Loop through output icv's, setting their values. Attaching is done by get_input_icvid. */ for (ifile=0; ifile < get_output_numfiles(loopfile_info); ifile++) { icvid = create_output_icvid(loopfile_info, ifile); (void) miicv_setint(icvid, MI_ICV_TYPE, NC_DOUBLE); (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_voxel_loop @INPUT : loop_options - user options for looping loopfile_info - information on files used in loop @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to loop through the voxels and do something to each one @METHOD : @GLOBALS : @CALLS : @CREATED : January 10, 1994 (Peter Neelin) @MODIFIED : November 30, 1994 (P.N.) ---------------------------------------------------------------------------- */ PRIVATE void do_voxel_loop(Loop_Options *loop_options, Loopfile_Info *loopfile_info) { long block_start[MAX_VAR_DIMS], block_end[MAX_VAR_DIMS]; long block_incr[MAX_VAR_DIMS]; long block_cur[MAX_VAR_DIMS], block_curcount[MAX_VAR_DIMS]; long chunk_start[MAX_VAR_DIMS], chunk_end[MAX_VAR_DIMS]; long chunk_incr[MAX_VAR_DIMS]; long chunk_cur[MAX_VAR_DIMS], chunk_curcount[MAX_VAR_DIMS]; long input_cur[MAX_VAR_DIMS], input_curcount[MAX_VAR_DIMS]; long firstfile_cur[MAX_VAR_DIMS], firstfile_curcount[MAX_VAR_DIMS]; double **input_buffers, **output_buffers, **extra_buffers; double **results_buffers; long chunk_num_voxels, block_num_voxels, ivox; int outmincid, imgid, maxid, minid; double *data, minimum, maximum, valid_range[2]; double *global_minimum, *global_maximum; int ifile, ofile, ibuff, ndims, idim; int num_output_files; int num_input_buffers, num_output_buffers, num_extra_buffers; int input_vector_length, output_vector_length; int modify_vector_count; int current_input; int input_icvid, input_mincid; int loop_dim_index; int dim_index; int outer_file_loop; int dummy_index; int input_curfile; nc_type file_datatype; /* Get number of files, buffers, etc. */ num_output_files = get_output_numfiles(loopfile_info); num_input_buffers = (loop_options->do_accumulate ? 1 : loop_options->num_all_inputs); num_extra_buffers = loop_options->num_extra_buffers; num_output_buffers = num_output_files + num_extra_buffers; input_vector_length = get_vector_length(get_input_mincid(loopfile_info, 0), loop_options); if ((input_vector_length == 0) || (loop_options->convert_input_to_scalar)) input_vector_length = 1; if (num_output_files > 0) { output_vector_length = get_vector_length(get_output_mincid(loopfile_info, 0), NULL); if (output_vector_length == 0) output_vector_length = 1; } else output_vector_length = 1; modify_vector_count = (input_vector_length != output_vector_length); /* Initialize all of the counters to reasonable values */ (void) miset_coords(MAX_VAR_DIMS, 0, block_start); (void) miset_coords(MAX_VAR_DIMS, 0, block_end); (void) miset_coords(MAX_VAR_DIMS, 0, block_incr); (void) miset_coords(MAX_VAR_DIMS, 0, block_cur); (void) miset_coords(MAX_VAR_DIMS, 0, block_curcount); (void) miset_coords(MAX_VAR_DIMS, 0, chunk_start); (void) miset_coords(MAX_VAR_DIMS, 0, chunk_end); (void) miset_coords(MAX_VAR_DIMS, 0, chunk_incr); (void) miset_coords(MAX_VAR_DIMS, 0, chunk_cur); (void) miset_coords(MAX_VAR_DIMS, 0, chunk_curcount); (void) miset_coords(MAX_VAR_DIMS, 0, input_cur); (void) miset_coords(MAX_VAR_DIMS, 0, input_curcount); (void) miset_coords(MAX_VAR_DIMS, 0, firstfile_cur); (void) miset_coords(MAX_VAR_DIMS, 0, firstfile_curcount); /* Get block and chunk looping information */ setup_looping(loop_options, loopfile_info, &ndims, block_start, block_end, block_incr, &block_num_voxels, chunk_incr, &chunk_num_voxels); /* Allocate space for buffers */ if (loop_options->allocate_buffer_function != NULL) { loop_options->allocate_buffer_function (loop_options->caller_data, TRUE, num_input_buffers, chunk_num_voxels, input_vector_length, &input_buffers, num_output_files, block_num_voxels, output_vector_length, &output_buffers, num_extra_buffers, chunk_num_voxels, output_vector_length, &extra_buffers, loop_options->loop_info); } else { /* Allocate input buffers */ input_buffers = MALLOC(num_input_buffers, double *); for (ibuff=0; ibuff < num_input_buffers; ibuff++) { input_buffers[ibuff] = MALLOC(chunk_num_voxels * input_vector_length, double); } /* Allocate output buffers */ if (num_output_files > 0) { output_buffers = MALLOC(num_output_files, double *); for (ibuff=0; ibuff < num_output_files; ibuff++) { output_buffers[ibuff] = MALLOC(block_num_voxels * output_vector_length, double); } } /* Allocate extra buffers */ if (num_extra_buffers > 0) { extra_buffers = MALLOC(num_extra_buffers, double *); for (ibuff=0; ibuff < num_extra_buffers; ibuff++) { extra_buffers[ibuff] = MALLOC(chunk_num_voxels * output_vector_length, double); } } } /* Set up the results pointers */ if (num_output_buffers > 0) { results_buffers = MALLOC(num_output_buffers, double *); for (ibuff=0; ibuff < num_output_buffers; ibuff++) { if (ibuff < num_output_files) { results_buffers[ibuff] = output_buffers[ibuff]; } else { results_buffers[ibuff] = extra_buffers[ibuff-num_output_files]; } } } /* Initialize global min and max */ if (num_output_files > 0) { global_minimum = MALLOC(num_output_files, double); global_maximum = MALLOC(num_output_files, double); for (ofile=0; ofile < num_output_files; ofile++) { global_minimum[ofile] = DBL_MAX; global_maximum[ofile] = -DBL_MAX; } } else { global_minimum = NULL; global_maximum = NULL; } /* Initialize loop info - just to be safe */ initialize_loop_info(loop_options->loop_info); /* Print log message */ if (loop_options->verbose) { (void) printf("Processing:"); (void) fflush(stdout); } /* Outer loop over files, if appropriate */ outer_file_loop = (loop_options->do_accumulate && (num_output_buffers <= 0)); for (initialize_file_and_index(loop_options, loopfile_info, outer_file_loop, &ifile, &dim_index, &dummy_index); finish_file_and_index(loop_options, loopfile_info, outer_file_loop, ifile, dim_index, dummy_index); increment_file_and_index(loop_options, loopfile_info, outer_file_loop, &ifile, &dim_index, &dummy_index)) { /* Loop through blocks (image-max/min do not vary over blocks) */ nd_begin_looping(block_start, block_cur, ndims); while (!nd_end_of_loop(block_cur, block_end, ndims)) { nd_update_current_count(block_cur, block_incr, block_end, block_curcount, ndims); /* Set results_buffers to beginning of output buffers */ for (ofile=0; ofile < num_output_files; ofile++) { results_buffers[ofile] = output_buffers[ofile]; } /* Loop through chunks (space for input buffers) */ for (idim=0; idim < ndims; idim++) { chunk_start[idim] = block_cur[idim]; chunk_end[idim] = block_cur[idim] + block_curcount[idim]; } nd_begin_looping(chunk_start, chunk_cur, ndims); while (!nd_end_of_loop(chunk_cur, chunk_end, ndims)) { nd_update_current_count(chunk_cur, chunk_incr, chunk_end, chunk_curcount, ndims); /* Print log message */ if (loop_options->verbose) { (void) printf("."); (void) fflush(stdout); } /* Calculate number of voxels in a chunk */ chunk_num_voxels = 1; for (idim=0; idim < ndims; idim++) chunk_num_voxels *= chunk_curcount[idim]; chunk_num_voxels /= input_vector_length; /* Translate start and count for file and save in loop_info */ if (outer_file_loop) input_curfile = ifile; else input_curfile = 0; input_mincid = get_input_mincid(loopfile_info, input_curfile); translate_input_coords(input_mincid, chunk_cur, firstfile_cur, chunk_curcount, firstfile_curcount, &loop_dim_index, loop_options); /* Save start and count and file and index in loop_info */ set_info_shape(loop_options->loop_info, firstfile_cur, firstfile_curcount); set_info_current_file(loop_options->loop_info, 0); set_info_current_index(loop_options->loop_info, 0); /* Initialize results buffers if necessary */ if (loop_options->do_accumulate) { if (loop_options->start_function != NULL) { loop_options->start_function (loop_options->caller_data, chunk_num_voxels, num_output_buffers, output_vector_length, results_buffers, loop_options->loop_info); } } /* Get the input buffers and accumulate them if needed */ current_input = 0; for (initialize_file_and_index(loop_options, loopfile_info, !outer_file_loop, &ifile, &dim_index, &dummy_index); finish_file_and_index(loop_options, loopfile_info, !outer_file_loop, ifile, dim_index, dummy_index); increment_file_and_index(loop_options, loopfile_info, !outer_file_loop, &ifile, &dim_index, &dummy_index)) { /* Get input icvid and mincid and translate coords for file. We need to do this each time in case we have an outer file loop. */ input_icvid = get_input_icvid(loopfile_info, ifile); (void) miicv_inqint(input_icvid, MI_ICV_CDFID, &input_mincid); translate_input_coords(input_mincid, chunk_cur, input_cur, chunk_curcount, input_curcount, &loop_dim_index, loop_options); /* Read buffer */ ibuff = (loop_options->do_accumulate ? 0 : current_input); input_cur[loop_dim_index] = dim_index; (void) miicv_get(input_icvid, input_cur, input_curcount, input_buffers[ibuff]); if (loop_options->do_accumulate) { set_info_shape(loop_options->loop_info, input_cur, input_curcount); set_info_current_file(loop_options->loop_info, ifile); set_info_current_index(loop_options->loop_info, dim_index); set_info_loopfile_info(loop_options->loop_info, loopfile_info); loop_options->voxel_function(loop_options->caller_data, chunk_num_voxels, num_input_buffers, input_vector_length, input_buffers, num_output_buffers, output_vector_length, results_buffers, loop_options->loop_info); set_info_loopfile_info(loop_options->loop_info, NULL); } current_input++; } /* Inner loop over files and dimension index */ /* Do something with the buffers or finish accumulation */ set_info_shape(loop_options->loop_info, firstfile_cur, firstfile_curcount); set_info_current_file(loop_options->loop_info, 0); set_info_current_index(loop_options->loop_info, 0); if (loop_options->do_accumulate) { if (loop_options->finish_function != NULL) { loop_options->finish_function(loop_options->caller_data, chunk_num_voxels, num_output_buffers, output_vector_length, results_buffers, loop_options->loop_info); } } else { loop_options->voxel_function(loop_options->caller_data, chunk_num_voxels, num_input_buffers, input_vector_length, input_buffers, num_output_buffers, output_vector_length, results_buffers, loop_options->loop_info); } /* Increment results_buffers through output buffers */ for (ofile=0; ofile < num_output_files; ofile++) { results_buffers[ofile] += chunk_num_voxels * output_vector_length; } nd_increment_loop(chunk_cur, chunk_start, chunk_incr, chunk_end, ndims); } /* End of loop through chunks */ /* Write out output buffers */ for (ofile=0; ofile < num_output_files; ofile++) { outmincid = get_output_mincid(loopfile_info, ofile); maxid = ncvarid(outmincid, MIimagemax); minid = ncvarid(outmincid, MIimagemin); data = output_buffers[ofile]; /* Find the max and min */ minimum = DBL_MAX; maximum = -DBL_MAX; for (ivox=0; ivox < block_num_voxels*output_vector_length; ivox++) { if (data[ivox] != -DBL_MAX) { if (data[ivox] < minimum) minimum = data[ivox]; if (data[ivox] > maximum) maximum = data[ivox]; } } if ((minimum == DBL_MAX) && (maximum == -DBL_MAX)) { minimum = 0.0; maximum = 0.0; } /* Save global min and max */ if (minimum < global_minimum[ofile]) global_minimum[ofile] = minimum; if (maximum > global_maximum[ofile]) global_maximum[ofile] = maximum; /* Write out the max and min */ (void) mivarput1(outmincid, maxid, block_cur, NC_DOUBLE, NULL, &maximum); (void) mivarput1(outmincid, minid, block_cur, NC_DOUBLE, NULL, &minimum); /* Write out the values */ if (modify_vector_count) block_curcount[ndims-1] = output_vector_length; (void) miicv_put(get_output_icvid(loopfile_info, ofile), block_cur, block_curcount, data); } /* End of loop through output files */ nd_increment_loop(block_cur, block_start, block_incr, block_end, ndims); } /* End of loop through chunks */ } /* End of outer loop through files and dimension indices */ /* Data has been completely written */ for (ofile=0; ofile < num_output_files; ofile++) { outmincid = get_output_mincid(loopfile_info, ofile); imgid = ncvarid(outmincid, MIimage); (void) miattputstr(outmincid, imgid, MIcomplete, MI_TRUE); if (loop_options->is_floating_type) { if ((global_minimum[ofile] == DBL_MAX) && (global_maximum[ofile] == -DBL_MAX)) { global_minimum[ofile] = 0.0; global_maximum[ofile] = 0.0; } valid_range[0] = global_minimum[ofile]; valid_range[1] = global_maximum[ofile]; /* Force truncation of valid_range to match float image */ if ((ncvarinq(outmincid, imgid, NULL, &file_datatype, NULL, NULL, NULL) != MI_ERROR) && (file_datatype == NC_FLOAT)) { valid_range[0] = (float) valid_range[0]; valid_range[1] = (float) valid_range[1]; } (void) miset_valid_range(outmincid, imgid, valid_range); } } /* Print log message */ if (loop_options->verbose) { (void) printf("Done\n"); (void) fflush(stdout); } /* Free results pointer array, but not its buffers, since these were allocate as output_buffers and extra_buffers */ if (num_output_buffers > 0) { FREE(results_buffers); } /* Free the buffers */ if (loop_options->allocate_buffer_function != NULL) { loop_options->allocate_buffer_function (loop_options->caller_data, FALSE, num_input_buffers, chunk_num_voxels, input_vector_length, &input_buffers, num_output_files, block_num_voxels, output_vector_length, &output_buffers, num_extra_buffers, chunk_num_voxels, output_vector_length, &extra_buffers, loop_options->loop_info); } else { /* Free input buffers */ for (ibuff=0; ibuff < num_input_buffers; ibuff++) { FREE(input_buffers[ibuff]); } FREE(input_buffers); /* Free output buffers */ if (num_output_files > 0) { for (ibuff=0; ibuff < num_output_files; ibuff++) { FREE(output_buffers[ibuff]); } FREE(output_buffers); } /* Free extra buffers */ if (num_extra_buffers > 0) { for (ibuff=0; ibuff < num_extra_buffers; ibuff++) { FREE(extra_buffers[ibuff]); } FREE(extra_buffers); } } /* Free max and min arrays */ if (num_output_files > 0) { FREE(global_minimum); FREE(global_maximum); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_looping @INPUT : loop_options - users options controlling looping loopfile_info - information on files @OUTPUT : ndims - number of dimensions block_start - vector specifying start of block block_end - end of block block_incr - increment for stepping through blocks block_num_voxels - number of voxels in block chunk_incr - increment for stepping through chunks chunk_num_voxels - number of voxels in chunk @RETURNS : (nothing) @DESCRIPTION: Routine to set up vectors giving blocks and chunks through which we will loop. @METHOD : @GLOBALS : @CALLS : @CREATED : December 2, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void setup_looping(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int *ndims, long block_start[], long block_end[], long block_incr[], long *block_num_voxels, long chunk_incr[], long *chunk_num_voxels) { int inmincid; int total_ndims, scalar_ndims, idim; int input_vector_length, output_vector_length; int num_input_buffers; int vector_data; int nimgdims; long size[MAX_VAR_DIMS]; long max_voxels_in_buffer; /* Get input mincid */ inmincid = get_input_mincid(loopfile_info, 0); /* Get number of dimensions and their sizes */ get_dim_info(inmincid, &total_ndims, size, NULL, NULL, NULL, NULL, NULL, loop_options); /* Get vector lengths */ input_vector_length = get_vector_length(inmincid, loop_options); if (get_output_numfiles(loopfile_info) > 0) output_vector_length = get_vector_length(get_output_mincid(loopfile_info, 0), NULL); else output_vector_length = 0; /* Check for vector data and whether we are adding a dimension */ vector_data = ((input_vector_length > 0) || (output_vector_length > 0)); if ((input_vector_length == 0) && (output_vector_length > 0)) { total_ndims++; size[total_ndims-1] = 1; } scalar_ndims = (vector_data ? total_ndims - 1 : total_ndims); /* Get number of image dimensions */ nimgdims = (vector_data ? 3 : 2); /* Set vector lengths properly */ if (input_vector_length <= 0) input_vector_length = 1; if (output_vector_length <= 0) output_vector_length = 1; /* Set vectors */ *block_num_voxels = 1; for (idim=0; idim < total_ndims; idim++) { block_start[idim] = 0; block_end[idim] = size[idim]; if (idim < total_ndims - nimgdims) block_incr[idim] = 1; else block_incr[idim] = size[idim]; *block_num_voxels *= block_incr[idim]; chunk_incr[idim] = 1; } if (vector_data) { *block_num_voxels /= input_vector_length; idim = total_ndims-1; chunk_incr[idim] = block_incr[idim]; } /* Figure out chunk size. Enforce a minimum chunk size. */ *chunk_num_voxels = 1; num_input_buffers = (loop_options->do_accumulate ? 1 : loop_options->num_all_inputs); max_voxels_in_buffer = (loop_options->total_copy_space/((long) sizeof(double)) - get_output_numfiles(loopfile_info) * *block_num_voxels * output_vector_length) / (num_input_buffers * input_vector_length + loop_options->num_extra_buffers * output_vector_length); if (max_voxels_in_buffer < MIN_VOXELS_IN_BUFFER) { max_voxels_in_buffer = MIN_VOXELS_IN_BUFFER; } if (max_voxels_in_buffer > 0) { for (idim=scalar_ndims-1; idim >= 0; idim--) { chunk_incr[idim] = max_voxels_in_buffer / *chunk_num_voxels; if (chunk_incr[idim] > block_incr[idim]) chunk_incr[idim] = block_incr[idim]; *chunk_num_voxels *= chunk_incr[idim]; } } /* Set ndims */ *ndims = total_ndims; } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_file_and_index @INPUT : loop_options - users options controlling looping loopfile_info - information on files do_loop - TRUE if looping stuff should really be done @OUTPUT : ifile - file counter dim_index - dimension index counter dummy_index - counter used when do_loop is FALSE @RETURNS : (nothing) @DESCRIPTION: Routine to initialize the file and index loop. These three routines allow looping through files and dimension indices at two levels. If do_loop is TRUE, then normal looping is done (increment dim_index fastest, then ifile). If do_loop is FALSE, then only one loop is performed (using dummy_index). @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void initialize_file_and_index(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int do_loop, int *ifile, int *dim_index, int *dummy_index) /* ARGSUSED */ { if (do_loop) { *ifile = 0; *dim_index = 0; } else { *dummy_index = 0; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : finish_file_and_index @INPUT : loop_options - users options controlling looping loopfile_info - information on files do_loop - TRUE if looping stuff should really be done ifile - file counter dim_index - dimension index counter dummy_index - counter used when do_loop is FALSE @RETURNS : TRUE while there are more buffers to process. @DESCRIPTION: Routine to test for the end of the file and index loop. These three routines allow looping through files and dimension indices at two levels. If do_loop is TRUE, then normal looping is done (increment dim_index fastest, then ifile). If do_loop is FALSE, then only one loop is performed (using dummy_index). @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int finish_file_and_index(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int do_loop, int ifile, int dim_index, int dummy_index) /* ARGSUSED */ { if (do_loop) { return (ifile < get_input_numfiles(loopfile_info)); } else { return (dummy_index < 1); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : increment_file_and_index @INPUT : loop_options - users options controlling looping loopfile_info - information on files do_loop - TRUE if looping stuff should really be done @OUTPUT : ifile - file counter dim_index - dimension index counter dummy_index - counter used when do_loop is FALSE @RETURNS : (nothing) @DESCRIPTION: Routine to increment the file and index loop. These three routines allow looping through files and dimension indices at two levels. If do_loop is TRUE, then normal looping is done (increment dim_index fastest, then ifile). If do_loop is FALSE, then only one loop is performed (using dummy_index). Note that dummy_index is not touched if do_loop is TRUE. @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void increment_file_and_index(Loop_Options *loop_options, Loopfile_Info *loopfile_info, int do_loop, int *ifile, int *dim_index, int *dummy_index) { int input_mincid; if (do_loop) { (*dim_index)++; input_mincid = get_input_mincid(loopfile_info, *ifile); if (*dim_index >= get_loop_dim_size(input_mincid, loop_options)) { *dim_index = 0; (*ifile)++; } } else { (*dummy_index)++; } } /* ------------ Routines controlling looping over files ------------ */ /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_loopfile_info @INPUT : num_input_files - number of input files input_files - list of input file names num_output_files - list of output file names output_files - list of output file names loop_options - user options for looping @OUTPUT : (none) @RETURNS : pointer to Loopfile_Info structure @DESCRIPTION: Routine to set up looping information for these files. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE Loopfile_Info *initialize_loopfile_info(int num_input_files, char *input_files[], int num_output_files, char *output_files[], Loop_Options *loop_options) { int num_free_files, num_files, ifile; Loopfile_Info *loopfile_info; /* Allocate structure */ loopfile_info = MALLOC(1, Loopfile_Info); /* Save clobber info */ if (loop_options->clobber) { loopfile_info->cflags = NC_CLOBBER; } else { loopfile_info->cflags = NC_NOCLOBBER; } #if MINC2 if (loop_options->v2format) { loopfile_info->cflags |= MI2_CREATE_V2; } #endif /* MINC2 */ /* Save number of input and output files */ loopfile_info->num_input_files = num_input_files; loopfile_info->num_output_files = num_output_files; /* Save input file names (just copy pointers, not strings) */ if (num_input_files > 0) { loopfile_info->input_files = MALLOC(num_input_files, char *); for (ifile=0; ifile < num_input_files; ifile++) loopfile_info->input_files[ifile] = input_files[ifile]; } else loopfile_info->input_files = NULL; /* Save output file names (just copy pointers, not strings) */ if (num_output_files > 0) { loopfile_info->output_files = MALLOC(num_output_files, char *); for (ifile=0; ifile < num_output_files; ifile++) loopfile_info->output_files[ifile] = output_files[ifile]; } else loopfile_info->output_files = NULL; /* Keep track of number of files that we can open */ num_free_files = loop_options->max_open_files; if (num_free_files > MI_MAX_NUM_ICV) num_free_files = MI_MAX_NUM_ICV; /* Check to see if we can open output files (we must leave room for one input file) */ if (num_output_files < num_free_files-1) { loopfile_info->output_all_open = TRUE; num_files = num_output_files; } else { loopfile_info->output_all_open = FALSE; num_files = 1; } num_free_files -= num_files; loopfile_info->output_mincid = MALLOC(num_files, int); loopfile_info->output_icvid = MALLOC(num_files, int); for (ifile=0; ifile < num_files; ifile++) { loopfile_info->output_mincid[ifile] = MI_ERROR; loopfile_info->output_icvid[ifile] = MI_ERROR; } loopfile_info->current_input_file_number = -1; /* Check whether sequential access would be better */ loopfile_info->sequential_access = (loop_options->do_accumulate && ((num_output_files + loop_options->num_extra_buffers) <= 0)); /* Check to see if we can open input files */ if (num_input_files < num_free_files) { loopfile_info->can_open_all_input = TRUE; num_files = num_input_files; } else { loopfile_info->can_open_all_input = FALSE; num_files = 1; } num_free_files -= num_files; loopfile_info->input_mincid = MALLOC(num_files, int); loopfile_info->input_icvid = MALLOC(num_files, int); for (ifile=0; ifile < num_files; ifile++) { loopfile_info->input_mincid[ifile] = MI_ERROR; loopfile_info->input_icvid[ifile] = MI_ERROR; } loopfile_info->current_output_file_number = -1; /* Check for an already open input file */ if (loop_options->input_mincid != MI_ERROR) { loopfile_info->input_mincid[0] = loop_options->input_mincid; loopfile_info->current_input_file_number = 0; } /* Check whether we want to open all input files */ loopfile_info->input_all_open = (! loopfile_info->sequential_access) && loopfile_info->can_open_all_input; /* Set default for expanding compressed files */ loopfile_info->headers_only = FALSE; loopfile_info->want_headers_only = FALSE; /* Return the loopfile_info structure */ return loopfile_info; } /* ----------------------------- MNI Header ----------------------------------- @NAME : cleanup_loopfile_info @INPUT : loopfile_info - looping information @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to clean up looping information. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void cleanup_loopfile_info(Loopfile_Info *loopfile_info) { int num_files, ifile; /* Close input files and free icv's */ if (loopfile_info->can_open_all_input) num_files = loopfile_info->num_input_files; else num_files = 1; for (ifile=0; ifile < num_files; ifile++) { if (loopfile_info->input_icvid[ifile] != MI_ERROR) (void) miicv_free(loopfile_info->input_icvid[ifile]); if (loopfile_info->input_mincid[ifile] != MI_ERROR) (void) miclose(loopfile_info->input_mincid[ifile]); } /* Close output files and free icv's */ if (loopfile_info->output_all_open) num_files = loopfile_info->num_output_files; else num_files = 1; for (ifile=0; ifile < num_files; ifile++) { (void) miicv_free(loopfile_info->output_icvid[ifile]); (void) miclose(loopfile_info->output_mincid[ifile]); } /* Free input arrays */ if (loopfile_info->input_files != NULL) FREE(loopfile_info->input_files); if (loopfile_info->input_mincid != NULL) FREE(loopfile_info->input_mincid); if (loopfile_info->input_icvid != NULL) FREE(loopfile_info->input_icvid); /* Free output arrays */ if (loopfile_info->output_files != NULL) FREE(loopfile_info->output_files); if (loopfile_info->output_mincid != NULL) FREE(loopfile_info->output_mincid); if (loopfile_info->output_icvid != NULL) FREE(loopfile_info->output_icvid); /* Free the structure */ FREE(loopfile_info); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_input_numfiles @INPUT : loopfile_info - looping information @OUTPUT : (none) @RETURNS : Number of input files @DESCRIPTION: Routine to get the number of input files. @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int get_input_numfiles(Loopfile_Info *loopfile_info) { return loopfile_info->num_input_files; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_output_numfiles @INPUT : loopfile_info - looping information @OUTPUT : (none) @RETURNS : Number of output files @DESCRIPTION: Routine to get the number of output files. @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int get_output_numfiles(Loopfile_Info *loopfile_info) { return loopfile_info->num_output_files; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_input_filename @INPUT : loopfile_info - looping information file_num - input file number @OUTPUT : (none) @RETURNS : Pointer to string containing input file name for file ifile. @DESCRIPTION: Routine to get name of an input file. @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE char *get_input_filename(Loopfile_Info *loopfile_info, int file_num) { /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_input_files)) { (void) fprintf(stderr, "Bad input file number %d\n", file_num); exit(EXIT_FAILURE); } return loopfile_info->input_files[file_num]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_input_headers_only @INPUT : loopfile_info - looping information headers_only - TRUE if we only need input headers, FALSE if we need the whole file. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to modify the Loopfile_Info structure so that in future we get either whole minc files or only the headers. The change is only made if it makes sense (ie. we are processing files sequentially). @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void set_input_headers_only(Loopfile_Info *loopfile_info, int headers_only) { int num_files, ifile; int icvid, mincid; /* Change the indication that we want to have headers only */ loopfile_info->want_headers_only = headers_only; /* If headers_only is not changing, don't do anything */ if ((headers_only && loopfile_info->headers_only) || (!headers_only && !loopfile_info->headers_only)) { return; } /* Check to see if it makes sense to change to headers only */ if (headers_only && loopfile_info->input_all_open) return; /* Change the value */ loopfile_info->headers_only = headers_only; /* If we are going to headers_only == FALSE, then loop through icv's and files, making sure that they are detached and closed (we will need to re-open them */ if (!loopfile_info->headers_only) { num_files = (loopfile_info->can_open_all_input ? loopfile_info->num_input_files : 1); for (ifile=0; ifile < num_files; ifile++) { icvid = loopfile_info->input_icvid[ifile]; mincid = MI_ERROR; if (icvid != MI_ERROR) { (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); if (mincid != MI_ERROR) { (void) miicv_detach(icvid); (void) miclose(mincid); } } if ((loopfile_info->input_mincid[ifile] != MI_ERROR) && (loopfile_info->input_mincid[ifile] != mincid)) { (void) miclose(loopfile_info->input_mincid[ifile]); } loopfile_info->input_mincid[ifile] = MI_ERROR; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_input_sequential @INPUT : loopfile_info - looping information sequential_access - TRUE if we want to open only one file at a time, FALSE otherwise. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to modify the Loopfile_Info structure so that files are opened one at a time. @METHOD : @GLOBALS : @CALLS : @CREATED : March 1, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void set_input_sequential(Loopfile_Info *loopfile_info, int sequential_access) { int old_input_all_open; int ifile, num_files; int mincid, icvid; int current_input_file_number; /* Set flag for sequential access */ loopfile_info->sequential_access = sequential_access; /* Change status of input_all_open */ old_input_all_open = loopfile_info->input_all_open; loopfile_info->input_all_open = (! loopfile_info->sequential_access) && loopfile_info->can_open_all_input; /* Check if input_all_open has changed */ if (!old_input_all_open && loopfile_info->input_all_open) { current_input_file_number = loopfile_info->current_input_file_number; if (current_input_file_number >= 0) { mincid = loopfile_info->input_mincid[0]; loopfile_info->input_mincid[0] = MI_ERROR; loopfile_info->input_mincid[current_input_file_number] = mincid; } } else if (old_input_all_open && !loopfile_info->input_all_open) { if (loopfile_info->can_open_all_input) num_files = loopfile_info->num_input_files; else num_files = 1; for (ifile=0; ifile < num_files; ifile++) { icvid = loopfile_info->input_icvid[ifile]; if (icvid != MI_ERROR) { (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); (void) miicv_detach(icvid); if (mincid != MI_ERROR) { (void) miclose(mincid); } } if ((loopfile_info->input_mincid[ifile] != MI_ERROR) && (loopfile_info->input_mincid[ifile] != mincid)) (void) miclose(loopfile_info->input_mincid[ifile]); loopfile_info->input_mincid[ifile] = MI_ERROR; } } /* Call set_input_headers_only in case want_headers_only is different from headers_only */ set_input_headers_only(loopfile_info, loopfile_info->want_headers_only); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_input_mincid @INPUT : loopfile_info - looping information file_num - input file number @OUTPUT : (none) @RETURNS : Id of minc file @DESCRIPTION: Routine to get the minc id for an input file. The file number corresponds to the file's position in the input_files list (counting from zero). @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int get_input_mincid(Loopfile_Info *loopfile_info, int file_num) { int index; int created_tempfile; char *filename; /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_input_files)) { (void) fprintf(stderr, "Bad input file number %d\n", file_num); exit(EXIT_FAILURE); } /* Check to see if all files are open or not */ if (loopfile_info->input_all_open) { index = file_num; } else { index = 0; if ((loopfile_info->input_mincid[index] != MI_ERROR) && (loopfile_info->current_input_file_number != file_num)) { if (loopfile_info->input_icvid[index] != MI_ERROR) (void) miicv_detach(loopfile_info->input_icvid[index]); (void) miclose(loopfile_info->input_mincid[index]); loopfile_info->input_mincid[index] = MI_ERROR; } loopfile_info->current_input_file_number = file_num; } /* Open the file if it hasn't been already */ if (loopfile_info->input_mincid[index] == MI_ERROR) { filename = miexpand_file(loopfile_info->input_files[file_num], NULL, loopfile_info->headers_only, &created_tempfile); loopfile_info->input_mincid[index] = miopen(filename, NC_NOWRITE); if (created_tempfile) { (void) remove(filename); } FREE(filename); } return loopfile_info->input_mincid[index]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_output_mincid @INPUT : loopfile_info - looping information file_num - output file number @OUTPUT : (none) @RETURNS : Id of minc file @DESCRIPTION: Routine to get the minc id for an output file. The file number corresponds to the file's position in the output_files list (counting from zero). @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int get_output_mincid(Loopfile_Info *loopfile_info, int file_num) { int index; /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_output_files)) { (void) fprintf(stderr, "Bad output file number %d\n", file_num); exit(EXIT_FAILURE); } /* Check to see if all files are open or not */ if (loopfile_info->output_all_open) { index = file_num; } else { index = 0; if ((loopfile_info->output_mincid[index] != MI_ERROR) && (loopfile_info->current_output_file_number != file_num)) { if (loopfile_info->output_icvid[index] != MI_ERROR) (void) miicv_detach(loopfile_info->output_icvid[index]); (void) miclose(loopfile_info->output_mincid[index]); loopfile_info->output_mincid[index] = MI_ERROR; } loopfile_info->current_output_file_number = file_num; } /* Open the file if it hasn't been already */ if (loopfile_info->output_mincid[index] == MI_ERROR) { loopfile_info->output_mincid[index] = miopen(loopfile_info->output_files[file_num], NC_WRITE); } return loopfile_info->output_mincid[index]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_output_file @INPUT : loopfile_info - looping information file_num - output file number @OUTPUT : (none) @RETURNS : Id of minc file @DESCRIPTION: Routine to create an output file. The file number corresponds to the file's position in the output_files list (counting from zero). @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int create_output_file(Loopfile_Info *loopfile_info, int file_num) { int index; /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_output_files)) { (void) fprintf(stderr, "Bad output file number %d for create.\n", file_num); exit(EXIT_FAILURE); } /* Check to see if all files are open or not */ if (loopfile_info->output_all_open) { index = file_num; } else { index = 0; if ((loopfile_info->output_mincid[index] != MI_ERROR) && (loopfile_info->current_output_file_number != file_num)) { (void) miclose(loopfile_info->output_mincid[index]); loopfile_info->output_mincid[index] = MI_ERROR; } loopfile_info->current_output_file_number = file_num; } /* Create the file */ if (loopfile_info->output_mincid[index] != MI_ERROR) { (void) fprintf(stderr, "File %s has already been created\n", loopfile_info->output_files[file_num]); exit(EXIT_FAILURE); } loopfile_info->output_mincid[index] = micreate(loopfile_info->output_files[file_num], loopfile_info->cflags); return loopfile_info->output_mincid[index]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_input_icvid @INPUT : loopfile_info - looping information file_num - input file number @OUTPUT : (none) @RETURNS : Id of icv for the specified file @DESCRIPTION: Routine to get the icv id for an input file. The file number corresponds to the file's position in the input_files list (counting from zero). @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int get_input_icvid(Loopfile_Info *loopfile_info, int file_num) { int mincid, icv_mincid, icvid; int index; /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_input_files)) { (void) fprintf(stderr, "Bad input file number %d\n", file_num); exit(EXIT_FAILURE); } /* Check to see if all files are open or not - get the correct index */ if (loopfile_info->can_open_all_input) { index = file_num; } else { index = 0; } /* Check to see if the icv is attached to the correct minc file. If not, re-attach it. */ icvid = loopfile_info->input_icvid[index]; mincid = get_input_mincid(loopfile_info, file_num); if (icvid != MI_ERROR) (void) miicv_inqint(icvid, MI_ICV_CDFID, &icv_mincid); else icv_mincid = MI_ERROR; if (mincid != icv_mincid) { (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); } return icvid; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_output_icvid @INPUT : loopfile_info - looping information file_num - output file number @OUTPUT : (none) @RETURNS : Id of icv for the specified file @DESCRIPTION: Routine to get the icv id for an output file. The file number corresponds to the file's position in the output_files list (counting from zero). @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int get_output_icvid(Loopfile_Info *loopfile_info, int file_num) { int mincid, icv_mincid, icvid; int index; /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_output_files)) { (void) fprintf(stderr, "Bad output file number %d\n", file_num); exit(EXIT_FAILURE); } /* Check to see if all files are open or not - get the correct index */ if (loopfile_info->output_all_open) { index = file_num; } else { index = 0; } /* Check to see if the icv is attached to the correct minc file. If not, re-attach it. */ icvid = loopfile_info->output_icvid[index]; mincid = get_output_mincid(loopfile_info, file_num); if (icvid != MI_ERROR) (void) miicv_inqint(icvid, MI_ICV_CDFID, &icv_mincid); else icv_mincid = MI_ERROR; if (mincid != icv_mincid) { (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); } return icvid; } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_input_icvid @INPUT : loopfile_info - looping information file_num - input file number @OUTPUT : (none) @RETURNS : Id of icv for the specified file @DESCRIPTION: Routine to create the icv id for an input file. The file number corresponds to the file's position in the input_files list (counting from zero). If the icv already exists, just return it. If there are too many files, then only one icv will be used. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int create_input_icvid(Loopfile_Info *loopfile_info, int file_num) { int index; /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_input_files)) { (void) fprintf(stderr, "Bad input file number %d\n", file_num); exit(EXIT_FAILURE); } /* Check to see if all files are open or not - get the correct index */ if (loopfile_info->can_open_all_input) { index = file_num; } else { index = 0; } /* Check to see if icv exists - if not create it */ if (loopfile_info->input_icvid[index] == MI_ERROR) { loopfile_info->input_icvid[index] = miicv_create(); } return loopfile_info->input_icvid[index]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_output_icvid @INPUT : loopfile_info - looping information file_num - output file number @OUTPUT : (none) @RETURNS : Id of icv for the specified file @DESCRIPTION: Routine to create the icv id for an output file. The file number corresponds to the file's position in the output_files list (counting from zero). If the icv already exists, just return it. If there are too many files, then only one icv will be used. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE int create_output_icvid(Loopfile_Info *loopfile_info, int file_num) { int index; /* Check for bad file_num */ if ((file_num < 0) || (file_num >= loopfile_info->num_output_files)) { (void) fprintf(stderr, "Bad output file number %d\n", file_num); exit(EXIT_FAILURE); } /* Check to see if all files are open or not - get the correct index */ if (loopfile_info->output_all_open) { index = file_num; } else { index = 0; } /* Check to see if icv exists - if not create it */ if (loopfile_info->output_icvid[index] == MI_ERROR) { loopfile_info->output_icvid[index] = miicv_create(); } return loopfile_info->output_icvid[index]; } /* ------------ Routines to set loop options ------------ */ /* ----------------------------- MNI Header ----------------------------------- @NAME : create_loop_options @INPUT : (none) @OUTPUT : (none) @RETURNS : Pointer to Loop_Options structure @DESCRIPTION: Routine to create and initialize the loop options structure. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI Loop_Options *create_loop_options(void) { Loop_Options *loop_options; /* Allocate structure */ loop_options = MALLOC(1, Loop_Options); /* Fill in the defaults */ loop_options->clobber = FALSE; loop_options->verbose = TRUE; loop_options->datatype = MI_ORIGINAL_TYPE; loop_options->is_signed = TRUE; loop_options->valid_range[0] = 0.0; loop_options->valid_range[1] = 0.0; loop_options->max_open_files = MI_MAX_NUM_ICV - 2; loop_options->check_all_input_dim_info = TRUE; loop_options->convert_input_to_scalar = FALSE; loop_options->output_vector_size = 0; loop_options->input_mincid = MI_ERROR; loop_options->total_copy_space = miget_cfg_int(MICFG_MAXBUF) * 1024; if(loop_options->total_copy_space == 0){ loop_options->total_copy_space = MI2_DEF_BUFF_SIZE * 1024; } loop_options->loop_dimension = NULL; loop_options->num_all_inputs = 0; loop_options->input_file_function = NULL; loop_options->output_file_function = NULL; loop_options->copy_all_header_info = TRUE; loop_options->do_accumulate = FALSE; loop_options->num_extra_buffers = 0; loop_options->start_function = NULL; loop_options->finish_function = NULL; loop_options->voxel_function = NULL; loop_options->caller_data = NULL; loop_options->loop_info = create_loop_info(); loop_options->allocate_buffer_function = NULL; #if MINC2 loop_options->v2format = FALSE; /* Use MINC 2.0 file format (HDF5)? */ #endif /* MINC2 */ /* Return the structure pointer */ return loop_options; } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_loop_options @INPUT : loop_options - pointer to structure to cleanup @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Routine to cleanup and free the Loop_Options structure @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void free_loop_options(Loop_Options *loop_options) { free_loop_info(loop_options->loop_info); if (loop_options->loop_dimension != NULL) FREE(loop_options->loop_dimension); FREE(loop_options); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_clobber @INPUT : loop_options - user options for looping verbose - TRUE if output files should be clobbered @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn output clobber on or off @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_clobber(Loop_Options *loop_options, int clobber) { loop_options->clobber = clobber; } #if MINC2 /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_v2format @INPUT : loop_options - user options for looping v2format - TRUE if output files should use MINC 2.0 format @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn output clobber on or off @METHOD : @GLOBALS : @CALLS : @CREATED : October 8, 2003 (Bert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_v2format(Loop_Options *loop_options, int v2format) { loop_options->v2format = v2format; } #endif /* MINC2 */ /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_verbose @INPUT : loop_options - user options for looping verbose - TRUE if logging should be done. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn logging on or off. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_verbose(Loop_Options *loop_options, int verbose) { loop_options->verbose = verbose; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_datatype @INPUT : loop_options - user options for looping datatype - NetCDF datatype for output (MI_ORIGINAL_TYPE means use input type) is_signed - TRUE if type is signed valid_min - valid minimum for type (if valid_min >= valid_max, then defaults are used) valid_max - valid maximum for type @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to set the output file datatype, sign and range. @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_datatype(Loop_Options *loop_options, nc_type datatype, int is_signed, double valid_min, double valid_max) { loop_options->datatype = datatype; loop_options->is_signed = is_signed; loop_options->valid_range[0] = valid_min; loop_options->valid_range[1] = valid_max; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_max_open_files @INPUT : loop_options - user options for looping max_open_files - maximum number of open files allowed (between 1 and MI_MAX_NUM_ICV) @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to set the maximum number of open minc files. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_max_open_files(Loop_Options *loop_options, int max_open_files) { if ((max_open_files <= 0) || (max_open_files > MI_MAX_NUM_ICV)) { (void) fprintf(stderr, "Bad number of files %d in set_loop_max_open_files\n", max_open_files); exit(EXIT_FAILURE); } loop_options->max_open_files = max_open_files; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_check_dim_info @INPUT : loop_options - user options for looping check_dim_info - TRUE if all dimension information in input files should be check, FALSE otherwise @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn dimension info checking on or off. @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_check_dim_info(Loop_Options *loop_options, int check_dim_info) { loop_options->check_all_input_dim_info = check_dim_info; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_convert_input_to_scalar @INPUT : loop_options - user options for looping convert_input_to_scalar - TRUE if input should be converted to scalar values @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to allow input to be converted to scalar values @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_convert_input_to_scalar(Loop_Options *loop_options, int convert_input_to_scalar) { loop_options->convert_input_to_scalar = convert_input_to_scalar; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_output_vector_size @INPUT : loop_options - user options for looping output_vector_size - length of vector dimension for output. 0 means keep the size the same as the input. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn set the length of the vector dimension for output. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_output_vector_size(Loop_Options *loop_options, int output_vector_size) { if (output_vector_size < 0) { (void) fprintf(stderr, "Bad vector size %d in set_loop_output_vector_size\n", output_vector_size); exit(EXIT_FAILURE); } loop_options->output_vector_size = output_vector_size; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_first_input_mincid @INPUT : loop_options - user options for looping input_mincid - id of first minc file (already opened). @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn allow the user to pass in an already opened minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_first_input_mincid(Loop_Options *loop_options, int input_mincid) { loop_options->input_mincid = input_mincid; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_buffer_size @INPUT : loop_options - user options for looping buffer_size - maximum amount of buffer space to use (in bytes). @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn set a limit on the amount of buffer space used. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_buffer_size(Loop_Options *loop_options, long buffer_size) { if (buffer_size <= 0) { (void) fprintf(stderr, "Bad buffer size %d in set_loop_buffer_size\n", (int) buffer_size); } loop_options->total_copy_space = buffer_size; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_dimension @INPUT : loop_options - user options for looping dimension_name - name of dimension that is treated like a series of input files. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to allow a dimension to be treated like a series of input files (one buffer per dimension element per file). @METHOD : @GLOBALS : @CALLS : @CREATED : January 24, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_dimension(Loop_Options *loop_options, char *dimension_name) { if (loop_options->loop_dimension != NULL) FREE(loop_options->loop_dimension); if ((dimension_name == NULL) || ((int)strlen(dimension_name) <= 0)) { loop_options->loop_dimension = NULL; } else { loop_options->loop_dimension = strdup(dimension_name); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_input_file_function @INPUT : loop_options - user options for looping input_file_function - function to be called for each input file so that the user can extract any extract information. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to allow the user to define a function to be called for each input file before processing is done. @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_input_file_function (Loop_Options *loop_options, VoxelInputFileFunction input_file_function) { loop_options->input_file_function = input_file_function; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_output_file_function @INPUT : loop_options - user options for looping output_file_function - function to be called for each output file so that the user can modify the header (file is in define mode). @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to allow the user to define a function to be called for each output file so that things can be added to the header. The file will be in define mode and should remain that way. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_output_file_function (Loop_Options *loop_options, VoxelOutputFileFunction output_file_function) { loop_options->output_file_function = output_file_function; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_copy_all_header @INPUT : loop_options - user options for looping copy_all_header - TRUE if all header info should be copied to output file @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn copying of all header info off. @METHOD : @GLOBALS : @CALLS : @CREATED : March 13, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_copy_all_header(Loop_Options *loop_options, int copy_all_header) { loop_options->copy_all_header_info = copy_all_header; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_accumulate @INPUT : loop_options - user options for looping do_accumulation - TRUE if accumulating should be done, FALSE otherwise. num_extra_buffers - number of extra buffers to allocate. start_function - function to be called before looping with all output and extra buffers as arguments. NULL means don't call any function. finish_function - function to be called after looping with all output and extra buffers as arguments. NULL means don't call any function. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to turn allow an accumulation mode of looping. Instead of loading all input files and then calling the voxel routine, the voxel routine is called after for each input file. The user can provide a start_function that is called to initialize the output buffers and a finish_function that is called to finish calculations. The user can also ask for extra buffers. These are treated like output buffers (at the end of the list) but are not written out. @METHOD : @GLOBALS : @CALLS : @CREATED : December 6, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void set_loop_accumulate(Loop_Options *loop_options, int do_accumulation, int num_extra_buffers, VoxelStartFunction start_function, VoxelFinishFunction finish_function) { loop_options->do_accumulate = do_accumulation; /* Turning off accumulation */ if (!do_accumulation) { loop_options->num_extra_buffers = 0; loop_options->start_function = NULL; loop_options->finish_function = NULL; } /* Turning on accumulation */ else { if (num_extra_buffers < 0) { (void) fprintf(stderr, "Bad num_extra_buffers %d in set_loop_accumulate\n", num_extra_buffers); exit(EXIT_FAILURE); } loop_options->do_accumulate = TRUE; loop_options->num_extra_buffers = num_extra_buffers; loop_options->start_function = start_function; loop_options->finish_function = finish_function; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_loop_allocate_buffer_function @INPUT : loop_options - user options for looping allocate_buffer_function - user function that allocates and frees input_data @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to set the function that allocates and frees input_data @METHOD : @GLOBALS : @CALLS : @CREATED : Aug 29, 2000 (J. Taylor) @MODIFIED : Sept. 19, 2000 (P. Neelin) ---------------------------------------------------------------------------- */ MNCAPI void set_loop_allocate_buffer_function(Loop_Options *loop_options, AllocateBufferFunction allocate_buffer_function) { loop_options->allocate_buffer_function = allocate_buffer_function; } /* ------------ Routines to set and get loop info ------------ */ /* ----------------------------- MNI Header ----------------------------------- @NAME : create_loop_info @INPUT : (none) @OUTPUT : (none) @RETURNS : Pointer to Loop_Info structure @DESCRIPTION: Routine to create and initialize the loop info structure. @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE Loop_Info *create_loop_info(void) { Loop_Info *loop_info; /* Allocate structure */ loop_info = MALLOC(1, Loop_Info); /* Fill in the defaults */ initialize_loop_info(loop_info); /* Return the structure pointer */ return loop_info; } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_loop_info @INPUT : loop_info - pointer to Loop_Info structure @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to initialize the loop info structure. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void initialize_loop_info(Loop_Info *loop_info) { int idim; /* Fill in the defaults */ loop_info->current_file = 0; loop_info->current_index = 0; for (idim=0; idim < MAX_VAR_DIMS; idim++) { loop_info->start[idim] = 0; loop_info->count[idim] = 0; } loop_info->loopfile_info = NULL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_loop_info @INPUT : loop_info - pointer to structure to cleanup @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Routine to cleanup and free the Loop_Info structure @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void free_loop_info(Loop_Info *loop_info) { FREE(loop_info); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_info_shape @INPUT : loop_info - info structure pointer start - start of hyperslab count - count of hyperslab @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Routine to set the hyperslab shape (start and count) @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void set_info_shape(Loop_Info *loop_info, long start[], long count[]) { int idim; long size; /* Save the shape of the current chunk */ for (idim=0; idim < MAX_VAR_DIMS; idim++) { loop_info->start[idim] = start[idim]; loop_info->count[idim] = count[idim]; } /* Figure out how many voxels will be skipped by a step of one in each dimension */ loop_info->dimvoxels[MAX_VAR_DIMS-1] = 1; for (idim=MAX_VAR_DIMS-2; idim >= 0; idim--) { size = loop_info->count[idim+1]; if (size <= 0) size = 1; loop_info->dimvoxels[idim] = size * loop_info->dimvoxels[idim+1]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_info_shape @INPUT : loop_info - info structure pointer ndims - number of dimensions to copy (uses MAX_VAR_DIMS if ndims == 0) @OUTPUT : start - start of hyperslab count - count of hyperslab @RETURNS : (none) @DESCRIPTION: Routine to get the current hyperslab shape (start and count) @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void get_info_shape(Loop_Info *loop_info, int ndims, long start[], long count[]) { int idim; if ((ndims <= 0) || (ndims > MAX_VAR_DIMS)) ndims = MAX_VAR_DIMS; for (idim=0; idim < ndims; idim++) { start[idim] = loop_info->start[idim]; count[idim] = loop_info->count[idim]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_info_voxel_index @INPUT : loop_info - info structure pointer subscript - 1-D voxel index into data buffers of voxel function ndims - number of dimensions in index array (uses MAX_VAR_DIMS if ndims == 0) @OUTPUT : index - multi-dimensional voxel index into file @RETURNS : (none) @DESCRIPTION: Routine to get the current voxel index. @METHOD : @GLOBALS : @CALLS : @CREATED : November 28, 2001 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI void get_info_voxel_index(Loop_Info *loop_info, long subscript, int ndims, long index[]) { int idim; long this_index; /* Check the array size */ if ((ndims <= 0) || (ndims > MAX_VAR_DIMS)) ndims = MAX_VAR_DIMS; /* Convert the 1-D subscript into a multi-dim index and add it to the start index of the chunk */ for (idim=0; idim < ndims; idim++) { this_index = subscript / loop_info->dimvoxels[idim]; index[idim] = loop_info->start[idim] + this_index; subscript -= this_index * loop_info->dimvoxels[idim]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_info_current_file @INPUT : loop_info - info structure pointer current_file - number of current input file (for accumulation) @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Routine to set the current input file number. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void set_info_current_file(Loop_Info *loop_info, int current_file) { loop_info->current_file = current_file; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_info_current_file @INPUT : loop_info - info structure pointer @OUTPUT : (none) @RETURNS : Number of current input file (for accumulating over files) @DESCRIPTION: Routine to get the current input file number. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int get_info_current_file(Loop_Info *loop_info) { return loop_info->current_file; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_info_current_mincid @INPUT : loop_info - info structure pointer @OUTPUT : (none) @RETURNS : Minc id for current input file (for accumulating over files) @DESCRIPTION: Routine to get the current input file mincid. @METHOD : @GLOBALS : @CALLS : @CREATED : March 8, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int get_info_current_mincid(Loop_Info *loop_info) { if (loop_info->loopfile_info == NULL) return MI_ERROR; return get_input_mincid(loop_info->loopfile_info, loop_info->current_file); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_info_current_index @INPUT : loop_info - info structure pointer current_index - number of current dimension index (for accumulation over files and dimension) @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Routine to set the current dimension index. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void set_info_current_index(Loop_Info *loop_info, int current_index) { loop_info->current_index = current_index; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_info_current_index @INPUT : loop_info - info structure pointer @OUTPUT : (none) @RETURNS : Number of current dimension index (for accumulating over files) @DESCRIPTION: Routine to get the current dimension index. @METHOD : @GLOBALS : @CALLS : @CREATED : February 28, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int get_info_current_index(Loop_Info *loop_info) { return loop_info->current_index; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_info_loopfile_info @INPUT : loop_info - info structure pointer loopfile_info - loopfile info structure pointer @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Routine to set the loopfile info structure for future queries @METHOD : @GLOBALS : @CALLS : @CREATED : March 7, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ PRIVATE void set_info_loopfile_info(Loop_Info *loop_info, Loopfile_Info *loopfile_info) { loop_info->loopfile_info = loopfile_info; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_info_whole_file @INPUT : loop_info - info structure pointer @OUTPUT : (none) @RETURNS : Id of current minc file @DESCRIPTION: Routine to change minc file handling to get the whole input file, not just the header (should be called from within the input_file_function). @METHOD : @GLOBALS : @CALLS : @CREATED : March 7, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ MNCAPI int get_info_whole_file(Loop_Info *loop_info) { Loopfile_Info *loopfile_info; /* Check for NULL pointer */ if (loop_info->loopfile_info == NULL) return MI_ERROR; loopfile_info = loop_info->loopfile_info; /* Make the input non-sequential (hold the files open if possible), and ask for whole files */ set_input_sequential(loopfile_info, FALSE); set_input_headers_only(loopfile_info, FALSE); /* Return the current minc file id */ if (loop_info->current_file >= 0) return get_input_mincid(loopfile_info, loop_info->current_file); else return MI_ERROR; } minc-2.2.00/libsrc/hdf_convenience.c0000644000265600003100000015717312030075003014202 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #if MINC2 /* Ignore this file if not MINC2 */ /* #define NC_FILL_INT 1 */ #include "minc_private.h" #include "hdf_convenience.h" #define MI2_STD_DIM_COUNT 9 #define MI2_DIMORDER "dimorder" #define MI2_LENGTH "length" #define MI2_CLASS "class" /************************************************************************ * Structures for files, variables, and dimensions. ************************************************************************/ struct m2_var { char name[NC_MAX_NAME]; char path[NC_MAX_NAME]; int id; int ndims; int is_cmpd; /* Is compound? */ hsize_t *dims; hid_t dset_id; hid_t ftyp_id; /* File type */ hid_t mtyp_id; /* Memory type */ hid_t fspc_id; }; struct m2_dim { struct m2_dim *link; int id; long length; int is_fake; /* TRUE if "emulated" vector dimension. */ char name[NC_MAX_NAME]; }; struct m2_file { struct m2_file *link; hid_t fd; int wr_ok; /* non-zero if write OK */ int resolution; /* Resolution setting. */ int nvars; int ndims; struct m2_var *vars[NC_MAX_VARS]; struct m2_dim *dims[NC_MAX_DIMS]; hid_t grp_id; /* Root group ID */ int comp_type; /* Compression type */ int comp_param; /* Compression parameter */ int chunk_type; /* Chunking enabled */ int chunk_param; /* Chunk length */ } *_m2_list; static struct m2_file * hdf_id_check(int fd) { struct m2_file *curr; for (curr = _m2_list; curr != NULL; curr = curr->link) { if (fd == curr->fd) { return (curr); } } return (NULL); } static struct m2_file * hdf_id_add(int fd) { struct m2_file *new; new = (struct m2_file *) malloc(sizeof (struct m2_file)); if (new != NULL) { new->fd = fd; new->resolution = 0; new->nvars = 0; new->ndims = 0; new->link =_m2_list; new->grp_id = H5Gopen1(fd, MI2_GRPNAME); new->comp_type = MI2_COMP_UNKNOWN; new->comp_param = 0; new->chunk_type = MI2_CHUNK_UNKNOWN; new->chunk_param = 0; _m2_list = new; } else { milog_message(MI_MSG_OUTOFMEM, sizeof(struct m2_file)); exit(-1); } return (new); } static int hdf_id_del(int fd) { struct m2_file *curr, *prev; int i; for (prev = NULL, curr = _m2_list; curr != NULL; prev = curr, curr = curr->link) { if (fd == curr->fd) { /* Unlink it from the global list. */ if (prev == NULL) { _m2_list = curr->link; } else { prev->link = curr->link; } /* Delete the variable list. */ for (i = 0; i < curr->nvars; i++) { struct m2_var *tmp = curr->vars[i]; if (tmp->dims != NULL) { free(tmp->dims); } /* Close the HDF5 handles we were holding open. */ H5Dclose(tmp->dset_id); H5Tclose(tmp->ftyp_id); H5Tclose(tmp->mtyp_id); H5Sclose(tmp->fspc_id); free(tmp); } /* Delete the dimension list. */ for (i = 0; i < curr->ndims; i++) { struct m2_dim *tmp = curr->dims[i]; free(tmp); } H5Gclose(curr->grp_id); free(curr); return (MI_NOERROR); } } return (MI_ERROR); } struct m2_var * hdf_var_byname(struct m2_file *file, const char *name) { int i; for (i = 0; i < file->nvars; i++) { if (!strcmp(file->vars[i]->name, name)) { return (file->vars[i]); } } return (NULL); } struct m2_var * hdf_var_byid(struct m2_file *file, int varid) { if (varid >= 0 && varid < file->nvars) { return (file->vars[varid]); } return (NULL); } struct m2_var * hdf_var_add(struct m2_file *file, const char *name, const char *path, int ndims, hsize_t *dims) { struct m2_var *new; if (file->nvars >= NC_MAX_VARS) { return (NULL); } new = (struct m2_var *) malloc(sizeof(struct m2_var)); if (new != NULL) { new->id = file->nvars++; strncpy(new->name, name, NC_MAX_NAME - 1); strncpy(new->path, path, NC_MAX_NAME - 1); new->is_cmpd = 0; new->dset_id = H5Dopen1(file->fd, path); new->ftyp_id = H5Dget_type(new->dset_id); new->mtyp_id = H5Tget_native_type(new->ftyp_id, H5T_DIR_ASCEND); new->fspc_id = H5Dget_space(new->dset_id); new->ndims = ndims; if (ndims != 0) { new->dims = (hsize_t *) malloc(sizeof (hsize_t) * ndims); if (new->dims != NULL) { int i; for (i = 0; i < ndims; i++) { new->dims[i] = dims[i]; } } else { milog_message(MI_MSG_OUTOFMEM, sizeof(hsize_t) * ndims); } } else { new->dims = NULL; } file->vars[new->id] = new; } else { milog_message(MI_MSG_OUTOFMEM, sizeof (struct m2_var)); exit(-1); } return (new); } /** Find a dimension by name. */ struct m2_dim * hdf_dim_byname(struct m2_file *file, const char *name) { int i; for (i = 0; i < file->ndims; i++) { if (!strcmp(file->dims[i]->name, name)) { return (file->dims[i]); } } return (NULL); } /** Find a dimension by ID number. */ struct m2_dim * hdf_dim_byid(struct m2_file *file, int dimid) { if (dimid >= 0 && dimid < file->ndims) { return (file->dims[dimid]); } return (NULL); } struct m2_dim * hdf_dim_add(struct m2_file *file, const char *name, long length) { struct m2_dim *new; if (file->ndims >= NC_MAX_DIMS) { return (NULL); } new = (struct m2_dim *) malloc(sizeof(struct m2_dim)); if (new != NULL) { new->id = file->ndims++; new->length = length; new->is_fake = 0; strncpy(new->name, name, NC_MAX_NAME - 1); file->dims[new->id] = new; } else { milog_message(MI_MSG_OUTOFMEM, sizeof(struct m2_dim)); exit(-1); } return (new); } /************************************************************************ * Other helper functions ************************************************************************/ static int hdf_is_dimension_name(struct m2_file *file, const char *varnm) { static char *dimnms[MI2_STD_DIM_COUNT] = { MIxspace, MIyspace, MIzspace, MItime, MIxfrequency, MIyfrequency, MIzfrequency, MItfrequency, MIvector_dimension, }; int i; if (hdf_dim_byname(file, varnm) != NULL) { return (1); } for (i = 0; i < MI2_STD_DIM_COUNT; i++) { if (!strcmp(varnm, dimnms[i])) { return (1); } } return (0); /* Not a dimension (yet?) */ } /** Find the path of a variable, given its name. The variable * may not yet exist in the file. */ static hid_t hdf_path_from_name(struct m2_file *file, const char *varnm, char *varpath) { if (!strcmp(varnm, MIimage) || !strcmp(varnm, MIimagemax) || !strcmp(varnm, MIimagemin)) { sprintf(varpath, "/minc-2.0/image/%d/", file->resolution); } else if (hdf_is_dimension_name(file, varnm)) { strcpy(varpath, "/minc-2.0/dimensions/"); } else { strcpy(varpath, "/minc-2.0/info/"); } strcat(varpath, varnm); return (MI_NOERROR); } /* map NetCDF types onto HDF types */ hid_t nc_to_hdf5_type(nc_type dtype, int is_signed) { switch (dtype) { case NC_CHAR: return (is_signed ? H5T_STD_I8LE : H5T_STD_U8LE); case NC_BYTE: return (is_signed ? H5T_STD_I8LE : H5T_STD_U8LE); case NC_SHORT: return (is_signed ? H5T_STD_I16LE : H5T_STD_U16LE); case NC_INT: return (is_signed ? H5T_STD_I32LE : H5T_STD_U32LE); case NC_FLOAT: return (H5T_IEEE_F32LE); case NC_DOUBLE: return (H5T_IEEE_F64LE); case NC_NAT: return (H5T_NO_CLASS); } return (-1); } static void hdf_get_diminfo(hid_t dst_id, int *ndims, hsize_t dims[]) { hid_t spc_id; spc_id = H5Dget_space(dst_id); if (spc_id < 0) { milog_message(MI_MSG_SNH); } else { *ndims = H5Sget_simple_extent_ndims(spc_id); if (*ndims > 0) { H5Sget_simple_extent_dims(spc_id, dims, NULL); } } } static int hdf_size(hid_t spc_id, hid_t typ_id) { int typ_size = H5Tget_size(typ_id); int spc_size = H5Sget_simple_extent_npoints(spc_id); if (typ_size <= 0 || spc_size <= 0) { milog_message(MI_MSG_SNH); return (-1); } return (typ_size * spc_size); } /** Given a numeric variable ID, get the text name of a MINC/HDF5 variable. * Equivalent of ncvarname() */ int hdf_varname(int fd, int varid, char *varnm) { struct m2_file *file; struct m2_var *var; /* Emulate rootvariable. */ if (varid == MI_ROOTVARIABLE_ID) { strcpy(varnm, MIrootvariable); return (MI_NOERROR); } if ((file = hdf_id_check(fd)) != NULL && (var = hdf_var_byid(file, varid)) != NULL) { strcpy(varnm, var->name); return (MI_NOERROR); } return (MI_ERROR); } /** Given a text name, get the numeric ID of a MINC/HDF5 variable. * Equivalent of ncvarid(). */ int hdf_varid(int fd, const char *varnm) { struct m2_file *file; struct m2_var *var; if (!strcmp(varnm, MIrootvariable)) { return (MI_ROOTVARIABLE_ID); } file = hdf_id_check(fd); if (file != NULL) { var = hdf_var_byname(file, varnm); if (var != NULL) { return (var->id); } } return (MI_ERROR); } /** Given a variable ID and attribute number return the attribute's text * name. The variable ID may be NC_GLOBAL. Equivalent to ncattname(). */ int hdf_attname(int fd, int varid, int attnum, char *name) { hid_t loc_id; hid_t att_id; int status; struct m2_file *file; struct m2_var *var; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if (varid == NC_GLOBAL) { var = NULL; loc_id = file->grp_id; } else { if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } loc_id = var->dset_id; } H5E_BEGIN_TRY { att_id = H5Aopen_idx(loc_id, attnum); } H5E_END_TRY; if (att_id >= 0) { status = H5Aget_name(att_id, MAX_NC_NAME, name); H5Aclose(att_id); } else { /* See if this is the magic emulated signtype attribute. */ if (var != NULL && !strcmp(var->name, MIimage) && attnum == H5Aget_num_attrs(loc_id)) { strcpy(name, MIsigntype); status = MI_NOERROR; } else { status = MI_ERROR; } } return (status); } /** This function provides emulation for the "ncattinq()" call which * is part of netCDF. Unlike a number of netCDF functions, this * function is expected to return 1 on success, rather than zero. */ int hdf_attinq(int fd, int varid, const char *attnm, nc_type *type_ptr, int *length_ptr) { hid_t att_id = -1; hid_t typ_id = -1; hid_t spc_id = -1; hid_t loc_id; int status = MI_ERROR; size_t typ_size; H5T_class_t typ_class; struct m2_file *file; struct m2_var *var; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if (varid == NC_GLOBAL) { var = NULL; loc_id = file->grp_id; } else { if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } loc_id = var->dset_id; } /* Special case - emulate the signtype attribute. */ if (!strcmp(attnm, MIsigntype)) { if (var != NULL && H5Tget_class(var->ftyp_id) == H5T_INTEGER) { if (type_ptr != NULL) { *type_ptr = NC_CHAR; } if (length_ptr != NULL) { /* Signed and unsigned are the same length, */ *length_ptr = sizeof(MI_UNSIGNED); } return (1); /* 1 -> success here */ } else { return (MI_ERROR); } } else { H5E_BEGIN_TRY { att_id = H5Aopen_name(loc_id, attnm); } H5E_END_TRY; if (att_id < 0) goto cleanup; if ((spc_id = H5Aget_space(att_id)) < 0) goto cleanup; if ((typ_id = H5Aget_type(att_id)) < 0) goto cleanup; typ_class = H5Tget_class(typ_id); typ_size = H5Tget_size(typ_id); if (type_ptr != NULL) { if (typ_class == H5T_INTEGER) { if (typ_size == 1) *type_ptr = NC_BYTE; else if (typ_size == 2) *type_ptr = NC_SHORT; else if (typ_size == 4) *type_ptr = NC_INT; else { milog_message(MI_MSG_INTSIZE, typ_size); } } else if (typ_class == H5T_FLOAT) { if (typ_size == 4) { *type_ptr = NC_FLOAT; } else if (typ_size == 8) { *type_ptr = NC_DOUBLE; } else { milog_message(MI_MSG_FLTSIZE, typ_size); } } else if (typ_class == H5T_STRING) { *type_ptr = NC_CHAR; } else { milog_message(MI_MSG_TYPECLASS, typ_class); } } if (length_ptr != NULL) { if (typ_class == H5T_STRING) { *length_ptr = typ_size; } else { *length_ptr = H5Sget_simple_extent_npoints(spc_id); } } status = 1; /* 1 -> success here */ cleanup: if (typ_id >= 0) H5Tclose(typ_id); if (spc_id >= 0) H5Sclose(spc_id); if (att_id >= 0) H5Aclose(att_id); } return (status); } static int hdf_put_dimorder(struct m2_file *file, int dst_id, int ndims, const int *dims_ptr) { int i; hid_t att_id; hid_t spc_id; hid_t typ_id; char str_buf[NC_MAX_NAME]; /* Don't bother */ if (ndims == 0) { return (MI_NOERROR); } str_buf[0] = '\0'; for (i = 0; i < ndims; i++) { struct m2_dim *dim = hdf_dim_byid(file, dims_ptr[i]); if (dim != NULL) { strcat(str_buf, dim->name); } if (i != ndims - 1) { strcat(str_buf, ","); } } typ_id = H5Tcopy(H5T_C_S1); H5Tset_size(typ_id, strlen(str_buf) + 1); spc_id = H5Screate(H5S_SCALAR); att_id = H5Acreate(dst_id, MI2_DIMORDER, typ_id, spc_id, H5P_DEFAULT, H5P_DEFAULT); if (att_id >= 0) { H5Awrite(att_id, typ_id, str_buf); } H5Aclose(att_id); H5Sclose(spc_id); H5Tclose(typ_id); return (MI_NOERROR); } static int hdf_get_dimorder(struct m2_file *file, int dst_id, int ndims, int *dims_ptr) { char *str_ptr; char *tmp_ptr; hid_t att_id; hid_t typ_id; char buf[NC_MAX_NAME]; int status; struct m2_dim *dim; int n; int done; int length; /* Don't bother */ if (ndims == 0) { return (MI_NOERROR); } att_id = H5Aopen_name(dst_id, MI2_DIMORDER); if (att_id < 0) { return (MI_ERROR); } typ_id = H5Aget_type(att_id); length = H5Tget_size(typ_id); if (length > NC_MAX_NAME) { return (MI_ERROR); } status = H5Aread(att_id, typ_id, buf); if (status < 0) { return (MI_ERROR); } H5Tclose(typ_id); H5Aclose(att_id); buf[length] = '\0'; /* Make certain string is terminated. */ str_ptr = &buf[0]; n = 0; done = 0; while (!done && n < ndims) { tmp_ptr = str_ptr; while (*tmp_ptr != ',' && *tmp_ptr != '\0') { tmp_ptr++; } if (*tmp_ptr == '\0') { /* Real end of string? */ done = 1; /* We're finished after this iteration. */ } else { *tmp_ptr++ = '\0'; /* Terminate the string. */ } dim = hdf_dim_byname(file, str_ptr); if (dim != NULL) { dims_ptr[n++] = dim->id; } str_ptr = tmp_ptr; } #ifndef NO_EMULATE_VECTOR_DIMENSION typ_id = H5Dget_type(dst_id); if (typ_id >= 0) { if (H5Tget_class(typ_id) == H5T_COMPOUND) { dim = hdf_dim_byname(file, MIvector_dimension); if (dim != NULL) { dims_ptr[n++] = dim->id; } } H5Tclose(typ_id); } #endif /* NO_EMULATE_VECTOR_DIMENSION */ return (MI_NOERROR); } int hdf_inquire(int fd, int *ndims_ptr, int *nvars_ptr, int *natts_ptr, int *unlimdim_ptr) { struct m2_file *file; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if (ndims_ptr != NULL) { *ndims_ptr = file->ndims; } if (unlimdim_ptr != NULL) { /* We don't support unlimited dimensions. */ *unlimdim_ptr = -1; } if (nvars_ptr != NULL) { *nvars_ptr = file->nvars; } if (natts_ptr != NULL) { *natts_ptr = H5Aget_num_attrs(file->grp_id); } return (MI_NOERROR); } int hdf_varinq(int fd, int varid, char *varnm_ptr, nc_type *type_ptr, int *ndims_ptr, int *dims_ptr, int *natts_ptr) { hid_t dst_id; hid_t typ_id; size_t size; H5T_class_t class; int ndims; struct m2_file *file; struct m2_var *var; /* Emulate rootvariable */ if (varid == MI_ROOTVARIABLE_ID) { if (varnm_ptr != NULL) { strcpy(varnm_ptr, MIrootvariable); } if (type_ptr != NULL) { *type_ptr = NC_INT; } if (ndims_ptr != NULL) { *ndims_ptr = 0; } if (natts_ptr != NULL) { *natts_ptr = 0; } return (MI_NOERROR); } if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } dst_id = var->dset_id; typ_id = var->ftyp_id; class = H5Tget_class(typ_id); size = H5Tget_size(typ_id); if (type_ptr != NULL) { #ifndef NO_EMULATE_VECTOR_DIMENSION if (class == H5T_COMPOUND) { hid_t subtype_id = H5Tget_member_type(typ_id, 0); class = H5Tget_class(subtype_id); size = H5Tget_size(subtype_id); H5Tclose(subtype_id); } #endif /* NO_EMULATE_VECTOR_DIMENSION */ if (class == H5T_INTEGER) { if (size == 1) *type_ptr = NC_BYTE; else if (size == 2) *type_ptr = NC_SHORT; else if (size == 4) *type_ptr = NC_INT; else { milog_message(MI_MSG_INTSIZE, size); exit(-1); } } else if (class == H5T_FLOAT) { if (size == 4) { *type_ptr = NC_FLOAT; } else if (size == 8) { *type_ptr = NC_DOUBLE; } else { milog_message(MI_MSG_FLTSIZE, size); exit(-1); } } else if (class == H5T_STRING) { *type_ptr = NC_CHAR; } else { milog_message(MI_MSG_TYPECLASS, class); exit(-1); } } if (class == H5T_STRING) { ndims = 0; } else { ndims = var->ndims; } if (dims_ptr != NULL && ndims != 0) { hdf_get_dimorder(file, dst_id, ndims, dims_ptr); } if (ndims_ptr != NULL) { *ndims_ptr = ndims; } if (natts_ptr != NULL) { int natts = H5Aget_num_attrs(dst_id); /* Emulate the signtype attribute for the image variable. */ if (!strcmp(var->name, MIimage) && H5Tget_class(var->ftyp_id) == H5T_INTEGER) { natts++; } *natts_ptr = natts; } if (varnm_ptr != NULL) { strcpy(varnm_ptr, var->name); } return (MI_NOERROR); } int hdf_dimrename(int fd, int dimid, const char *new_name) { milog_message(MI_MSG_NOTIMPL, "dimrename"); return (MI_NOERROR); } int hdf_dimid(int fd, const char *dimnm) { struct m2_file *file; struct m2_dim *dim; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if ((dim = hdf_dim_byname(file, dimnm)) == NULL) { return (MI_ERROR); } return (dim->id); } int hdf_diminq(int fd, int dimid, char *dimnm_ptr, long *len_ptr) { struct m2_file *file; struct m2_dim *dim; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if ((dim = hdf_dim_byid(file, dimid)) == NULL) { return (MI_ERROR); } /* Copy the dimension name, if appropriate. */ if (dimnm_ptr != NULL) { strcpy(dimnm_ptr, dim->name); } if (len_ptr != NULL) { *len_ptr = dim->length; } return (MI_NOERROR); } static void hdf_set_length(hid_t dst_id, const char *dimnm, unsigned long length) { hid_t att_id; hid_t aspc_id; aspc_id = H5Screate(H5S_SCALAR); if (aspc_id >= 0) { H5E_BEGIN_TRY { H5Adelete(dst_id, MI2_LENGTH); /* Create the attribute anew. */ att_id = H5Acreate(dst_id, MI2_LENGTH, H5T_STD_U32LE, aspc_id, H5P_DEFAULT, H5P_DEFAULT); } H5E_END_TRY; if (att_id >= 0) { H5Awrite(att_id, H5T_NATIVE_LONG, (void *) &length); H5Aclose(att_id); } H5Sclose(aspc_id); } } int hdf_dimdef(int fd, const char *dimnm, long length) { int status = MI_ERROR; struct m2_file *file; struct m2_dim *dim; if ((file = hdf_id_check(fd)) != NULL && (dim = hdf_dim_add(file, dimnm, length)) != NULL) { struct m2_var *var = hdf_var_byname(file, dimnm); if (var != NULL) { hdf_set_length(var->dset_id, dimnm, length); } status = dim->id; } return (status); } /** Like hdf_attinq, this function must return one for success, not * zero! */ int hdf_attget(int fd, int varid, const char *attnm, void *value) { hid_t att_id; hid_t ftyp_id; hid_t mtyp_id; hid_t loc_id; int status = MI_ERROR; struct m2_file *file; struct m2_var *var; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if (varid == NC_GLOBAL) { var = NULL; loc_id = file->grp_id; } else { if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } loc_id = var->dset_id; } /* Special case - emulate the signtype attribute. */ if (!strcmp(attnm, MIsigntype)) { if (H5Tget_class(var->ftyp_id) == H5T_INTEGER) { if (H5Tget_sign(var->ftyp_id) == H5T_SGN_NONE) { strcpy((char *) value, MI_UNSIGNED); } else { strcpy((char *) value, MI_SIGNED); } status = 1; /* 1 -> success */ } } else if (!strcmp(attnm, MI_FillValue)) { hid_t plist_id = H5Dget_create_plist(loc_id); if (plist_id >= 0) { if (H5Pget_fill_value(plist_id, var->mtyp_id, value) >= 0) { status = MI_NOERROR; } H5Pclose(plist_id); } } else { H5E_BEGIN_TRY { att_id = H5Aopen_name(loc_id, attnm); } H5E_END_TRY; if (att_id >= 0) { if ((ftyp_id = H5Aget_type(att_id)) >= 0) { mtyp_id = H5Tget_native_type(ftyp_id, H5T_DIR_ASCEND); if (mtyp_id >= 0) { if (H5Aread(att_id, mtyp_id, value) >= 0) { status = 1; /* 1 -> success */ } H5Tclose(mtyp_id); } H5Tclose(ftyp_id); } H5Aclose(att_id); } } return (status); } int hdf_attput(int fd, int varid, const char *attnm, nc_type val_typ, int val_len, void *val_ptr) { hid_t att_id = -1; hid_t mtyp_id = -1; /* Memory type */ hid_t ftyp_id = -1; /* File type */ hid_t spc_id = -1; hid_t loc_id; int status = MI_ERROR; struct m2_file *file; struct m2_var *var; /* Ignore deprecated variables. */ if (varid == MI_ROOTVARIABLE_ID) { return (MI_NOERROR); /* Pretend all is OK. */ } /* Ignore deprecated attributes. */ if (!strcmp(attnm, MIparent) || !strcmp(attnm, MIchildren) || !strcmp(attnm, MIimagemin) || !strcmp(attnm, MIimagemax) || !strcmp(attnm, MI_FillValue)) { return (MI_NOERROR); /* Pretend we created it. */ } if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if (varid == NC_GLOBAL) { var = NULL; loc_id = file->grp_id; } else { if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } loc_id = var->dset_id; } if (!strcmp(attnm, MIsigntype)) { /* Emulate 'signtype' */ int new_signed; /* Need to recreate dataset with new type. Sigh. */ if (!strncmp(val_ptr, MI_SIGNED, 8)) { new_signed = 1; } else if (!strncmp(val_ptr, MI_UNSIGNED, 8)) { new_signed = 0; } else { return (MI_ERROR); } if ((H5Tget_sign(var->ftyp_id) == H5T_SGN_NONE && new_signed) || (H5Tget_sign(var->ftyp_id) == H5T_SGN_2 && !new_signed)) { hid_t new_type_id; hid_t new_dset_id; hid_t new_plst_id; char temp[128]; unsigned int i; sprintf(temp, "junkXXXX"); new_type_id = H5Tcopy(var->ftyp_id); if (new_type_id < 0) { milog_message(MI_MSG_SNH); } if (H5Tset_sign(new_type_id, (new_signed) ? H5T_SGN_2 : H5T_SGN_NONE) < 0) { milog_message(MI_MSG_SNH); } new_plst_id = H5Dget_create_plist(var->dset_id); new_dset_id = H5Dcreate1(file->grp_id, temp, new_type_id, var->fspc_id, new_plst_id); /* Iterate over all attributes, copying from old to new. */ i = 0; H5Aiterate1(var->dset_id, &i, hdf_copy_attr, (void *) new_dset_id); H5Dclose(var->dset_id); H5Tclose(var->ftyp_id); H5Tclose(var->mtyp_id); H5Tclose(new_type_id); H5Pclose(new_plst_id); H5Sclose(var->fspc_id); if (H5Gunlink(fd, var->path) < 0) { milog_message(MI_MSG_SNH); } if (H5Gmove2(file->grp_id, temp, fd, var->path) < 0) { milog_message(MI_MSG_SNH); } var->dset_id = new_dset_id; var->ftyp_id = H5Dget_type(var->dset_id); var->mtyp_id = H5Tget_native_type(var->ftyp_id, H5T_DIR_ASCEND); var->fspc_id = H5Dget_space(var->dset_id); } return (MI_NOERROR); } if (val_typ == NC_CHAR) { ftyp_id = H5Tcopy(H5T_C_S1); H5Tset_size(ftyp_id, val_len); mtyp_id = H5Tcopy(ftyp_id); spc_id = H5Screate(H5S_SCALAR); } else { switch (val_typ) { case NC_BYTE: mtyp_id = H5T_NATIVE_UCHAR; ftyp_id = H5T_STD_U8LE; break; case NC_SHORT: mtyp_id = H5T_NATIVE_USHORT; ftyp_id = H5T_STD_U16LE; break; case NC_INT: mtyp_id = H5T_NATIVE_UINT; ftyp_id = H5T_STD_U32LE; break; case NC_FLOAT: mtyp_id = H5T_NATIVE_FLOAT; ftyp_id = H5T_IEEE_F32LE; break; case NC_DOUBLE: mtyp_id = H5T_NATIVE_DOUBLE; ftyp_id = H5T_IEEE_F64LE; break; default: milog_message(MI_MSG_BADTYPE, val_typ); return (MI_ERROR); } mtyp_id = H5Tcopy(mtyp_id); ftyp_id = H5Tcopy(ftyp_id); if (val_len == 1) { spc_id = H5Screate(H5S_SCALAR); } else { hsize_t temp_size = val_len; spc_id = H5Screate_simple(1, &temp_size, NULL); } } /* If the attribute already exists, delete it. It is not possible * to change the size of an existing attribute. */ H5E_BEGIN_TRY { H5Adelete(loc_id, attnm); /* Create the attribute anew. */ att_id = H5Acreate(loc_id, attnm, ftyp_id, spc_id, H5P_DEFAULT, H5P_DEFAULT); } H5E_END_TRY; if (att_id < 0) goto cleanup; /* Save the value. */ status = H5Awrite(att_id, mtyp_id, val_ptr); if (status >= 0) { status = MI_NOERROR; } cleanup: if (spc_id >= 0) H5Sclose(spc_id); if (ftyp_id >= 0) H5Tclose(ftyp_id); if (mtyp_id >= 0) H5Tclose(mtyp_id); if (att_id >= 0) H5Aclose(att_id); return (status); } /** This function simply sweeps through all of the dimensions defined * in a file, and if a dimension variable has not yet been saved to the * file, it creates one here. */ static void hdf_dim_commit(int fd) { struct m2_file *file; struct m2_dim *dim; int i; if ((file = hdf_id_check(fd)) != NULL && file->wr_ok) { for (i = 0; i < file->ndims; i++) { if ((dim = hdf_dim_byid(file, i)) != NULL && !dim->is_fake) { if (hdf_var_byname(file, dim->name) == NULL) { hdf_vardef(fd, dim->name, NC_INT, 0, NULL); } } } } } /** This function is called when the "definition" phase of NetCDF file * creation is completed. The HDF5 library really doesn't need this, * since the mode doesn't exist in HDF5. But this is a convenient * time to make certain all of the dimension variables have actually * been defined. */ void hdf_enddef(int fd) { hdf_dim_commit(fd); /* Make sure all dimensions were saved. */ } /** This function provides the HDF5 emulation of the function ncvardef */ int hdf_vardef(int fd, const char *varnm, nc_type vartype, int ndims, const int *dimids) { int dst_id = -1; int typ_id = -1; int spc_id = -1; int prp_id = -1; int status = MI_ERROR; int i; long length; hsize_t dims[MAX_NC_DIMS]; hsize_t chkdims[MAX_NC_DIMS]; char varpath[NC_MAX_NAME]; struct m2_file *file; struct m2_var *var; struct m2_dim *dim; int chunk_length; int comp_level; /* Ignore deprecated variables */ if (!strcmp(varnm, MIrootvariable)) { return (MI_ROOTVARIABLE_ID); } if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if (hdf_path_from_name(file, varnm, varpath) < 0) { return (MI_ERROR); } prp_id = H5Pcreate(H5P_DATASET_CREATE); if (prp_id < 0) { goto cleanup; } if (ndims == 0) { spc_id = H5Screate(H5S_SCALAR); /* For any scalar datasets, use compact dataset layout to * minimize file overhead. */ H5Pset_layout(prp_id, H5D_COMPACT); } else { for (i = 0; i < ndims; i++) { status = hdf_diminq(fd, dimids[i], NULL, &length); if (status < 0) { return (status); } dims[i] = length; } spc_id = H5Screate_simple(ndims, dims, NULL); if (file->comp_type == MI2_COMP_UNKNOWN) { comp_level = miget_cfg_int(MICFG_COMPRESS); } else { if (file->comp_type == MI2_COMP_ZLIB) { comp_level = file->comp_param; } else { comp_level = 0; } } if (comp_level != 0) { /* If compression is specified, chunking must be enabled. */ if (file->chunk_type == MI2_CHUNK_UNKNOWN) { /* read from minc config file or environment variable */ chunk_length = miget_cfg_int(MICFG_CHUNKING); } else if( file->chunk_type == MI2_CHUNK_OFF ) { chunk_length = 0; } else { chunk_length = file->chunk_param; if( chunk_length < MI2_CHUNK_MIN_SIZE ) { chunk_length = MI2_CHUNK_MIN_SIZE; fprintf(stdout, "Warning: using chunk size of %d\n", MI2_CHUNK_MIN_SIZE ); } } /* If nothing good was found for the chunking, use chunking that matches the hyperslab that fits into the work buffer. This seems to be the optimal chunking performance-wise. */ if (chunk_length <= 0 ) { chunk_length = 0; } /* This mimics the way the buffer is filled in MI_var_loop so that a good (optimal) chunking can be set from the dimensions filling up the buffer. This seems pretty optimal in terms of speed and gives a very good compression ratio, often better than gzip. */ hsize_t val = 1; int unit_size = nctypelen( vartype ); for( i = ndims-1; i >= 0; i-- ) { if( MI_MAX_VAR_BUFFER_SIZE > dims[i] * val * unit_size ) { chkdims[i] = dims[i]; } else { chkdims[i] = MIN( dims[i], (hsize_t)( MI_MAX_VAR_BUFFER_SIZE / ( val * unit_size ) ) ); } val *= chkdims[i]; } for (i = 0; i < ndims; i++) { if( chunk_length >= MI2_CHUNK_MIN_SIZE ) { if( chkdims[i] > chunk_length ) { chkdims[i] = chunk_length; } } } H5Pset_deflate(prp_id, comp_level); H5Pset_chunk(prp_id, ndims, chkdims); } } if (spc_id < 0) { goto cleanup; } typ_id = H5Tcopy(nc_to_hdf5_type(vartype, TRUE)); if (typ_id < 0) { goto cleanup; } H5E_BEGIN_TRY { dst_id = H5Dcreate1(fd, varpath, typ_id, spc_id, prp_id); } H5E_END_TRY; if (dst_id < 0) { milog_message(MI_MSG_OPENDSET, varnm); goto cleanup; } /* If this is a dimension variable, we have to define the length * attribute now. */ if ((dim = hdf_dim_byname(file, varnm)) != NULL) { hdf_set_length(dst_id, varnm, dim->length); } /* Add the dimension order information. */ hdf_put_dimorder(file, dst_id, ndims, dimids); /* bert - Closing the dataset here is necessary for HDF5 1.6.5. * Without this we get nasty errors caused by re-opening the * dataset in hdf_var_add(). The conclusion seems to be that * HDF5 1.6.5 does not allow re-opening a newly created dataset. */ H5Dclose(dst_id); dst_id = -1; /* Add the variable to the internal table. */ var = hdf_var_add(file, varnm, varpath, ndims, dims); if (var == NULL) { goto cleanup; } status = var->id; cleanup: if (prp_id >= 0) { H5Pclose(prp_id); } if (dst_id >= 0) { H5Dclose(dst_id); } if (typ_id >= 0) { H5Tclose(typ_id); } if (spc_id >= 0) { H5Sclose(spc_id); } return (status); } /** */ int hdf_var_declare(int fd, char *varnm, char *varpath, int ndims, hsize_t *sizes) { struct m2_file *file; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } hdf_var_add(file, varnm, varpath, ndims, sizes); return (MI_NOERROR); } int hdf_varget(int fd, int varid, const long *start_ptr, const long *length_ptr, void *val_ptr) { int status = MI_ERROR; int dst_id = -1; int typ_id = -1; int fspc_id = -1; int mspc_id = -1; int i; int ndims; hsize_t fstart[MAX_VAR_DIMS]; hsize_t count[MAX_VAR_DIMS]; struct m2_file *file; struct m2_var *var; // fprintf(stderr, "HDF varget\n"); /* Emulate the obsolete "rootvariable" */ if (varid == MI_ROOTVARIABLE_ID) { *((int *)val_ptr) = 0; return (MI_NOERROR); } if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } dst_id = var->dset_id; typ_id = var->mtyp_id; fspc_id = var->fspc_id; ndims = var->ndims; #ifndef NO_EMULATE_VECTOR_DIMENSION /* If it is a compound variable, we cannot actually pick and choose the * length of the hyperslab along the emulated vector_dimension, so we * just reduce the dimensionality by 1 */ if (var->is_cmpd) { struct m2_dim *dim = hdf_dim_byname(file, MIvector_dimension); if (dim != NULL && length_ptr[ndims - 1] != dim->length) { fprintf(stderr, "ERROR: can't read subset of emulated vector dimension\n"); return (MI_ERROR); } ndims--; } #endif /* NO_EMULATE_VECTOR_DIMENSION */ if (ndims == 0) { mspc_id = H5Screate(H5S_SCALAR); } else { for (i = 0; i < ndims; i++) { fstart[i] = start_ptr[i]; count[i] = length_ptr[i]; } status = H5Sselect_hyperslab(fspc_id, H5S_SELECT_SET, fstart, NULL, count, NULL); if (status < 0) { milog_message(MI_MSG_SNH); goto cleanup; } mspc_id = H5Screate_simple(ndims, count, 0); if (mspc_id < 0) { milog_message(MI_MSG_SNH); goto cleanup; } } status = H5Dread(dst_id, typ_id, mspc_id, fspc_id, H5P_DEFAULT, val_ptr); if (status < 0) { milog_message(MI_MSG_READDSET, var->path); } cleanup: // fprintf(stderr, "cleanup - dst_id: %d fspc_id: %d mspc_id: %d\n", dst_id, fspc_id, mspc_id); // I think this should be needed but am not sure with HDF 1.8.x // Andrew Janke - 3/3/2010 // if(fspc_id >= 0) // H5Sclose(fspc_id); if (mspc_id >= 0) H5Sclose(mspc_id); // fprintf(stderr, "cleanup - done\n"); return (status); } int hdf_varputg(int fd, int varid, const long *start, const long *edges, const long *stride, const long *map, const void *value) { int status = MI_ERROR; /* Assume guilty */ int maxidim; /* maximum dimensional index */ int idim; hsize_t *mystart = NULL; hsize_t *myedges; hsize_t *iocount; /* count vector */ hsize_t *stop; /* stop indexes */ hsize_t *length; /* edge lengths in bytes */ ptrdiff_t *mystride; ptrdiff_t *mymap; struct m2_var *varp; struct m2_file *file; int dst_id = -1; int typ_id = -1; int fspc_id = -1; int mspc_id = -1; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if ((varp = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } dst_id = varp->dset_id; typ_id = varp->mtyp_id; fspc_id = varp->fspc_id; mspc_id = H5Scopy(fspc_id); maxidim = (int) varp->ndims - 1; if (maxidim < 0) { /* * The variable is a scalar! */ milog_message(MI_MSG_SNH); goto cleanup; } /* * Verify stride argument. */ if (stride != NULL) { for (idim = 0; idim <= maxidim; idim++) { /* cast needed for braindead systems with signed size_t */ if (stride[idim] == 0) { goto cleanup; } } } mystart = (hsize_t *)calloc(varp->ndims * 7, sizeof(hsize_t)); if (mystart == NULL) { goto cleanup; } myedges = (mystart + varp->ndims); iocount = myedges + varp->ndims; stop = iocount + varp->ndims; length = stop + varp->ndims; mystride = (ptrdiff_t *)(length + varp->ndims); mymap = mystride + varp->ndims; /* * Initialize I/O parameters. */ for (idim = maxidim; idim >= 0; --idim) { mystart[idim] = start != NULL ? start[idim] : 0; /* Hmm - should this even _BE_ here? */ if (edges[idim] == 0) { status = MI_NOERROR; /* nothing to do here */ goto cleanup; } if (edges != NULL) { myedges[idim] = edges[idim]; } else { myedges[idim] = varp->dims[idim] - mystart[idim]; } if (stride != NULL) { mystride[idim] = stride[idim]; } else { mystride[idim] = 1; } if (map != NULL) { mymap[idim] = map[idim]; } else if (idim == maxidim) { mymap[idim] = 1; } else { mymap[idim] = mymap[idim+1] * (ptrdiff_t) myedges[idim+1]; } iocount[idim] = 1; length[idim] = mymap[idim] * myedges[idim]; stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; } /* * Check start, edges */ for (idim = 0; idim < maxidim; idim++) { if (mystart[idim] >= varp->dims[idim]) { status = MI_ERROR; goto cleanup; } if (mystart[idim] + myedges[idim] > varp->dims[idim]) { status = MI_ERROR; goto cleanup; } } /* * As an optimization, adjust I/O parameters when the fastest * dimension has unity stride both externally and internally. * In this case, the user could have called a simpler routine * (i.e. ncvarnc_put_vara_uchar() */ if (mystride[maxidim] == 1 && mymap[maxidim] == 1) { iocount[maxidim] = myedges[maxidim]; mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; mymap[maxidim] = (ptrdiff_t) length[maxidim]; } mspc_id = H5Screate_simple(varp->ndims, iocount, NULL); /* * Perform I/O. Exit when done. */ for (;;) { status = H5Sselect_hyperslab(fspc_id, H5S_SELECT_SET, mystart, NULL, iocount, NULL); if (status < 0) { milog_message(MI_MSG_SNH); goto cleanup; } status = H5Dwrite(dst_id, typ_id, mspc_id, fspc_id, H5P_DEFAULT, value); if (status < 0) { milog_message(MI_MSG_WRITEDSET, varp->path); goto cleanup; } /* * The following code permutes through the variable's * external start-index space and it's internal address * space. At the UPC, this algorithm is commonly * called "odometer code". */ idim = maxidim; carry: value = ((char *)value) + mymap[idim]; mystart[idim] += mystride[idim]; if (mystart[idim] == stop[idim]) { mystart[idim] = start[idim]; value = ((char *)value) - length[idim]; if (--idim < 0) break; /* normal return */ goto carry; } } /* I/O loop */ cleanup: if (mystart != NULL) { free(mystart); } if (mspc_id >= 0) { H5Sclose(mspc_id); } return (status); } int hdf_vargetg(int fd, int varid, const long *start, const long *edges, const long *stride, const long *map, void *value) { int status = MI_NOERROR; struct m2_var *varp; int maxidim; /* maximum dimensional index */ struct m2_file *file; int idim; long *mystart = NULL; long *myedges; long *iocount; /* count vector */ long *stop; /* stop indexes */ long *length; /* edge lengths in bytes */ long *mystride; long *mymap; file = hdf_id_check(fd); if (file == NULL) { return (MI_ERROR); } varp = hdf_var_byid(file, varid); if (varp == NULL) { return (MI_ERROR); } maxidim = (int) varp->ndims - 1; if (maxidim < 0) { /* * The variable is a scalar! */ milog_message(MI_MSG_SNH); return (MI_ERROR); } /* * Verify stride argument. */ if (stride != NULL) { for (idim = 0; idim <= maxidim; idim++) { if (stride[idim] == 0) { return MI_ERROR; } } } mystart = (long *)calloc(varp->ndims * 7, sizeof(long)); if (mystart == NULL) { return (MI_ERROR); } myedges = mystart + varp->ndims; iocount = myedges + varp->ndims; stop = iocount + varp->ndims; length = stop + varp->ndims; mystride = length + varp->ndims; mymap = mystride + varp->ndims; /* * Initialize I/O parameters. */ for (idim = maxidim; idim >= 0; --idim) { mystart[idim] = start != NULL ? start[idim] : 0; /* Hmm - should this even _BE_ here? */ if (edges[idim] == 0) { status = MI_NOERROR; /* nothing to do here */ goto done; } if (edges != NULL) { myedges[idim] = edges[idim]; } else { myedges[idim] = varp->dims[idim] - mystart[idim]; } if (stride != NULL) { mystride[idim] = stride[idim]; } else { mystride[idim] = 1; } if (map != NULL) { mymap[idim] = map[idim]; } else if (idim == maxidim) { mymap[idim] = 1; } else { mymap[idim] = mymap[idim+1] * (ptrdiff_t) myedges[idim+1]; } iocount[idim] = 1; length[idim] = mymap[idim] * myedges[idim]; stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; } /* * Check start, edges */ for (idim = 0; idim < maxidim; idim++) { if (mystart[idim] >= varp->dims[idim]) { status = MI_ERROR; goto done; } if (mystart[idim] + myedges[idim] > varp->dims[idim]) { status = MI_ERROR; goto done; } } /* * As an optimization, adjust I/O parameters when the fastest * dimension has unity stride both externally and internally. * In this case, the user could have called a simpler routine * (i.e. ncvarnc_put_vara_uchar() */ if (mystride[maxidim] == 1 && mymap[maxidim] == 1) { iocount[maxidim] = myedges[maxidim]; mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; mymap[maxidim] = (ptrdiff_t) length[maxidim]; } /* * Perform I/O. Exit when done. */ for (;;) { int lstatus = hdf_varget(fd, varid, mystart, iocount, value); if (lstatus != MI_NOERROR && status == MI_NOERROR) { status = lstatus; } /* * The following code permutes through the variable's * external start-index space and it's internal address * space. At the UPC, this algorithm is commonly * called "odometer code". */ idim = maxidim; carry: value = ((char *)value) + mymap[idim]; mystart[idim] += mystride[idim]; if (mystart[idim] == stop[idim]) { mystart[idim] = start[idim]; value = ((char *)value) - length[idim]; if (--idim < 0) break; /* normal return */ goto carry; } } /* I/O loop */ done: free(mystart); return (status); } int hdf_varput(int fd, int varid, const long *start_ptr, const long *length_ptr, const void *val_ptr) { int status = MI_ERROR; int dst_id; int typ_id; int fspc_id; int mspc_id = -1; int i; int ndims; hsize_t fstart[MAX_VAR_DIMS]; hsize_t count[MAX_VAR_DIMS]; struct m2_file *file; struct m2_var *var; if (varid == MI_ROOTVARIABLE_ID) { return (MI_NOERROR); } if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } dst_id = var->dset_id; typ_id = var->mtyp_id; fspc_id = var->fspc_id; ndims = var->ndims; if (ndims == 0) { mspc_id = H5Screate(H5S_SCALAR); } else { for (i = 0; i < ndims; i++) { fstart[i] = start_ptr[i]; count[i] = length_ptr[i]; } status = H5Sselect_hyperslab(fspc_id, H5S_SELECT_SET, fstart, NULL, count, NULL); if (status < 0) { milog_message(MI_MSG_SNH); goto cleanup; } mspc_id = H5Screate_simple(ndims, count, NULL); if (mspc_id < 0) { milog_message(MI_MSG_SNH); goto cleanup; } } status = H5Dwrite(dst_id, typ_id, mspc_id, fspc_id, H5P_DEFAULT, val_ptr); if (status < 0) { milog_message(MI_MSG_WRITEDSET, var->path); goto cleanup; } cleanup: if (mspc_id >= 0) H5Sclose(mspc_id); return (status); } int hdf_varput1(int fd, int varid, const long *mindex_ptr, const void *val_ptr) { long length[MAX_VAR_DIMS]; int i; /* Rather than querying the number of dimensions, just fill the whole * darn thing with 1's. */ for (i = 0; i < MAX_VAR_DIMS; i++) { length[i] = 1; } return hdf_varput(fd, varid, mindex_ptr, length, val_ptr); } /** Emulates ncattdel(). Like many of the netCDF attribute functions, * success here is indicated by a return value of one. */ int hdf_attdel(int fd, int varid, const char *attnm) { hid_t loc_id; struct m2_file *file; struct m2_var *var; if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if (varid == NC_GLOBAL) { var = NULL; loc_id = file->grp_id; } else { if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } loc_id = var->dset_id; } H5E_BEGIN_TRY { H5Adelete(loc_id, attnm); } H5E_END_TRY; return 1; /* success */ } /* Get the current size of a variable. This is needed in HDF5 since * dimensions are associated with individual variable's dataspaces, * and can be independent, rather than set by a file-wide "dimension" * object. */ int hdf_varsize(int fd, int varid, long *size_ptr) { int i; hsize_t dims[MAX_VAR_DIMS]; struct m2_file *file; struct m2_var *var; if (varid == MI_ROOTVARIABLE_ID) { *size_ptr = 1; return (MI_NOERROR); } if ((file = hdf_id_check(fd)) == NULL) { return (MI_ERROR); } if ((var = hdf_var_byid(file, varid)) == NULL) { return (MI_ERROR); } if (var->ndims > MAX_VAR_DIMS) { milog_message(MI_MSG_TOOMANYDIMS, MAX_VAR_DIMS); exit(-1); } H5Sget_simple_extent_dims(var->fspc_id, dims, NULL); for (i = 0; i < var->ndims; i++) { size_ptr[i] = dims[i]; } return (MI_NOERROR); } herr_t hdf_copy_attr(hid_t in_id, const char *attr_name, void *op_data) { hid_t out_id = (hid_t) op_data; hid_t inatt_id = -1; hid_t outatt_id = -1; hid_t spc_id = -1; hid_t typ_id = -1; void *val_ptr = NULL; int status = MI_ERROR; if ((inatt_id = H5Aopen_name(in_id, attr_name)) < 0) goto cleanup; if ((spc_id = H5Aget_space(inatt_id)) < 0) goto cleanup; if ((typ_id = H5Aget_type(inatt_id)) < 0) goto cleanup; outatt_id = H5Acreate(out_id, attr_name, typ_id, spc_id, H5P_DEFAULT, H5P_DEFAULT); if (outatt_id < 0) { /* This can happen if the attribute already exists. If it does, we * don't overwrite the existing value. */ status = MI_NOERROR; goto cleanup; } if ((val_ptr = malloc(hdf_size(spc_id, typ_id))) == NULL) goto cleanup; if (H5Aread(inatt_id, typ_id, val_ptr) < 0) goto cleanup; if (H5Awrite(outatt_id, typ_id, val_ptr) < 0) goto cleanup; status = MI_NOERROR; cleanup: if (val_ptr != NULL) free(val_ptr); if (spc_id >= 0) H5Sclose(spc_id); if (typ_id >= 0) H5Tclose(typ_id); if (inatt_id >= 0) H5Aclose(inatt_id); if (outatt_id >= 0) H5Aclose(outatt_id); return (status); } int hdf_open_dsets(struct m2_file *file, hid_t grp_id, char *cpath, int is_dim) { hsize_t nobjs; hsize_t idx; char temp[NC_MAX_NAME]; char tpath[NC_MAX_NAME]; hid_t new_id; herr_t result; result = H5Gget_num_objs(grp_id, &nobjs); if (result < 0) { return (MI_ERROR); } for (idx = 0; idx < nobjs; idx++) { switch (H5Gget_objtype_by_idx(grp_id, idx)) { case H5G_GROUP: H5Gget_objname_by_idx(grp_id, idx, temp, sizeof(temp)); strcpy(tpath, cpath); strcat(tpath, temp); strcat(tpath, "/"); new_id = H5Gopen1(grp_id, temp); if (new_id >= 0) { hdf_open_dsets(file, new_id, tpath, is_dim); H5Gclose(new_id); } break; case H5G_DATASET: H5Gget_objname_by_idx(grp_id, idx, temp, sizeof(temp)); strcpy(tpath, cpath); strcat(tpath, temp); new_id = H5Dopen1(grp_id, temp); if (new_id >= 0) { hid_t spc_id; spc_id = H5Dget_space(new_id); if (spc_id < 0) { milog_message(MI_MSG_SNH); } else { hsize_t dims[MAX_NC_DIMS]; int ndims; hdf_get_diminfo(new_id, &ndims, dims); hdf_var_add(file, temp, tpath, ndims, dims); } if (is_dim) { long length; hid_t att_id; att_id = H5Aopen_name(new_id, MI2_LENGTH); if (att_id > 0) { H5Aread(att_id, H5T_NATIVE_LONG, (void *) &length); H5Aclose(att_id); } else { milog_message(MI_MSG_SNH); } hdf_dim_add(file, temp, length); } H5Dclose(new_id); } break; default: break; } } return (MI_NOERROR); } int hdf_open(const char *path, int mode) { hid_t fd; hid_t grp_id; hid_t dset_id; struct m2_file *file; hsize_t dims[MAX_NC_DIMS]; int ndims; struct m2_var *var; H5E_BEGIN_TRY { #if HDF5_MMAP_TEST if (mode & 0x8000) { hid_t prp_id; prp_id = H5Pcreate(H5P_FILE_ACCESS); H5Pset_fapl_mmap(prp_id, 8192, 1); fd = H5Fopen(path, mode & 0x7FFF, prp_id); H5Pclose(prp_id); } else { fd = H5Fopen(path, mode, H5P_DEFAULT); } #else fd = H5Fopen(path, mode, H5P_DEFAULT); #endif } H5E_END_TRY; if (fd < 0) { return (MI_ERROR); } file = hdf_id_add(fd); /* Add it to the list */ file->wr_ok = (mode & H5F_ACC_RDWR) != 0; /* Open the image variables. */ H5E_BEGIN_TRY { dset_id = H5Dopen1(fd, "/minc-2.0/image/0/image"); if (dset_id >= 0) { hid_t type_id; int is_compound = 0; hdf_get_diminfo(dset_id, &ndims, dims); #ifndef NO_EMULATE_VECTOR_DIMENSION /* See if a vector_dimension needs to be emulated. */ type_id = H5Dget_type(dset_id); if (type_id >= 0) { if (H5Tget_class(type_id) == H5T_COMPOUND) { /* OK, it's compound type. */ struct m2_dim *dim = hdf_dim_add(file, MIvector_dimension, H5Tget_nmembers(type_id)); dim->is_fake = 1; dims[ndims++] = H5Tget_nmembers(type_id); is_compound = 1; } H5Tclose(type_id); } #endif /* NO_EMULATE_VECTOR_DIMENSION */ var = hdf_var_add(file, MIimage, "/minc-2.0/image/0/image", ndims, dims); var->is_cmpd = is_compound; H5Dclose(dset_id); } dset_id = H5Dopen1(fd, "/minc-2.0/image/0/image-min"); if (dset_id >= 0) { hdf_get_diminfo(dset_id, &ndims, dims); hdf_var_add(file, MIimagemin, "/minc-2.0/image/0/image-min", ndims, dims); H5Dclose(dset_id); } dset_id = H5Dopen1(fd, "/minc-2.0/image/0/image-max"); if (dset_id >= 0) { hdf_get_diminfo(dset_id, &ndims, dims); hdf_var_add(file, MIimagemax, "/minc-2.0/image/0/image-max", ndims, dims); H5Dclose(dset_id); } } H5E_END_TRY; /* Open all of the datasets in the "dimensions" category. */ grp_id = H5Gopen2(fd, "/minc-2.0/dimensions", H5P_DEFAULT); hdf_open_dsets(file, grp_id, "/minc-2.0/dimensions/", 1); H5Gclose(grp_id); /* Open all of the datasets in the "info" category. */ grp_id = H5Gopen2(fd, "/minc-2.0/info", H5P_DEFAULT); hdf_open_dsets(file, grp_id, "/minc-2.0/info/", 0); H5Gclose(grp_id); return (fd); } /** Create an HDF5 file. */ int hdf_create(const char *path, int cmode, struct mi2opts *opts_ptr) { hid_t grp_id; hid_t fd; hid_t tmp_id; struct m2_file *file; /* Convert the MINC (NetCDF) mode to a HDF5 mode. */ if (cmode & NC_NOCLOBBER) { cmode = H5F_ACC_EXCL; } else { cmode = H5F_ACC_TRUNC; } H5E_BEGIN_TRY { fd = H5Fcreate(path, cmode, H5P_DEFAULT, H5P_DEFAULT); } H5E_END_TRY; if (fd < 0) { return (MI_ERROR); } /* Create the default groups. * Should we use a non-zero value for size_hint (parameter 3)??? */ if ((grp_id = H5Gcreate1(fd, MI2_GRPNAME, 0)) < 0) { return (MI_ERROR); } if ((tmp_id = H5Gcreate1(grp_id, "dimensions", 0)) < 0) { return (MI_ERROR); } H5Gclose(tmp_id); if ((tmp_id = H5Gcreate1(grp_id, "info", 0)) < 0) { return (MI_ERROR); } H5Gclose(tmp_id); if ((tmp_id = H5Gcreate1(grp_id, "image", 0)) < 0) { return (MI_ERROR); } H5Gclose(tmp_id); if ((tmp_id = H5Gcreate1(grp_id, "image/0", 0)) < 0) { return (MI_ERROR); } H5Gclose(tmp_id); H5Gclose(grp_id); file = hdf_id_add(fd); /* Add it to the list */ if (file == NULL) { return (MI_ERROR); /* Should not happen?? */ } file->wr_ok = 1; if (opts_ptr != NULL && opts_ptr->struct_version == MI2_OPTS_V1) { file->comp_type = opts_ptr->comp_type; file->comp_param = opts_ptr->comp_param; file->chunk_type = opts_ptr->chunk_type; file->chunk_param = opts_ptr->chunk_param; } return ((int) fd); } int hdf_close(int fd) { hdf_dim_commit(fd); /* Make sure all dimensions were saved. */ hdf_id_del(fd); /* Delete it from the list. */ H5Fclose(fd); return (MI_NOERROR); } /* * Returns one (1) if the argument is the path name of an existing HDF5 * file, or zero if the file does not exist or is not in the right format. */ int hdf_access(const char *path) { htri_t status; H5E_BEGIN_TRY { status = H5Fis_hdf5(path); } H5E_END_TRY; return (status > 0); /* Return non-zero if success */ } #ifdef HDF_TEST main(int argc, char **argv) { int dims[5] = {0,0,0,0,0}; int i; int n; while (--argc > 0) { n = hdf_parse_dimorder(*++argv, 5, dims); for (i = 0; i < n; i++) { printf("%d ", dims[i]); } printf("\n"); } } #endif /* HDF_TEST defined */ #endif /* MINC2 defined */ minc-2.2.00/libsrc/minc_compat.c0000644000265600003100000002102112027132662013347 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #if MINC2 /* Ignore if not MINC2 */ /* minc_compat.c * * this code exists to provide a dispatch layer between the MI2* low-level * calls and their respective HDF5 and NetCDF implementations. * * Since each of these calls uses exactly one file descriptor, the logic is * simple: we just apply the correct operation based on a quick determination * of whether this is an HDF5 handle or a NetCDF file descriptor. */ #define _MI2_FORCE_NETCDF_ #include "minc_private.h" #include "hdf_convenience.h" /* */ MNCAPI int MI2varname(int fd, int varid, char *varnm) { if (MI2_ISH5OBJ(fd)) { return (hdf_varname(fd, varid, varnm)); } else { return (nc_inq_varname(fd, varid, varnm)); } } /* */ MNCAPI int MI2varid(int fd, const char *varnm) { if (MI2_ISH5OBJ(fd)) { return (hdf_varid(fd, varnm)); } else { return (ncvarid(fd, varnm)); } } /* */ MNCAPI int MI2attinq(int fd, int varid, const char *attnm, nc_type *type_ptr, int *length_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_attinq(fd, varid, attnm, type_ptr, length_ptr)); } else { int status; int oldncopts = ncopts; ncopts = 0; status = ncattinq(fd, varid, attnm, type_ptr, length_ptr); ncopts = oldncopts; if (status != 1 && oldncopts != 0) { fprintf(stderr, _("ncattinq: ncid %d: varid: %d: Attribute '%s' not found"), fd, varid, attnm); } return (status); } } MNCAPI int MI2attname(int fd, int varid, int attid, char *name) { if (MI2_ISH5OBJ(fd)) { return (hdf_attname(fd, varid, attid, name)); } else { return (ncattname(fd, varid, attid, name)); } } /* */ MNCAPI int MI2inquire(int fd, int *ndims_ptr, int *nvars_ptr, int *natts_ptr, int *unlimdim_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_inquire(fd, ndims_ptr, nvars_ptr, natts_ptr, unlimdim_ptr)); } else { return (ncinquire(fd, ndims_ptr, nvars_ptr, natts_ptr, unlimdim_ptr)); } } /* */ MNCAPI int MI2varinq(int fd, int varid, char *varnm_ptr, nc_type *type_ptr, int *ndims_ptr, int *dims_ptr, int *natts_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_varinq(fd, varid, varnm_ptr, type_ptr, ndims_ptr, dims_ptr, natts_ptr)); } else { return (ncvarinq(fd, varid, varnm_ptr, type_ptr, ndims_ptr, dims_ptr, natts_ptr)); } } /* */ MNCAPI int MI2dimid(int fd, const char *dimnm) { if (MI2_ISH5OBJ(fd)) { return (hdf_dimid(fd, dimnm)); } else { return (ncdimid(fd, dimnm)); } } /* */ MNCAPI int MI2diminq(int fd, int dimid, char *dimnm_ptr, long *len_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_diminq(fd, dimid, dimnm_ptr, len_ptr)); } else { return (ncdiminq(fd, dimid, dimnm_ptr, len_ptr)); } } /* */ MNCAPI int MI2dimdef(int fd, const char *dimnm, long length) { if (MI2_ISH5OBJ(fd)) { return (hdf_dimdef(fd, dimnm, length)); } else { return (ncdimdef(fd, dimnm, length)); } } /* */ MNCAPI int MI2attget(int fd, int varid, const char *attnm, void *value) { if (MI2_ISH5OBJ(fd)) { return (hdf_attget(fd, varid, attnm, value)); } else { return (ncattget(fd, varid, attnm, value)); } } /* */ MNCAPI int MI2attput(int fd, int varid, const char *attnm, nc_type val_typ, int val_len, void *val_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_attput(fd, varid, attnm, val_typ, val_len, val_ptr)); } else { int old_ncopts = ncopts; int result; ncopts = 0; result = ncattput(fd, varid, attnm, val_typ, val_len, val_ptr); ncopts = old_ncopts; return (result); } } /* */ MNCAPI int MI2endef(int fd) { if (MI2_ISH5OBJ(fd)) { return (MI_NOERROR); /* Just a stub, HDF5 doesn't do this! */ } else { return (ncendef(fd)); } } /* */ MNCAPI int MI2vardef(int fd, const char *varnm, nc_type vartype, int ndims, const int *dimids) { if (MI2_ISH5OBJ(fd)) { return (hdf_vardef(fd, varnm, vartype, ndims, dimids)); } else { return (ncvardef(fd, varnm, vartype, ndims, dimids)); } } /* */ MNCAPI int MI2varget(int fd, int varid, const long *start_ptr, const long *count_ptr, void *val_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_varget(fd, varid, start_ptr, count_ptr, val_ptr)); } else { return (ncvarget(fd, varid, start_ptr, count_ptr, val_ptr)); } } /* */ MNCAPI int MI2varput(int fd, int varid, const long *start_ptr, const long *count_ptr, const void *val_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_varput(fd, varid, start_ptr, count_ptr, val_ptr)); } else { return (ncvarput(fd, varid, start_ptr, count_ptr, val_ptr)); } } /* */ MNCAPI int MI2varput1(int fd, int varid, const long *mindex_ptr, const void *val_ptr) { if (MI2_ISH5OBJ(fd)) { return (hdf_varput1(fd, varid, mindex_ptr, val_ptr)); } else { return (ncvarput1(fd, varid, mindex_ptr, val_ptr)); } } MNCAPI int MI2attdel(int fd, int varid, const char *attnm) { if (MI2_ISH5OBJ(fd)) { return (hdf_attdel(fd, varid, attnm)); } else { return (ncattdel(fd, varid, attnm)); } } /* */ MNCAPI int MI2dimrename(int fd, int dimid, const char *new_name) { if (MI2_ISH5OBJ(fd)) { return (hdf_dimrename(fd, dimid, new_name)); } else { return (ncdimrename(fd, dimid, new_name)); } } MNCAPI int MI2varputg(int fd, int varid, const long *startp, const long *countp, const long *stridep, const long *imapp, const void *valp) { if (MI2_ISH5OBJ(fd)) { return (hdf_varputg(fd, varid, startp, countp, stridep, imapp, valp)); } else { return (ncvarputg(fd, varid, startp, countp, stridep, imapp, valp)); } } MNCAPI int MI2attcopy(int infd, int invarid, const char *name, int outfd, int outvarid) { if (!MI2_ISH5OBJ(infd) && !MI2_ISH5OBJ(outfd)) { /* Trivial case. */ return (ncattcopy(infd, invarid, name, outfd, outvarid)); } else { /* Complex case. Using our own compatibility layer functions lets us * handle all three other possible combinations of infd & outfd types. */ nc_type att_type; int att_length; void *val_ptr; int status; status = MI2attinq(infd, invarid, name, &att_type, &att_length); if (status == MI_ERROR) { return (MI_ERROR); } /* Special case for att_type == NC_CHAR && att_length == 0 */ if (att_type == NC_CHAR && att_length == 0) { val_ptr = malloc(1); if (val_ptr == NULL) { return (MI_ERROR); } *(char *)val_ptr = '\0'; att_length = 1; status = MI_NOERROR; } else { val_ptr = malloc(MI2typelen(att_type) * att_length); if (val_ptr == NULL) { return (MI_ERROR); } status = MI2attget(infd, invarid, name, val_ptr); } if (status != MI_ERROR) { status = MI2attput(outfd, outvarid, name, att_type, att_length, val_ptr); } free(val_ptr); return (status); } } MNCAPI int MI2typelen(int type_id) { switch (type_id) { case NC_BYTE: case NC_CHAR: return (1); case NC_SHORT: return (2); case NC_INT: case NC_FLOAT: return (4); case NC_DOUBLE: return (8); default: break; } fprintf(stderr, _("Unknown type %d"), type_id); return (-1); } MNCAPI int MI2redef(int fd) { if (MI2_ISH5OBJ(fd)) { /* Do nothing, since there is no equivalent in HDF5. */ return (MI_NOERROR); } else { return (ncredef(fd)); } } MNCAPI int MI2sync(int fd) { if (MI2_ISH5OBJ(fd)) { /* Commit the (entire) file to disk. */ if (H5Fflush(fd, H5F_SCOPE_GLOBAL) < 0) { return (MI_ERROR); } else { return (MI_NOERROR); } } else { return (ncsync(fd)); } } MNCAPI int MI2setfill(int fd, int fillmode) { if (MI2_ISH5OBJ(fd)) { /* TODO: ??? */ return (MI_NOERROR); } else { return (ncsetfill(fd, fillmode)); } } #endif /* MINC2 defined */ minc-2.2.00/libsrc/minc_simple.c0000644000265600003100000011306212027132662013364 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_simple.c @DESCRIPTION: Simplified interface to 3D and 4D minc files @METHOD : Routines included in this file : @CREATED : August 20, 2004. (Bert Vincent, Montreal Neurological Institute) @MODIFIED : * $Log: minc_simple.c,v $ * Revision 6.6 2008-01-11 07:17:07 stever * Remove unused variables. * * Revision 6.5 2005/08/26 21:04:58 bert * Use #if rather than #ifdef with MINC2 symbol * * Revision 6.4 2005/05/20 21:01:52 bert * Declare all public functions MNCAPI * * Revision 6.3 2005/01/04 22:45:57 bert * Adopt Leila's changes to restructure_array() and make appropriate corrections to the rest of the code * * Revision 6.2 2004/12/14 23:53:46 bert * Get rid of compilation warnings * * Revision 6.1 2004/11/01 22:06:48 bert * Initial checkin, simplified minc interface * @COPYRIGHT : Copyright 2004 Robert Vincent, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "minc_private.h" #include /* for sqrt */ #include /* for DBL_MAX */ #include "minc_simple.h" /* Trivial MINC interface */ #define MI_S_T 0 #define MI_S_Z 1 #define MI_S_Y 2 #define MI_S_X 3 #define MI_S_NDIMS 4 static char *minc_dimnames[] = { MItime, MIzspace, MIyspace, MIxspace }; /* private function from from libminc2. This function is private partially because it's parameters are somewhat bizarre. It would be a good idea to rework them into a more rational and easily described form. */ MNCAPI void restructure_array(int ndims, unsigned char *array, const unsigned long *lengths_perm, int el_size, const int *map, const int *dir); /* Structures used to represent a file in memory. */ struct att_info { char att_name[128]; nc_type att_type; int att_len; void *att_val; }; struct var_info { char var_name[128]; nc_type var_type; int var_natts; int var_ndims; int var_dims[MAX_NC_DIMS]; struct att_info *var_atts; }; struct file_info { int file_ndims; int file_nvars; int file_natts; struct att_info *file_atts; struct var_info *file_vars; }; static int minc_simple_to_nc_type(int minctype, nc_type *nctype, char **signstr) { switch (minctype) { case MINC_TYPE_CHAR: *nctype = NC_BYTE; *signstr = MI_SIGNED; break; case MINC_TYPE_UCHAR: *nctype = NC_BYTE; *signstr = MI_UNSIGNED; break; case MINC_TYPE_SHORT: *nctype = NC_SHORT; *signstr = MI_SIGNED; break; case MINC_TYPE_USHORT: *nctype = NC_SHORT; *signstr = MI_UNSIGNED; break; case MINC_TYPE_INT: *nctype = NC_INT; *signstr = MI_SIGNED; break; case MINC_TYPE_UINT: *nctype = NC_INT; *signstr = MI_UNSIGNED; break; case MINC_TYPE_FLOAT: *nctype = NC_FLOAT; *signstr = MI_SIGNED; break; case MINC_TYPE_DOUBLE: *nctype = NC_DOUBLE; *signstr = MI_SIGNED; break; default: return (MINC_STATUS_ERROR); } return (MINC_STATUS_OK); } MNCAPI int minc_file_size(char *path, long *ct, long *cz, long *cy, long *cx, long *cvoxels, long *cbytes) { int fd; nc_type nctype; int dim_id[MI_S_NDIMS]; long dim_len[MI_S_NDIMS]; int i; int var_id; int var_ndims; int var_dims[MAX_NC_DIMS]; long voxel_count; long byte_count; int old_ncopts; fd = miopen(path, NC_NOWRITE); if (fd < 0) { return (MINC_STATUS_ERROR); } old_ncopts = ncopts; ncopts = 0; for (i = 0; i < MI_S_NDIMS; i++) { dim_id[i] = ncdimid(fd, minc_dimnames[i]); if (dim_id[i] >= 0) { ncdiminq(fd, dim_id[i], NULL, &dim_len[i]); } else { dim_len[i] = 0; } } ncopts = old_ncopts; if (ct != NULL) { *ct = dim_len[MI_S_T]; } if (cz != NULL) { *cz = dim_len[MI_S_Z]; } if (cy != NULL) { *cy = dim_len[MI_S_Y]; } if (cx != NULL) { *cx = dim_len[MI_S_X]; } var_id = ncvarid(fd, MIimage); if (cvoxels != NULL || cbytes != NULL) { ncvarinq(fd, var_id, NULL, &nctype, &var_ndims, var_dims, NULL); voxel_count = 1; for (i = 0; i < var_ndims; i++) { long length; ncdiminq(fd, var_dims[i], NULL, &length); voxel_count *= length; } byte_count = voxel_count * nctypelen(nctype); if (cvoxels != NULL) { *cvoxels = voxel_count; } if (cbytes != NULL) { *cbytes = byte_count; } } return (MINC_STATUS_OK); } MNCAPI int minc_load_data(char *path, void *dataptr, int datatype, long *ct, long *cz, long *cy, long *cx, double *dt, double *dz, double *dy, double *dx, void **infoptr) { int fd; /* MINC file descriptor */ nc_type nctype; /* netCDF type */ char *signstr; /* MI_SIGNED or MI_UNSIGNED */ int length; int dim_id[MI_S_NDIMS]; long dim_len[MI_S_NDIMS]; int i, j; /* Generic loop counters */ int var_id; int var_ndims; int var_dims[MAX_NC_DIMS]; int icv; /* MINC image conversion variable */ long start[MI_S_NDIMS]; long count[MI_S_NDIMS]; int dir[MI_S_NDIMS]; /* Dimension "directions" */ int map[MI_S_NDIMS]; /* Dimension mapping */ int old_ncopts; /* For storing the old state of ncopts */ double *p_dtmp; long *p_ltmp; struct file_info *p_file; struct att_info *p_att; int r; /* Generic return code */ *infoptr = NULL; fd = miopen(path, NC_NOWRITE); if (fd < 0) { return (MINC_STATUS_ERROR); } old_ncopts = ncopts; ncopts = 0; for (i = 0; i < MI_S_NDIMS; i++) { dim_id[i] = ncdimid(fd, minc_dimnames[i]); if (dim_id[i] >= 0) { ncdiminq(fd, dim_id[i], NULL, &dim_len[i]); var_id = ncvarid(fd, minc_dimnames[i]); ncattinq(fd, var_id, MIstep, &nctype, &length); switch (i) { case MI_S_T: p_ltmp = ct; p_dtmp = dt; break; case MI_S_X: p_ltmp = cx; p_dtmp = dx; break; case MI_S_Y: p_ltmp = cy; p_dtmp = dy; break; case MI_S_Z: p_ltmp = cz; p_dtmp = dz; break; default: return (MINC_STATUS_ERROR); } if (nctype == NC_DOUBLE && length == 1) { ncattget(fd, var_id, MIstep, p_dtmp); } else { *p_dtmp = 0; /* Unknown/not set */ } *p_ltmp = dim_len[i]; } else { dim_len[i] = 0; } } ncopts = old_ncopts; var_id = ncvarid(fd, MIimage); ncvarinq(fd, var_id, NULL, &nctype, &var_ndims, var_dims, NULL); if (var_ndims != 3 && var_ndims != 4) { return (MINC_STATUS_ERROR); } /* We want the data to wind up in t, x, y, z order. */ for (i = 0; i < MI_S_NDIMS; i++) { map[i] = -1; } for (i = 0; i < var_ndims; i++) { if (var_dims[i] == dim_id[MI_S_T]) { map[MI_S_T] = i; } else if (var_dims[i] == dim_id[MI_S_X]) { map[MI_S_X] = i; } else if (var_dims[i] == dim_id[MI_S_Y]) { map[MI_S_Y] = i; } else if (var_dims[i] == dim_id[MI_S_Z]) { map[MI_S_Z] = i; } } icv = miicv_create(); minc_simple_to_nc_type(datatype, &nctype, &signstr); miicv_setint(icv, MI_ICV_TYPE, nctype); miicv_setstr(icv, MI_ICV_SIGN, signstr); miicv_attach(icv, fd, var_id); for (i = 0; i < var_ndims; i++) { start[i] = 0; } for (i = 0; i < MI_S_NDIMS; i++) { if (map[i] >= 0) { count[map[i]] = dim_len[i]; } } r = miicv_get(icv, start, count, dataptr); if (r < 0) { return (MINC_STATUS_ERROR); } if (map[MI_S_T] >= 0) { if (*dt < 0) { dir[MI_S_T] = -1; *dt = -*dt; } else { dir[MI_S_T] = 1; } } if (map[MI_S_X] >= 0) { if (*dx < 0) { dir[MI_S_X] = -1; *dx = -*dx; } else { dir[MI_S_X] = 1; } } if (map[MI_S_Y] >= 0) { if (*dy < 0) { dir[MI_S_Y] = -1; *dy = -*dy; } else { dir[MI_S_Y] = 1; } } if (map[MI_S_Z] >= 0) { if (*dz < 0) { dir[MI_S_Z] = -1; *dz = -*dz; } else { dir[MI_S_Z] = 1; } } if (var_ndims == 3) { for (i = 1; i < MI_S_NDIMS; i++) { map[i-1] = map[i]; dir[i-1] = dir[i]; } } j = 0; for (i = 0; i < MI_S_NDIMS; i++) { if (dim_len[i] > 0) { count[j++] = dim_len[i]; } } restructure_array(var_ndims, dataptr, count, nctypelen(nctype), map, dir); miicv_detach(icv); miicv_free(icv); old_ncopts = ncopts; ncopts = 0; /* Generate the complete infoptr array. * This is essentially an in-memory copy of the variables and attributes * in the file. */ p_file = (struct file_info *) malloc(sizeof (struct file_info)); ncinquire(fd, &p_file->file_ndims, &p_file->file_nvars, &p_file->file_natts, NULL); p_file->file_atts = (struct att_info *) malloc(sizeof (struct att_info) * p_file->file_natts); p_file->file_vars = (struct var_info *) malloc(sizeof (struct var_info) * p_file->file_nvars); for (i = 0; i < p_file->file_natts; i++) { p_att = &p_file->file_atts[i]; ncattname(fd, NC_GLOBAL, i, p_att->att_name); ncattinq(fd, NC_GLOBAL, p_att->att_name, &p_att->att_type, &p_att->att_len); p_att->att_val = malloc(p_att->att_len * nctypelen(p_att->att_type)); ncattget(fd, NC_GLOBAL, p_att->att_name, p_att->att_val); } for (i = 0; i < p_file->file_nvars; i++) { struct var_info *p_var = &p_file->file_vars[i]; ncvarinq(fd, i, p_var->var_name, &p_var->var_type, &p_var->var_ndims, p_var->var_dims, &p_var->var_natts); p_var->var_atts = malloc(p_var->var_natts * sizeof (struct att_info)); if (ncdimid(fd, p_var->var_name) >= 0) { /* It's a dimension variable, have to treat it specially... */ } for (j = 0; j < p_var->var_natts; j++) { p_att = &p_var->var_atts[j]; ncattname(fd, i, j, p_att->att_name); ncattinq(fd, i, p_att->att_name, &p_att->att_type, &p_att->att_len); p_att->att_val = malloc(p_att->att_len * nctypelen(p_att->att_type)); ncattget(fd, i, p_att->att_name, p_att->att_val); } } *infoptr = p_file; ncopts = old_ncopts; miclose(fd); return (MINC_STATUS_OK); } MNCAPI void minc_free_info(void *infoptr) { struct file_info *p_file; int i, j; if ((p_file = infoptr) != NULL) { if (p_file->file_natts != 0 && p_file->file_atts != NULL) { for (i = 0; i < p_file->file_natts; i++) { free(p_file->file_atts[i].att_val); } free(p_file->file_atts); } if (p_file->file_nvars != 0 && p_file->file_vars != NULL) { for (i = 0; i < p_file->file_nvars; i++) { if (p_file->file_vars[i].var_natts != 0 && p_file->file_vars[i].var_atts != NULL) { for (j = 0; j < p_file->file_vars[i].var_natts; j++) { if (p_file->file_vars[i].var_atts[j].att_val != NULL) { free(p_file->file_vars[i].var_atts[j].att_val); } } free(p_file->file_vars[i].var_atts); } } free(p_file->file_vars); } } } /* int minc_save_start() * * Returns an opaque handle which must be passed to successive calls to * minc_save_data() and ultimately to minc_save_done(). */ MNCAPI int minc_save_start(char *path, /* Path to the file */ int filetype, /* Date type as stored in the file */ long ct, /* Total length of time axis, in voxels */ long cz, /* Total length of Z axis, in voxels */ long cy, /* Total length of Y axis, in voxels */ long cx, /* Total length of X axis, in voxels */ double dt, /* Sample width along time axis, in seconds */ double dz, /* Sample width along Z axis, in mm */ double dy, /* Sample width along Y axis, in mm */ double dx, /* Sample width along X axis, in mm */ void *infoptr, /* Opaque file structure information */ const char *history) /* New history information */ { int fd; /* MINC file descriptor */ int dim_id[MI_S_NDIMS]; /* netCDF dimension ID array */ int var_ndims; /* Number of dimensions per variable */ int var_dims[MI_S_NDIMS]; /* Dimension ID's per variable */ int i, j; /* Generic loop counters */ int old_ncopts; /* For supressing fatal error messages */ struct file_info *p_file; /* For accessing the file structure */ struct var_info *p_var; struct att_info *p_att; int var_id; /* netCDF ID for variable */ char *signstr; nc_type nctype; old_ncopts = ncopts; ncopts = 0; fd = micreate(path, NC_CLOBBER); if (fd < 0) { return (MINC_STATUS_ERROR); } if (ct > 0) { dim_id[MI_S_T] = ncdimdef(fd, MItime, ct); micreate_std_variable(fd, MItime, NC_INT, 0, NULL); if (dt > 0.0) { miattputdbl(fd, ncvarid(fd, MItime), MIstep, dt); } } else { dim_id[MI_S_T] = -1; } if (cz > 0) { dim_id[MI_S_Z] = ncdimdef(fd, MIzspace, cz); micreate_std_variable(fd, MIzspace, NC_INT, 0, NULL); if (dz > 0.0) { miattputdbl(fd, ncvarid(fd, MIzspace), MIstep, dz); } } else { dim_id[MI_S_Z] = -1; } if (cy > 0) { dim_id[MI_S_Y] = ncdimdef(fd, MIyspace, cy); micreate_std_variable(fd, MIyspace, NC_INT, 0, NULL); if (dy > 0.0) { miattputdbl(fd, ncvarid(fd, MIyspace), MIstep, dy); } } else { return (MINC_STATUS_ERROR); /* Must define Y */ } if (cx > 0) { dim_id[MI_S_X] = ncdimdef(fd, MIxspace, cx); micreate_std_variable(fd, MIxspace, NC_INT, 0, NULL); if (dx > 0.0) { miattputdbl(fd, ncvarid(fd, MIxspace), MIstep, dx); } } else { return (MINC_STATUS_ERROR); /* Must define X */ } /* The var_dims[] array is the array of actual dimension ID's to * be used in defining the image variables. Here I set it up by * copying all valid dimension ID's from the dim_id[] array. */ var_ndims = 0; for (i = 0; i < MI_S_NDIMS; i++) { if (dim_id[i] >= 0) { var_dims[var_ndims] = dim_id[i]; var_ndims++; } } minc_simple_to_nc_type(filetype, &nctype, &signstr); /* Create the image variable with the standard * dimension order, and the same type as the template * file. */ micreate_std_variable(fd, MIimage, nctype, var_ndims, var_dims); micreate_std_variable(fd, MIimagemin, NC_DOUBLE, 1, var_dims); micreate_std_variable(fd, MIimagemax, NC_DOUBLE, 1, var_dims); /* Copy information from the infoptr to the output. */ if ((p_file = infoptr) != NULL) { old_ncopts = ncopts; ncopts = 0; for (i = 0; i < p_file->file_natts; i++) { p_att = &p_file->file_atts[i]; if (strcmp(p_att->att_name, "ident") != 0) { ncattput(fd, NC_GLOBAL, p_att->att_name, p_att->att_type, p_att->att_len, p_att->att_val); } } for (i = 0; i < p_file->file_nvars; i++) { p_var = &p_file->file_vars[i]; if ((var_id = ncvarid(fd, p_var->var_name)) < 0) { var_id = ncvardef(fd, p_var->var_name, p_var->var_type, p_var->var_ndims, p_var->var_dims); } for (j = 0; j < p_var->var_natts; j++) { p_att = &p_var->var_atts[j]; ncattput(fd, var_id, p_att->att_name, p_att->att_type, p_att->att_len, p_att->att_val); } } } miattputstr(fd, ncvarid(fd, MIimage), MIcomplete, MI_FALSE); miattputstr(fd, ncvarid(fd, MIimage), MIsigntype, signstr); miappend_history(fd, history); ncendef(fd); return fd; } /* Internal function */ static void find_minmax(void *dataptr, long datacount, int datatype, double *min, double *max) { *min = DBL_MAX; *max = -DBL_MAX; switch (datatype) { case MINC_TYPE_CHAR: { char *c_ptr = dataptr; while (datacount--) { if (*c_ptr > *max) { *max = *c_ptr; } if (*c_ptr < *min) { *min = *c_ptr; } c_ptr++; } } break; case MINC_TYPE_UCHAR: { unsigned char *c_ptr = dataptr; while (datacount--) { if (*c_ptr > *max) { *max = *c_ptr; } if (*c_ptr < *min) { *min = *c_ptr; } c_ptr++; } } break; case MINC_TYPE_SHORT: { short *s_ptr = dataptr; while (datacount--) { if (*s_ptr > *max) { *max = *s_ptr; } if (*s_ptr < *min) { *min = *s_ptr; } s_ptr++; } } break; case MINC_TYPE_USHORT: { unsigned short *s_ptr = dataptr; while (datacount--) { if (*s_ptr > *max) { *max = *s_ptr; } if (*s_ptr < *min) { *min = *s_ptr; } s_ptr++; } } break; case MINC_TYPE_INT: { int *i_ptr = dataptr; while (datacount--) { if (*i_ptr > *max) { *max = *i_ptr; } if (*i_ptr < *min) { *min = *i_ptr; } i_ptr++; } } break; case MINC_TYPE_UINT: { unsigned int *i_ptr = dataptr; while (datacount--) { if (*i_ptr > *max) { *max = *i_ptr; } if (*i_ptr < *min) { *min = *i_ptr; } i_ptr++; } } break; case MINC_TYPE_FLOAT: { float *f_ptr = dataptr; while (datacount--) { if (*f_ptr > *max) { *max = *f_ptr; } if (*f_ptr < *min) { *min = *f_ptr; } f_ptr++; } } break; case MINC_TYPE_DOUBLE: { double *d_ptr = dataptr; while (datacount--) { if (*d_ptr > *max) { *max = *d_ptr; } if (*d_ptr < *min) { *min = *d_ptr; } d_ptr++; } } break; default: return; } } MNCAPI int minc_save_data(int fd, void *dataptr, int datatype, long st, long sz, long sy, long sx, long ct, long cz, long cy, long cx) { nc_type nctype; char *signstr; int i; int var_id; int var_ndims; int var_dims[MAX_NC_DIMS]; int icv; long start[MI_S_NDIMS]; long count[MI_S_NDIMS]; int old_ncopts; int r; double min, max; long slice_size; long index; int dtbytes; /* Length of datatype in bytes */ old_ncopts = ncopts; ncopts = 0; var_id = ncvarid(fd, MIimage); ncvarinq(fd, var_id, NULL, NULL, &var_ndims, var_dims, NULL); if (var_ndims < 2 || var_ndims > 4) { return (MINC_STATUS_ERROR); } r = minc_simple_to_nc_type(datatype, &nctype, &signstr); if (r == MINC_STATUS_ERROR) { return (MINC_STATUS_ERROR); } dtbytes = nctypelen(nctype); /* Update the image-min and image-max values */ if (ct > 0) { slice_size = cz * cy * cx; index = st; for (i = 0; i < ct; i++) { find_minmax((char *) dataptr + (dtbytes * slice_size * i), slice_size, datatype, &min, &max); mivarput1(fd, ncvarid(fd, MIimagemin), &index, NC_DOUBLE, MI_SIGNED, &min); mivarput1(fd, ncvarid(fd, MIimagemax), &index, NC_DOUBLE, MI_SIGNED, &max); index++; } } else { slice_size = cy * cx; index = sz; for (i = 0; i < cz; i++) { find_minmax((char *) dataptr + (dtbytes * slice_size * i), slice_size, datatype, &min, &max); mivarput1(fd, ncvarid(fd, MIimagemin), &index, NC_DOUBLE, MI_SIGNED, &min); mivarput1(fd, ncvarid(fd, MIimagemax), &index, NC_DOUBLE, MI_SIGNED, &max); index++; } } /* We want the data to wind up in t, x, y, z order. */ icv = miicv_create(); if (icv < 0) { return (MINC_STATUS_ERROR); } r = miicv_setint(icv, MI_ICV_TYPE, nctype); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_setstr(icv, MI_ICV_SIGN, signstr); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_setint(icv, MI_ICV_DO_NORM, 1); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_setint(icv, MI_ICV_DO_FILLVALUE, 1); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_attach(icv, fd, var_id); if (r < 0) { return (MINC_STATUS_ERROR); } i = 0; switch (var_ndims) { case 4: count[i] = ct; start[i] = st; i++; /* fall through */ case 3: count[i] = cz; start[i] = sz; i++; /* fall through */ case 2: count[i] = cy; start[i] = sy; i++; count[i] = cx; start[i] = sx; i++; break; } r = miicv_put(icv, start, count, dataptr); if (r < 0) { return (MINC_STATUS_ERROR); } miicv_detach(icv); miicv_free(icv); return (MINC_STATUS_OK); } MNCAPI int minc_save_done(int fd) { miattputstr(fd, ncvarid(fd, MIimage), MIcomplete, MI_TRUE); miclose(fd); return (MINC_STATUS_OK); } static void normalize_vector(double vector[MINC_3D]) { int i; double magnitude; magnitude = 0.0; for (i = 0; i < MINC_3D; i++) { magnitude += (vector[i] * vector[i]); } magnitude = sqrt(magnitude); if (magnitude > 0.0) { for (i = 0; i < MINC_3D; i++) { vector[i] /= magnitude; } } } MNCAPI int minc_get_world_transform(char *path, double transform[MINC_3D][MINC_3D+1]) { int i, j; double dircos[MINC_3D]; double step, start; char *dimensions[] = { MIxspace, MIyspace, MIzspace }; int length; int fd; int varid; int old_ncopts; old_ncopts = ncopts; ncopts = 0; fd = miopen(path, NC_NOWRITE); if (fd < 0) { return (MINC_STATUS_ERROR); } /* Zero the matrix */ for (i = 0; i < MINC_3D; i++) { for (j = 0; j < MINC_3D + 1; j++) { transform[i][j] = 0.0; } transform[i][i] = 1.0; } for (j = 0; j < MINC_3D; j++) { /* Set default values */ step = 1.0; start = 0.0; for (i = 0; i < MINC_3D; i++) { dircos[i] = 0.0; } dircos[j] = 1.0; varid = ncvarid(fd, dimensions[j]); miattget(fd, varid, MIstart, NC_DOUBLE, 1, &start, &length); miattget(fd, varid, MIstep, NC_DOUBLE, 1, &step, &length); miattget(fd, varid, MIdirection_cosines, NC_DOUBLE, 3, dircos, &length); normalize_vector(dircos); /* Put them in the matrix. */ for (i = 0; i < MINC_3D; i++) { transform[i][j] = step * dircos[i]; transform[i][MINC_3D] += start * dircos[i]; } } ncopts = old_ncopts; return (MINC_STATUS_OK); } #if !MINC2 typedef unsigned long mioffset_t; /** In-place array dimension restructuring. * * Based on Chris H.Q. Ding, "An Optimal Index Reshuffle Algorithm for * Multidimensional Arrays and its Applications for Parallel Architectures" * IEEE Transactions on Parallel and Distributed Systems, Vol.12, No.3, * March 2001, pp.306-315. * * I rewrote the algorithm in "C" an generalized it to N dimensions. * * Guaranteed to do the minimum number of memory moves, but requires * that we allocate a bitmap of nelem/8 bytes. The paper suggests * ways to eliminate the bitmap - I'll work on it. */ /** * Map a set of array coordinates to a linear offset in the array memory. */ static mioffset_t index_to_offset(int ndims, const unsigned long sizes[], const unsigned long index[]) { mioffset_t offset = index[0]; int i; for (i = 1; i < ndims; i++) { offset *= sizes[i]; offset += index[i]; } return (offset); } /** * Map a linear offset to a set of coordinates in a multidimensional array. */ static void offset_to_index(int ndims, const unsigned long sizes[], mioffset_t offset, unsigned long index[]) { int i; for (i = ndims - 1; i > 0; i--) { index[i] = offset % sizes[i]; offset /= sizes[i]; } index[0] = offset; } /* Trivial bitmap test & set. */ #define BIT_TST(bm, i) (bm[(i) / 8] & (1 << ((i) % 8))) #define BIT_SET(bm, i) (bm[(i) / 8] |= (1 << ((i) % 8))) /** The main restructuring code. */ MNCAPI void restructure_array(int ndims, /* Dimension count */ unsigned char *array, /* Raw data */ const unsigned long *lengths_perm, /* Permuted lengths */ int el_size, /* Element size, in bytes */ const int *map, /* Mapping array */ const int *dir) /* Direction array, in permuted order */ { unsigned long index[MAX_VAR_DIMS]; /* Raw indices */ unsigned long index_perm[MAX_VAR_DIMS]; /* Permuted indices */ unsigned long lengths[MAX_VAR_DIMS]; /* Raw (unpermuted) lengths */ unsigned char *temp; mioffset_t offset_start; mioffset_t offset_next; mioffset_t offset; unsigned char *bitmap; size_t total; int i; if ((temp = malloc(el_size)) == NULL) { return; } /** * Permute the lengths from their "output" configuration back into * their "raw" or native order: **/ for (i = 0; i < ndims; i++) { //lengths[i] = lengths_perm[map[i]]; lengths[map[i]] = lengths_perm[i]; } /** * Calculate the total size of the array, in elements. **/ total = 1; for (i = 0; i < ndims; i++) { total *= lengths[i]; } /** * Allocate a bitmap with enough space to hold one bit for each * element in the array. **/ bitmap = calloc((total + 8 - 1) / 8, 1); /* bit array */ if (bitmap == NULL) { return; } for (offset_start = 0; offset_start < total; offset_start++) { /** * Look for an unset bit - that's where we start the next * cycle. **/ if (!BIT_TST(bitmap, offset_start)) { /** * Found a cycle we have not yet performed. **/ offset_next = -1; /* Initialize. */ #ifdef DEBUG printf("%ld", offset_start); #endif /* DEBUG */ /** * Save the first element in this cycle. **/ memcpy(temp, array + (offset_start * el_size), el_size); /** * We've touched this location. **/ BIT_SET(bitmap, offset_start); offset = offset_start; /** * Do until the cycle repeats. **/ while (offset_next != offset_start) { /** * Compute the index from the offset and permuted length. **/ offset_to_index(ndims, lengths_perm, offset, index_perm); /** * Permute the index into the alternate arrangement. **/ for (i = 0; i < ndims; i++) { if (dir[i] < 0) { // index[i] = lengths[i] - index_perm[map[i]] - 1; index[map[i]] = lengths[map[i]] - index_perm[i] - 1; } else { //index[i] = index_perm[map[i]]; index[map[i]] = index_perm[i]; } } /** * Calculate the next offset from the permuted index. **/ offset_next = index_to_offset(ndims, lengths, index); #ifdef DEBUG if (offset_next >= total) { printf("Fatal - offset %ld out of bounds!\n", offset_next); printf("lengths %ld,%ld,%ld\n", lengths[0],lengths[1],lengths[2]); printf("index %ld,%ld,%ld\n", index_perm[0], index_perm[0], index_perm[2]); exit(-1); } #endif /** * If we are not at the end of the cycle... **/ if (offset_next != offset_start) { /** * Note that we've touched a new location. **/ BIT_SET(bitmap, offset_next); #ifdef DEBUG printf(" - %ld", offset_next); #endif /* DEBUG */ /** * Move from old to new location. **/ memcpy(array + (offset * el_size), array + (offset_next * el_size), el_size); /** * Advance offset to the next location in the cycle. **/ offset = offset_next; } } /** * Store the first value in the cycle, which we saved in * 'tmp', into the last offset in the cycle. **/ memcpy(array + (offset * el_size), temp, el_size); #ifdef DEBUG printf("\n"); #endif /* DEBUG */ } } free(bitmap); /* Get rid of the bitmap. */ free(temp); } #endif /* !MINC2 */ #ifdef MINC_SIMPLE_TEST /* #define NC_TYPE MINC_TYPE_FLOAT #define MM_TYPE float #define MM_FMT "%20.16g" #define EPSILON 1.0e-6 */ #define NC_TYPE MINC_TYPE_DOUBLE #define MM_TYPE double #define MM_FMT "%20.16g" #define EPSILON 1.0e-9 /* #define NC_TYPE MINC_TYPE_CHAR #define MM_TYPE unsigned char #define MM_FMT "%d" */ /* #define NC_TYPE MINC_TYPE_SHORT #define MM_TYPE short #define MM_FMT "%d" */ /* #define NC_TYPE MINC_TYPE_INT #define MM_TYPE int #define MM_FMT "%d" */ #define CX 11 #define CY 12 #define CZ 9 main(int argc, char **argv) { short buffer[1][256][256][256]; long ct, cx, cy, cz; double dt, dx, dy, dz; long cvoxels, cbytes; int i, j, k; int h; MM_TYPE buf_xyz[CX][CY][CZ]; MM_TYPE buf_xYz[CX][CY][CZ]; /* Negative Y */ MM_TYPE buf_xyZ[CX][CY][CZ]; /* Negative Z */ MM_TYPE buf_xzy[CX][CY][CZ]; MM_TYPE buf_yxz[CX][CY][CZ]; MM_TYPE buf_yzx[CX][CY][CZ]; MM_TYPE buf_zyx[CX][CY][CZ]; MM_TYPE buf_zxy[CX][CY][CZ]; void *inf_xyz; void *inf_xYz; void *inf_xyZ; void *inf_xzy; void *inf_yxz; void *inf_yzx; void *inf_zxy; void *inf_zyx; int errors[6]; printf("junk-xyz.mnc\n"); minc_load_data("junk-xyz.mnc", buf_xyz, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_xyz); printf("junk-xYz.mnc\n"); minc_load_data("junk-xYz.mnc", buf_xYz, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_xYz); printf("junk-xyZ.mnc\n"); minc_load_data("junk-xyZ.mnc", buf_xyZ, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_xyZ); printf("junk-xzy.mnc\n"); minc_load_data("junk-xzy.mnc", buf_xzy, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_xzy); printf("junk-yxz.mnc\n"); minc_load_data("junk-yxz.mnc", buf_yxz, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_yxz); printf("junk-yzx.mnc\n"); minc_load_data("junk-yzx.mnc", buf_yzx, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_yzx); printf("junk-zxy.mnc\n"); minc_load_data("junk-zxy.mnc", buf_zxy, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_zxy); printf("junk-zyx.mnc\n"); minc_load_data("junk-zyx.mnc", buf_zyx, NC_TYPE, &ct, &cx, &cy, &cz, &dt, &dx, &dy, &dz, &inf_zyx); for (i = 0; i < 6; i++) { errors[i] = 0; } #ifdef EPSILON #define CLOSE(a, b) (fabs(a - b) < EPSILON) #else #define CLOSE(a, b) (a == b) #endif for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { double e; if (!CLOSE(buf_xyz[i][j][k], buf_xzy[i][j][k])) { printf(MM_FMT, buf_xyz[i][j][k]); printf(" "); printf(MM_FMT, buf_xzy[i][j][k]); printf("\n"); errors[1]++; } if (!CLOSE(buf_xyz[i][j][k], buf_xYz[i][j][k])) { errors[0]++; } if (!CLOSE(buf_xyz[i][j][k], buf_xyZ[i][j][k])) { errors[0]++; } if (!CLOSE(buf_xyz[i][j][k], buf_yxz[i][j][k])) { errors[2]++; } if (!CLOSE(buf_xyz[i][j][k], buf_yzx[i][j][k])) { errors[3]++; } if (!CLOSE(buf_xyz[i][j][k], buf_zxy[i][j][k])) { errors[4]++; } if (!CLOSE(buf_xyz[i][j][k], buf_zyx[i][j][k])) { errors[5]++; } } } } for (i = 0; i < 6; i++) { printf("%d - ", errors[i]); printf("\n"); } h = minc_save_start("temp-xyz.mnc", MINC_TYPE_SHORT, ct, cx, cy, cz, dt, dx, dy, dz, inf_xyz, "testing"); minc_save_data(h, buf_xyz, NC_TYPE, 0, 0, 0, 0, ct, cx, cy, cz); minc_save_done(h); h = minc_save_start("temp-xzy.mnc", MINC_TYPE_SHORT, ct, cx, cy, cz, dt, dx, dy, dz, inf_xzy, "testing"); minc_save_data(h, buf_xzy, NC_TYPE, 0, 0, 0, 0, ct, cx, cy, cz); minc_save_done(h); h = minc_save_start("temp-yxz.mnc", MINC_TYPE_SHORT, ct, cx, cy, cz, dt, dx, dy, dz, inf_yxz, "testing"); minc_save_data(h, buf_yxz, NC_TYPE, 0, 0, 0, 0, ct, cx, cy, cz); minc_save_done(h); h = minc_save_start("temp-yzx.mnc", MINC_TYPE_SHORT, ct, cx, cy, cz, dt, dx, dy, dz, inf_yzx, "testing"); minc_save_data(h, buf_yzx, NC_TYPE, 0, 0, 0, 0, ct, cx, cy, cz); minc_save_done(h); h = minc_save_start("temp-zxy.mnc", MINC_TYPE_SHORT, ct, cx, cy, cz, dt, dx, dy, dz, inf_zxy, "testing"); minc_save_data(h, buf_zxy, NC_TYPE, 0, 0, 0, 0, ct, cx, cy, cz); minc_save_done(h); h = minc_save_start("temp-zyx.mnc", MINC_TYPE_SHORT, ct, cx, cy, cz, dt, dx, dy, dz, inf_zyx, "testing"); minc_save_data(h, buf_zyx, NC_TYPE, 0, 0, 0, 0, ct, cx, cy, cz); minc_save_done(h); } #endif /* MINC_SIMPLE_TEST */ minc-2.2.00/libsrc/strdup.c0000644000265600003100000000306712027132662012411 00000000000000#include #include /* ----------------------------- MNI Header ----------------------------------- @NAME : strdup @INPUT : string - string to duplicate @OUTPUT : (none) @RETURNS : Pointer to duplicate string or NULL if an error occurs @DESCRIPTION: Makes a duplicate of a string and returns a pointer to it. @METHOD : VAX CC rtl does not have strdup, so we provide it here to be included in minc.olb. @GLOBALS : @CALLS : @CREATED : June 18, 1993 (Peter Neelin) @MODIFIED : * $Log: strdup.c,v $ * Revision 6.1 1999-10-19 14:45:11 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:54 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:53 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:07:52 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:33:12 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:38:18 neelin * Release of minc version 0.2 * * Revision 1.3 94/09/28 10:37:36 neelin * Pre-release * * Revision 1.2 93/08/11 12:06:30 neelin * Added RCS logging in source. * ---------------------------------------------------------------------------- */ char *strdup(const char *string) { int length; char *new_string; /* Get the string length */ length = strlen(string); /* Allocate space */ new_string = malloc((size_t) length+1); if (new_string == NULL) { return NULL; } /* Copy the string */ return strcpy(new_string, string); } minc-2.2.00/libsrc/config.h.msvc-win320000644000265600003100000000166312027132662014251 00000000000000/* Win32 config.h for MINC * * Author: Bert Vincent * * $Header: /private-cvsroot/minc/libsrc/config.h.msvc-win32,v 6.3 2005-07-18 22:19:01 bert Exp $ */ #ifndef _CONFIG_H_ #define _CONFIG_H_ 1 #define HAVE_FCNTL_H 1 #define HAVE_FLOAT_H 1 #define HAVE_MEMORY_H 1 #define HAVE_STDINT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_SYS_STAT_H 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_TEMPNAM 1 #define HAVE_TMPNAM 1 #define STDC_HEADERS 1 #define VERSION "2.0.09" #define sleep(x) _sleep(x) #define snprintf _snprintf #define strncasecmp(x,y,z) strnicmp(x,y,z) #define tempnam(x,y) _tempnam(x,y) int __stdcall gethostname(char *name, int namelen); /* Quick implmentation of rint() for Intel, since thoughtless Microsoft * programmers failed to provide us with one... */ __inline double rint(double dblvar) { __asm fld dblvar __asm frndint __asm fst dblvar return dblvar; } #endif /* _CONFIG_H_ not defined */ minc-2.2.00/libsrc2/0000755000265600003100000000000012030114724011051 500000000000000minc-2.2.00/libsrc2/minc2.h0000644000265600003100000005513712030075003012161 00000000000000/** \file minc2.h * \brief MINC 2.0 public constants, types, and definitions. */ #ifndef _MINC2_H_ /* Avoid multiple inclusions */ #define _MINC2_H_ 1 #ifdef __cplusplus extern "C" { /* Hey, Mr. Compiler - this is "C" code! */ #endif /* __cplusplus defined */ /************************************************************************ * CONSTANTS ************************************************************************/ #ifndef MI_NOERROR /** Generic return code for successful operations. */ #define MI_NOERROR 0 #endif /* MI_NOERROR not defined */ #ifndef MI_ERROR /** Generic return code for operations which fail for any reason. */ #define MI_ERROR (-1) #endif /* MI_ERROR not defined */ #define MI_NATIVE "native____" #define MI_TALAIRACH "talairach_" #define MI_CALLOSAL "callosal__" #ifndef TRUE #define TRUE 1 #endif /* TRUE */ #ifndef FALSE #define FALSE 0 #endif /* FALSE */ /** World spatial coordinates should always have this structure. */ #define MI2_3D 3 #define MI2_X 0 #define MI2_Y 1 #define MI2_Z 2 /** Dimension attribute values. */ #define MI_DIMATTR_ALL 0 #define MI_DIMATTR_REGULARLY_SAMPLED 0x1 #define MI_DIMATTR_NOT_REGULARLY_SAMPLED 0x2 /** Maximum length of a standard string. */ #define MI2_CHAR_LENGTH 128 /** Maximum number of dimensions a variable can have. */ #define MI2_MAX_VAR_DIMS 100 #define MI2_CHUNK_SIZE 32 /* Length of chunk, per dimension */ #define MI2_DEFAULT_ZLIB_LEVEL 4 #define MI2_MAX_ZLIB_LEVEL 9 #define MI2_MAX_PATH 128 #define MI2_MAX_RESOLUTION_GROUP 16 #define MI2_OPEN_READ 0x0001 #define MI2_OPEN_RDWR 0x0002 #define MI_VERSION_2_0 "MINC Version 2.0" /************************************************************************ * ENUMS, STRUCTS, and TYPEDEFS ************************************************************************/ /* These structure declarations exist to allow the following typedefs to * work. Since the details of these structures are not meant to be public, * the actual structure definitions are in minc2_private.h */ struct mivolprops; struct midimension; struct mivolume; /** \typedef mivolumeprops_t * Opaque pointer to volume properties. */ typedef struct mivolprops *mivolumeprops_t; /** \typedef midimhandle_t * Opaque pointer to a MINC dimension object. */ typedef struct midimension *midimhandle_t; /** \typedef mihandle_t * The mihandle_t is an opaque type that represents a MINC file object. */ typedef struct mivolume *mihandle_t; typedef void *milisthandle_t; /** * This typedef used to represent the type of an individual voxel as * stored by MINC 2.0. If a volume is */ typedef enum { MI_TYPE_BYTE = 1, /**< 8-bit signed integer */ MI_TYPE_SHORT = 3, /**< 16-bit signed integer */ MI_TYPE_INT = 4, /**< 32-bit signed integer */ MI_TYPE_FLOAT = 5, /**< 32-bit floating point */ MI_TYPE_DOUBLE = 6, /**< 64-bit floating point */ MI_TYPE_STRING = 7, /**< ASCII string */ MI_TYPE_UBYTE = 100, /**< 8-bit unsigned integer */ MI_TYPE_USHORT = 101, /**< 16-bit unsigned integer */ MI_TYPE_UINT = 102, /**< 32-bit unsigned integer */ MI_TYPE_SCOMPLEX = 1000, /**< 16-bit signed integer complex */ MI_TYPE_ICOMPLEX = 1001, /**< 32-bit signed integer complex */ MI_TYPE_FCOMPLEX = 1002, /**< 32-bit floating point complex */ MI_TYPE_DCOMPLEX = 1003, /**< 64-bit floating point complex */ MI_TYPE_UNKNOWN = -1 /**< when the type is a record */ } mitype_t; /** * This typedef is used to represent the class of the MINC file. * * The class specifies the data's interpretation rather than its * storage format. For example, a floating point class implies * that the data may be stored as integers but must nonetheless be * scaled into a "real" range before any mathematical operations * are performed. A label class implies that the values of a voxel * should be considered to represent a symbol, and therefore many * operations on the voxels would be considered meaningless. */ typedef enum { MI_CLASS_REAL = 0, /**< Floating point (default) */ MI_CLASS_INT = 1, /**< Integer */ MI_CLASS_LABEL = 2, /**< Enumerated (named data values) */ MI_CLASS_COMPLEX = 3, /**< Complex (real/imaginary) values */ MI_CLASS_UNIFORM_RECORD = 4, /**< Aggregate datatypes consisting of multiple values of the same underlying type. */ MI_CLASS_NON_UNIFORM_RECORD = 5 /**< Aggregate datatypes consisting of multiple values of potentially differing types (not yet implemented). */ } miclass_t; /** Dimensions be members of one of several classes. The "MI_DIMCLASS_ANY" * value is never actually assigned to a dimension. It is used in the * programming interface to specify that an operation should apply to * all dimensions regardless of class. */ typedef enum { MI_DIMCLASS_ANY = 0, /**< Don't care (or unknown) */ MI_DIMCLASS_SPATIAL = 1, /**< Spatial dimensions (x, y, z) */ MI_DIMCLASS_TIME = 2, /**< Time dimension */ MI_DIMCLASS_SFREQUENCY = 3, /**< Spatial frequency dimensions */ MI_DIMCLASS_TFREQUENCY = 4, /**< Temporal frequency dimensions */ MI_DIMCLASS_USER = 5, /**< Arbitrary user-defined dimension */ MI_DIMCLASS_RECORD = 6 /**< Record as dimension */ } midimclass_t; /** Dimension order refers to the idea that data can be structured in * a variety of ways with respect to the dimensions. For example, a typical * 3D scan could be structured as a transverse (ZYX) or sagittal (XZY) image. * Since it may be convenient to write code which expects a particular * dimension order, a user can specify an alternative ordering by using * miset_apparent_dimension_order(). This will cause most functions * to return data as if the file was in the apparent, rather than the * file (native) order. */ typedef enum { MI_DIMORDER_FILE = 0, MI_DIMORDER_APPARENT = 1 } miorder_t; /** Voxel order can be either file (native), or apparent, as set by * the function miset_dimension_apparent_voxel_order(). */ typedef enum { MI_ORDER_FILE = 0, /**< File order */ MI_ORDER_APPARENT = 1 /**< Apparent (user) order */ } mivoxel_order_t; /** * Voxel flipping can be specified to either follow the file's native * order, the opposite of the file's order, or it can be tied to the * value of the dimension's step attribute. A value of MI_NEGATIVE * implies that the voxel order should be rearranged such that the step * attribute is negative, a value of MI_POSITIVE implies the opposite. */ typedef enum { MI_FILE_ORDER = 0, /**< no flip */ MI_COUNTER_FILE_ORDER = 1, /**< flip */ MI_POSITIVE = 2, /**< force step value to be positive */ MI_NEGATIVE = 3 /**< force step value to be negative */ } miflipping_t; /** Compression type */ typedef enum { MI_COMPRESS_NONE = 0, /**< No compression */ MI_COMPRESS_ZLIB = 1 /**< GZIP compression */ } micompression_t; typedef int miboolean_t; typedef unsigned int midimattr_t; typedef unsigned long misize_t; /** 16-bit integer complex voxel. */ typedef struct { short real; /**< Real part */ short imag; /**< Imaginary part */ } miscomplex_t; /** 32-bit integer complex voxel. */ typedef struct { int real; /**< Real part */ int imag; /**< Imaginary part */ } miicomplex_t; /** 32-bit floating point complex voxel. */ typedef struct { float real; /**< Real part */ float imag; /**< Imaginary part */ } mifcomplex_t; /** 64-bit floating point complex voxel. */ typedef struct { double real; /**< Real part */ double imag; /**< Imaginary part */ } midcomplex_t; /************************************************************************ * FUNCTION DECLARATIONS ************************************************************************/ /* ATTRIBUTE/GROUP FUNCTIONS */ extern int milist_start(mihandle_t vol, const char *path, int flags, milisthandle_t *handle); extern int milist_attr_next(mihandle_t vol, milisthandle_t handle, char *path, int maxpath, char *name, int maxname); extern int milist_finish(milisthandle_t handle); extern int milist_grp_next(milisthandle_t handle, char *path, int maxpath); extern int micreate_group(mihandle_t vol, const char *path, const char *name); extern int midelete_attr(mihandle_t vol, const char *path, const char *name); extern int midelete_group(mihandle_t vol, const char *path, const char *name); extern int miget_attr_length(mihandle_t vol, const char *path, const char *name, int *length); extern int miget_attr_type(mihandle_t vol, const char *path, const char *name, mitype_t *data_type); extern int micopy_attr(mihandle_t vol, const char *path, mihandle_t new_vol); extern int miget_attr_values(mihandle_t vol, mitype_t data_type, const char *path, const char *name, int length, void *values); extern int miset_attr_values(mihandle_t vol, mitype_t data_type, const char *path, const char *name, int length, const void *values); extern int miadd_history_attr(mihandle_t vol, int length, const void *values); /* FREE FUNCTIONS */ extern int mifree_name(char *name_ptr); extern int mifree_names(char **name_pptr); /* DATA TYPE/SPACE FUNCTIONS */ extern int miget_data_class(mihandle_t vol, miclass_t *volume_class); extern int miget_data_type(mihandle_t vol, mitype_t *volume_data_type); extern int miget_data_type_size(mihandle_t vol, misize_t *voxel_size); extern int miget_space_name(mihandle_t vol, char **name); extern int miset_space_name(mihandle_t vol, const char *name); /* DIMENSION FUNCTIONS */ extern int miget_volume_from_dimension(midimhandle_t dimension, mihandle_t *volume); extern int micopy_dimension(midimhandle_t dim_ptr, midimhandle_t *new_dim_ptr); extern int micreate_dimension(const char *name, midimclass_t dimclass, midimattr_t attr, unsigned int length, midimhandle_t *new_dim_ptr); extern int mifree_dimension_handle(midimhandle_t dim_ptr); extern int miget_volume_dimensions(mihandle_t volume, midimclass_t dimclass, midimattr_t attr, miorder_t order, int array_length, midimhandle_t dimensions[]); extern int miset_apparent_dimension_order(mihandle_t volume, int array_length, midimhandle_t dimensions[]); extern int miset_apparent_dimension_order_by_name(mihandle_t volume, int array_length, char **names); extern int miset_apparent_record_dimension_flag(mihandle_t volume, int record_flag); extern int miget_dimension_apparent_voxel_order(midimhandle_t dimension, miflipping_t *file_order, miflipping_t *sign); extern int miset_dimension_apparent_voxel_order(midimhandle_t dimension, miflipping_t flipping_order); extern int miget_dimension_class(midimhandle_t dimension, midimclass_t *dimclass); extern int miset_dimension_class(midimhandle_t dimension, midimclass_t dimclass); extern int miget_dimension_cosines(midimhandle_t dimension, double direction_cosines[3]); extern int miset_dimension_cosines(midimhandle_t dimension, const double direction_cosines[3]); extern int miset_dimension_description(midimhandle_t dimension, const char *comments); extern int miget_dimension_description(midimhandle_t dimension, char **comments_ptr); extern int miget_dimension_name(midimhandle_t dimension, char **name_ptr); extern int miset_dimension_name(midimhandle_t dimension, const char *name); extern int miget_dimension_offsets(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, double offsets[]); extern int miset_dimension_offsets(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, const double offsets[]); extern int miget_dimension_sampling_flag(midimhandle_t dimension, miboolean_t *sampling_flag); extern int miset_dimension_sampling_flag(midimhandle_t dimension, miboolean_t sampling_flag); extern int miget_dimension_separation(midimhandle_t dimension, mivoxel_order_t voxel_order, double *separation_ptr); extern int miset_dimension_separation(midimhandle_t dimension, double separation); extern int miget_dimension_separations(const midimhandle_t dimensions[], mivoxel_order_t voxel_order, int array_length, double separations[]); extern int miset_dimension_separations(const midimhandle_t dimensions[], int array_length, const double separations[]); extern int miget_dimension_size(midimhandle_t dimension, unsigned int *size_ptr); extern int miset_dimension_size(midimhandle_t dimension, unsigned int size); extern int miget_dimension_sizes(const midimhandle_t dimensions[], int array_length, unsigned int sizes[]); extern int miget_dimension_start(midimhandle_t dimension, mivoxel_order_t voxel_order, double *start_ptr); extern int miset_dimension_start(midimhandle_t dimension, double start_ptr); extern int miget_dimension_starts(const midimhandle_t dimensions[], mivoxel_order_t voxel_order, int array_length, double starts[]); extern int miset_dimension_starts(const midimhandle_t dimensions[], int array_length, const double starts[]); extern int miget_dimension_units(midimhandle_t dimension, char **units_ptr); extern int miset_dimension_units(midimhandle_t dimension, const char *units); extern int miget_dimension_width(midimhandle_t dimension, double *width_ptr); extern int miset_dimension_width(midimhandle_t dimension, double width_ptr); extern int miget_dimension_widths(midimhandle_t dimension, mivoxel_order_t voxel_order, unsigned long array_length, unsigned long start_position, double widths[]); extern int miset_dimension_widths(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, const double widths[]); /* VOLUME FUNCTIONS */ extern int micreate_volume(const char *filename, int number_of_dimensions, midimhandle_t dimensions[], mitype_t volume_type, miclass_t volume_class, mivolumeprops_t create_props, mihandle_t *volume); extern int micreate_volume_image(mihandle_t volume); extern int miget_volume_dimension_count(mihandle_t volume, midimclass_t dimclass, midimattr_t attr, int *number_of_dimensions); extern int miget_volume_voxel_count(mihandle_t volume, int *number_of_voxels); extern int miopen_volume(const char *filename, int mode, mihandle_t *volume); extern int miclose_volume(mihandle_t volume); extern int miget_slice_scaling_flag(mihandle_t volume, miboolean_t *slice_scaling_flag); extern int miset_slice_scaling_flag(mihandle_t volume, miboolean_t slice_scaling_flag); /* VOLUME PROPERTIES FUNCTIONS */ extern int minew_volume_props(mivolumeprops_t *props); extern int mifree_volume_props(mivolumeprops_t props); extern int miget_volume_props(mihandle_t vol, mivolumeprops_t *props); extern int miset_props_multi_resolution(mivolumeprops_t props, miboolean_t enable_flag, int depth); extern int miget_props_multi_resolution(mivolumeprops_t props, miboolean_t *enable_flag, int *depth); extern int miselect_resolution(mihandle_t volume, int depth); extern int miflush_from_resolution(mihandle_t volume, int depth); extern int miset_props_compression_type(mivolumeprops_t props, micompression_t compression_type); extern int miget_props_compression_type(mivolumeprops_t props, micompression_t *compression_type); extern int miset_props_zlib_compression(mivolumeprops_t props, int zlib_level); extern int miget_props_zlib_compression(mivolumeprops_t props, int *zlib_level); extern int miset_props_blocking(mivolumeprops_t props, int edge_count, const int *edge_lengths); extern int miget_props_blocking(mivolumeprops_t props, int *edge_count, int *edge_lengths, int max_lengths); extern int miset_props_record(mivolumeprops_t props, long record_length, char *record_name); extern int miset_props_template(mivolumeprops_t props, int template_flag); /* SLICE/VOLUME SCALE FUNCTIONS */ extern int miget_slice_max(mihandle_t volume, const unsigned long start_positions[], int array_length, double *slice_max); extern int miset_slice_max(mihandle_t volume, const unsigned long start_positions[], int array_length, double slice_max); extern int miget_slice_min(mihandle_t volume, const unsigned long start_positions[], int array_length, double *slice_min); extern int miset_slice_min(mihandle_t volume, const unsigned long start_positions[], int array_length, double slice_min); extern int miget_slice_range(mihandle_t volume, const unsigned long start_positions[], int array_length, double *slice_max, double *slice_min); extern int miset_slice_range(mihandle_t volume, const unsigned long start_positions[], int array_length, double slice_max, double slice_min); extern int miget_volume_max(mihandle_t volume, double *slice_max); extern int miset_volume_max(mihandle_t volume, double slice_max); extern int miget_volume_min(mihandle_t volume, double *slice_min); extern int miset_volume_min(mihandle_t volume, double slice_min); extern int miget_volume_range(mihandle_t volume, double *slice_max, double *slice_min); extern int miset_volume_range(mihandle_t volume, double slice_max, double slice_min); /* HYPERSLAB FUNCTIONS */ extern int miget_hyperslab_size(mitype_t volume_data_type, int n_dimensions, const unsigned long count[], misize_t *size_ptr); extern int miget_hyperslab_normalized(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], double min, double max, void *buffer); extern int miget_hyperslab_with_icv(mihandle_t volume, int icv, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer); extern int miset_hyperslab_with_icv(mihandle_t volume, int icv, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer); extern int miget_real_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer); extern int miset_real_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer); extern int miget_voxel_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer); extern int miset_voxel_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer); /* CONVERT FUNCTIONS */ extern int miconvert_real_to_voxel(mihandle_t volume, const unsigned long coords[], int ncoords, double real_value, double *voxel_value_ptr); extern int miconvert_voxel_to_real(mihandle_t volume, const unsigned long coords[], int ncoords, double voxel_value, double *real_value_ptr); extern int miconvert_voxel_to_world(mihandle_t volume, const double voxel[], double world[]); extern int miconvert_world_to_voxel(mihandle_t volume, const double world[], double voxel[]); extern int miget_real_value(mihandle_t volume, const unsigned long coords[], int ndims, double *value_ptr); extern int miset_real_value(mihandle_t volume, const unsigned long coords[], int ndims, double value); extern int miget_voxel_value(mihandle_t volume, const unsigned long coords[], int ndims, double *voxel_ptr); extern int miset_voxel_value(mihandle_t volume, const unsigned long coords[], int ndims, double voxel); extern int miget_volume_real_range(mihandle_t volume, double real_range[2]); extern int miset_world_origin(mihandle_t volume, double origin[MI2_3D]); /* VALID functions */ extern int miget_volume_valid_max(mihandle_t volume, double *valid_max); extern int miset_volume_valid_max(mihandle_t volume, double valid_max); extern int miget_volume_valid_min(mihandle_t volume, double *valid_min); extern int miset_volume_valid_min(mihandle_t volume, double valid_min); extern int miget_volume_valid_range(mihandle_t volume, double *valid_max, double *valid_min); extern int miset_volume_valid_range(mihandle_t volume, double valid_max, double valid_min); /* RECORD functions */ extern int miget_record_name(mihandle_t volume, char **name); extern int miget_record_length(mihandle_t volume, int *length); extern int miget_record_field_name(mihandle_t volume, int index, char **name); extern int miset_record_field_name(mihandle_t volume, int index, const char *name); /* LABEL functions */ extern int midefine_label(mihandle_t volume, int value, const char *name); extern int miget_label_name(mihandle_t volume, int value, char **name); extern int miget_label_value(mihandle_t volume, const char *name, int *value); extern int miget_number_of_defined_labels(mihandle_t volume, int *number_of_labels); extern int miget_label_value_by_index(mihandle_t volume, int idx, int *value); #ifdef __cplusplus } #endif /* __cplusplus defined */ #endif /* _MINC2_H_ */ minc-2.2.00/libsrc2/minc2_private.h0000644000265600003100000001533112030075003013703 00000000000000/** \internal * \file minc2_private.h * \brief MINC 2.0 private constants, types, and functions. */ /** The root of all MINC 2.0 objects in the HDF5 hierarchy. */ #define MI_ROOT_PATH "/minc-2.0" #define MI_ROOT_COMMENT "Root of the MINC 2.0 data hierarchy" #define MI_DIMAGE_PATH "image" #define MI_INFO_NAME "info" #define MI_INFO_COMMENT "Group holding directly accessible attributes" #define MI_DIMENSIONS_PATH "dimensions" #define MI_DIMS_COMMENT "Group holding dimension variables" /** The fixed path to the full-resolution image data. */ #define MI_IMAGE_PATH MI_ROOT_PATH "/" MI_DIMAGE_PATH /** The fixed path to the full-resolution image data. */ #define MI_FULLIMAGE_PATH MI_IMAGE_PATH "/0" /** The fixed path to the dimension */ #define MI_FULLDIMENSIONS_PATH MI_ROOT_PATH "/dimensions" /** Size of a linear transform */ #define MI2_LIN_XFM_SIZE 4 /** Standard linear transform, a 4x4 matrix. */ typedef double mi_lin_xfm_t[MI2_LIN_XFM_SIZE][MI2_LIN_XFM_SIZE]; #ifdef _WIN32 typedef __int64 mi_i64_t; #else //_WIN32 typedef long long mi_i64_t; #endif //_WIN32 /** The fixed path to the dimension */ #define MI_FULLDIMENSIONS_PATH MI_ROOT_PATH "/dimensions" /** \internal * Volume properties */ struct mivolprops { miboolean_t enable_flag; /* enable multi-res */ int depth; /* multi-res depth */ micompression_t compression_type; int zlib_level; int edge_count; /* how many chunks */ int *edge_lengths; /* size of each chunk */ int max_lengths; long record_length; char *record_name; int template_flag; }; /** \internal * Dimension handle */ struct midimension { midimattr_t attr; /* Dimension attributes */ midimclass_t class; /* Dimension class */ double direction_cosines[3]; /* Direction cosines */ miflipping_t flipping_order; char *name; /* Dimension name */ double *offsets; /* Offsets (if irregular) */ double step; /* Step size */ unsigned int length; /* Length */ double start; /* Start value */ char *units; /* Units string */ double width; /* Sample width (if regular) */ double *widths; /* Widths (if irregular) */ char *comments; /* Comment string */ mihandle_t volume_handle; /* Handle of associated volume */ short world_index; /* -1, MI2_X, MI2_Y, or MI2_Z */ }; /** \internal * Volume handle */ struct mivolume { hid_t hdf_id; miboolean_t has_slice_scaling; int number_of_dims; midimhandle_t *dim_handles; /* file order of dimensions */ int *dim_indices; /* apparent order of dimensions */ mitype_t volume_type; miclass_t volume_class; mivolumeprops_t create_props; double valid_min; /* Volume-wide valid min */ double valid_max; /* Volume-wide valid max */ mi_lin_xfm_t v2w_transform; /* Voxel-to-world transform */ mi_lin_xfm_t w2v_transform; /* World-to-voxel transform (inverse) */ int selected_resolution; /* The current resolution (0-N) */ int mode; /* Open mode */ hid_t ftype_id; /* File type ID of image. */ hid_t mtype_id; /* Memory type ID of image. */ hid_t plist_id; /* Image property list */ hid_t image_id; /* Dataset for image */ hid_t imax_id; /* Dataset for image-max */ hid_t imin_id; /* Dataset for image-min */ double scale_min; /* Global minimum */ double scale_max; /* Global maximum */ miboolean_t is_dirty; /* TRUE if data has been modified. */ }; /** * \internal * "semi-private" functions. ****************************************************************************/ /* From m2util.c */ extern hid_t midescend_path(hid_t file_id, const char *path); extern hid_t mitype_to_hdftype(mitype_t, int); extern int mitype_to_nctype(mitype_t, int *is_signed); extern int miget_attribute(mihandle_t volume, const char *varpath, const char *attname, mitype_t data_type, int maxvals, void *values); extern int miset_attr_at_loc(hid_t hdf_loc, const char *attname, mitype_t data_type, int maxvals, const void *values); extern int miset_attribute(mihandle_t volume, const char *varpath, const char *attname, mitype_t data_type, int maxvals, const void *values); extern void mifind_spatial_dims(int mincid, int space_to_dim[], int dim_to_space[]); extern void miget_voxel_to_world(mihandle_t volume, mi_lin_xfm_t voxel_to_world); extern void minormalize_vector(double vector[]); extern void mitransform_coord(double out_coord[], mi_lin_xfm_t transform, const double in_coord[]); extern int miinvert_transform(mi_lin_xfm_t transform, mi_lin_xfm_t inverse); extern void miinit(void); extern void miinit_enum(hid_t); extern int miget_scalar(hid_t loc_id, hid_t type_id, const char *path, void *data); extern int minc_create_thumbnail(mihandle_t volume, int grp); extern int minc_update_thumbnail(mihandle_t volume, hid_t loc_id, int igrp, int ogrp); extern int minc_update_thumbnails(mihandle_t volume); extern int scaled_maximal_pivoting_gaussian_elimination(int n, int row[], double **a, int n_values, double **solution ); extern int scaled_maximal_pivoting_gaussian_elimination_real(int n, double **coefs, int n_values, double **values ); extern double *alloc1d(int); extern double **alloc2d(int, int); extern void free2d(int, double **); extern int create_dataset(hid_t hdf_file, const char *path); extern int create_standard_dataset(hid_t hdf_file, const char *path); /* From hyper.c */ extern int mitranslate_hyperslab_origin(mihandle_t volume, const unsigned long start[], const unsigned long count[], hssize_t hdf_start[], hsize_t hdf_count[], int dir[]); /* From volume.c */ extern void misave_valid_range(mihandle_t volume); /* External */ #include "../libsrc/minc_private.h" minc-2.2.00/libsrc2/convert.c0000644000265600003100000004053012027132662012626 00000000000000/** \file convert.c * \brief MINC 2.0 Coordinate and Voxel Conversion Functions * \author Bert Vincent * * Functions to convert "real" valued data to and from "voxel" valued * data, and to convert coordinates between "voxel" and "world" systems. */ /** * \defgroup mi2Cvt MINC 2.0 Coordinate and Voxel Conversion Functions */ #include #include #include #include #include "minc2.h" #include "minc2_private.h" /** Convert values between real (scaled) values and voxel (unscaled) * values. The voxel value is the unscaled value, and corresponds to the * value actually stored in the file, whereas the "real" value is the * value at the given location after scaling has been applied. * * The \a coords parameter specifies the location at which the * conversion is performed. This is needed because MINC supports * per-slice scaling, therefore a conversion performed at one location * may differ from that performed at another location. * * \param volume A volume handle * \param coords The position for which to perform the conversion. * \param ncoords The length of the \a coords array. * \param real_value The original real value, to be converted to voxel. * \param voxel_value_ptr A pointer to the converted voxel value. * \ingroup mi2Cvt */ int miconvert_real_to_voxel(mihandle_t volume, const unsigned long coords[], int ncoords, double real_value, double *voxel_value_ptr ) { int result = MI_NOERROR; double valid_min, valid_max; double slice_min, slice_max; double voxel_range, voxel_offset; double real_range, real_offset; /* get valid min/max, image min/max */ miget_volume_valid_range(volume, &valid_max, &valid_min); /* get image min/max */ miget_slice_range(volume, coords, ncoords, &slice_max, &slice_min); /* Calculate the actual conversion. */ voxel_offset = valid_min; real_offset = slice_min; voxel_range = valid_max - valid_min; real_range = slice_max - slice_min; real_value = (real_value - real_offset) / real_range; *voxel_value_ptr = (real_value * voxel_range) + voxel_offset; return (result); } /** Convert values between real (scaled) values and voxel (unscaled) * values. The voxel value is the unscaled value, and corresponds to the * value actually stored in the file, whereas the "real" value is the * value at the given location after scaling has been applied. * * The \a coords parameter specifies the location at which the * conversion is performed. This is needed because MINC supports * per-slice scaling, therefore a conversion performed at one location * may differ from that performed at another location. * * \param volume A volume handle * \param coords The position for which to perform the conversion. * \param ncoords The length of the \a coords array. * \param voxel_value The original voxel value, to be converted to real. * \param real_value_ptr A pointer to the converted real value. * \ingroup mi2Cvt */ int miconvert_voxel_to_real(mihandle_t volume, const unsigned long coords[], int ncoords, double voxel_value, double *real_value_ptr) { int result = MI_NOERROR; double valid_min, valid_max; double slice_min, slice_max; double voxel_range, voxel_offset; double real_range, real_offset; /* get valid min/max, image min/max */ miget_volume_valid_range(volume, &valid_max, &valid_min); /* get image min/max */ miget_slice_range(volume, coords, ncoords, &slice_max, &slice_min); /* Calculate the actual conversion. */ voxel_offset = valid_min; real_offset = slice_min; voxel_range = valid_max - valid_min; real_range = slice_max - slice_min; voxel_value = (voxel_value - voxel_offset) / voxel_range; *real_value_ptr = (voxel_value * real_range) + real_offset; return (result); } /** \internal */ static void mireorder_voxel_to_xyz(mihandle_t volume, const double voxel[], double xyz[MI2_3D], midimclass_t dimclass) { int i, axis; for (i = 0; i < volume->number_of_dims; i++) { midimhandle_t hdim = volume->dim_handles[i]; axis = hdim->world_index; if ( axis >= 0 && dimclass == hdim->class) { xyz[axis] = voxel[i]; } } } /** \internal */ static void mireorder_xyz_to_voxel(mihandle_t volume, const double xyz[MI2_3D], double voxel[], midimclass_t dimclass) { int i, axis; for (i = 0; i < volume->number_of_dims; i++) { midimhandle_t hdim = volume->dim_handles[i]; axis = hdim->world_index; if ( axis >= 0 && dimclass == hdim->class) { voxel[i] = xyz[axis]; } } } /** Converts an N-dimensional spatial position in voxel coordinates into a * 3-dimensional spatial position in world coordinates. * * The returned world coordinate vector is in a standardized order, with * the X position first (at index 0), followed by the Y and Z coordinates. * The voxel coordinate vector is in the native order appropriate to the * file. * * \ingroup mi2Cvt */ int miconvert_voxel_to_world(mihandle_t volume, const double voxel[], double world[MI2_3D]) { double temp[MI2_3D]; mireorder_voxel_to_xyz(volume, voxel, temp, MI_DIMCLASS_SPATIAL); mitransform_coord(world, volume->v2w_transform, temp); return (MI_NOERROR); } /** Converts a 3-dimensional spatial position in world coordinates into a * N-dimensional spatial position in voxel coordinates. * * The input world coordinate vector is in a standardized order, with * the X position first (at index 0), followed by the Y and Z coordinates. * The voxel coordinate vector is in the native order appropriate to the * file. * * \ingroup mi2Cvt */ int miconvert_world_to_voxel(mihandle_t volume, const double world[MI2_3D], double voxel[]) { double temp[MI2_3D]; int i; for (i = 0; i < volume->number_of_dims; i++) { voxel[i] = 0.0; } mitransform_coord(temp, volume->w2v_transform, world); mireorder_xyz_to_voxel(volume, temp, voxel, MI_DIMCLASS_SPATIAL); return (MI_NOERROR); } /** This function retrieves the real values of a position in the * MINC volume. The "real" value is the value at the given location * after scaling has been applied. * * \param volume A volume handle * \param coords The voxel position to retrieve * \param ndims The number of values in the \a coords array * \param value_ptr Pointer to a double variable to hold the returned value. * * \ingroup mi2Cvt */ int miget_real_value(mihandle_t volume, const unsigned long coords[], int ndims, double *value_ptr) { double voxel; int result; result = miget_voxel_value(volume, coords, ndims, &voxel); if (result != MI_NOERROR) { return (result); } miconvert_voxel_to_real(volume, coords, ndims, voxel, value_ptr); return (MI_NOERROR); } /** This function sets the real value of a position in the MINC * volume. The "real" value is the value at the given location * after scaling has been applied. * * \param volume A volume handle * \param coords The voxel position to retrieve * \param ndims The number of values in the \a coords array * \param value The value to save at this location. * * \ingroup mi2Cvt */ int miset_real_value(mihandle_t volume, const unsigned long coords[], int ndims, double value) { double voxel; if ((volume->mode & MI2_OPEN_RDWR) == 0) { return (MI_ERROR); } miconvert_real_to_voxel(volume, coords, ndims, value, &voxel); return (miset_voxel_value(volume, coords, ndims, voxel)); } /** * This function calculates the start values for the volume dimensions, * assuming that the spatial origin is relocated to the given world * coordinate. * * \ingroup mi2Cvt */ int miconvert_world_origin_to_start( mihandle_t volume, double world[3], double starts[3]) { return (MI_NOERROR); } /** * This function calculates the start values for the volume dimensions, * assuming that the spatial origin is relocated to the given world * coordinate. * * \ingroup mi2Cvt */ int miconvert_spatial_frequency_origin_to_start( mihandle_t volume, double world[3], double starts[3]) { return (MI_NOERROR); } static double dot_vectors(int n, double v1[], double v2[]) { int i; double d; d = 0.0; for ( i = 0; i < n; i++ ) { d += v1[i] * v2[i]; } return ( d ); } static int solve_linear_system( int n, double **coefs, double *values, double *solution) { int i; for ( i = 0; i < n; i++ ) { solution[i] = values[i]; } return (scaled_maximal_pivoting_gaussian_elimination_real(n, coefs, 1, &solution )); } static void convert_transform_origin_to_starts(mihandle_t hvol, double origin[], double starts[] ) { int axis; int which[MI2_3D]; int n_axes, i, j; double o_dot_c, c_dot_c; double x_dot_x, x_dot_y, x_dot_v, y_dot_y, y_dot_v, bottom; double **matrix, solution[MI2_3D]; for ( i = 0; i < hvol->number_of_dims; i++) { starts[i] = 0.0; } /*--- get the list of valid axes (which) */ n_axes = 0; for ( i = 0; i < hvol->number_of_dims; i++ ) { axis = hvol->dim_handles[i]->world_index; if ( axis >= 0 ) { which[axis] = i; ++n_axes; } } /*--- get the starts: computed differently for 1, 2, or 3 axes */ switch (n_axes) { case 1: o_dot_c = dot_vectors(MI2_3D, origin, hvol->dim_handles[which[0]]->direction_cosines); c_dot_c = dot_vectors(MI2_3D, hvol->dim_handles[which[0]]->direction_cosines, hvol->dim_handles[which[0]]->direction_cosines); if ( c_dot_c != 0.0 ) { starts[which[0]] = o_dot_c / c_dot_c; } break; case 2: x_dot_x = dot_vectors(MI2_3D, hvol->dim_handles[which[0]]->direction_cosines, hvol->dim_handles[which[0]]->direction_cosines ); x_dot_v = dot_vectors(MI2_3D, hvol->dim_handles[which[0]]->direction_cosines, origin ); x_dot_y = dot_vectors(MI2_3D, hvol->dim_handles[which[0]]->direction_cosines, hvol->dim_handles[which[1]]->direction_cosines ); y_dot_y = dot_vectors(MI2_3D, hvol->dim_handles[which[1]]->direction_cosines, hvol->dim_handles[which[1]]->direction_cosines ); y_dot_v = dot_vectors(MI2_3D, hvol->dim_handles[which[1]]->direction_cosines, origin ); bottom = x_dot_x * y_dot_y - x_dot_y * x_dot_y; if ( bottom != 0.0 ) { starts[which[0]] = (x_dot_v * y_dot_y - x_dot_y * y_dot_v) / bottom; starts[which[1]] = (y_dot_v * x_dot_x - x_dot_y * x_dot_v) / bottom; } break; case 3: /*--- this is the usual case, solve the equations to find what starts give the desired origin */ matrix = alloc2d(MI2_3D, MI2_3D); for ( i = 0; i < MI2_3D; i++) { for ( j = 0; j < hvol->number_of_dims; j++ ) { matrix[i][j] = hvol->dim_handles[j]->direction_cosines[i]; } } if ( solve_linear_system( MI2_3D, matrix, origin, solution ) ) { starts[which[0]] = solution[0]; starts[which[1]] = solution[1]; starts[which[2]] = solution[2]; } free2d(MI2_3D, matrix); break; } } /** * This function sets the world coordinates of the point (0,0,0) in voxel * coordinates. This changes the constant offset of the two coordinate * systems. * * \ingroup mi2Cvt */ int miset_world_origin(mihandle_t volume, /**< A volume handle */ double world[MI2_3D]) /**< The world coordinates of voxel origin */ { double starts[MI2_3D]; int i; convert_transform_origin_to_starts(volume, world, starts); for (i = 0; i < volume->number_of_dims; i++) { midimhandle_t hdim = volume->dim_handles[i]; if (hdim->class == MI_DIMCLASS_SPATIAL || hdim->class == MI_DIMCLASS_SFREQUENCY) { hdim->start = starts[hdim->world_index]; } } /* Get the voxel to world transform for the volume */ miget_voxel_to_world(volume, volume->v2w_transform); /* Calculate the inverse transform */ miinvert_transform(volume->v2w_transform, volume->w2v_transform); return (MI_NOERROR); } /** * This function sets the world coordinates of the point (0,0,0) in voxel * coordinates. This changes the constant offset of the two coordinate * systems. * * \ingroup mi2Cvt */ int miset_spatial_frequency_origin(mihandle_t volume, double world[3]) { if ((volume->mode & MI2_OPEN_RDWR) == 0) { return (MI_ERROR); } return (MI_NOERROR); } /** This function retrieves the voxel values of a position in the * MINC volume. The voxel value is the unscaled value, and corresponds * to the value actually stored in the file. * * \ingroup mi2Cvt */ int miget_voxel_value(mihandle_t volume, const unsigned long coords[], int ndims, double *voxel_ptr) { int result; unsigned long count[MI2_MAX_VAR_DIMS]; int i; for (i = 0; i < volume->number_of_dims; i++) { count[i] = 1; } result = miget_voxel_value_hyperslab(volume, MI_TYPE_DOUBLE, coords, count, voxel_ptr); return (result); } /** This function sets the voxel value of a position in the MINC * volume. The voxel value is the unscaled value, and corresponds to the * value actually stored in the file. * * \ingroup mi2Cvt */ int miset_voxel_value(mihandle_t volume, const unsigned long coords[], int ndims, double voxel) { int result; unsigned long count[MI2_MAX_VAR_DIMS]; int i; if ((volume->mode & MI2_OPEN_RDWR) == 0) { return (MI_ERROR); } for (i = 0; i < ndims; i++) { count[i] = 1; } result = miset_voxel_value_hyperslab(volume, MI_TYPE_DOUBLE, coords, count, &voxel); return (result); } /** Get the absolute minimum and maximum values of a volume. * * \ingroup mi2Cvt */ int miget_volume_real_range(mihandle_t volume, double real_range[]) { hid_t spc_id; int n; double *buffer; int i; /* First find the real minimum. */ spc_id = H5Dget_space(volume->imin_id); n = (int) H5Sget_simple_extent_npoints(spc_id); H5Sclose(spc_id); buffer = malloc(n * sizeof(double)); if (buffer == NULL) { return (MI_ERROR); } H5Dread(volume->imin_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); real_range[0] = FLT_MAX; for (i = 0; i < n; i++) { if (buffer[i] < real_range[0]) { real_range[0] = buffer[i]; } } free(buffer); /* Now find the maximum. */ spc_id = H5Dget_space(volume->imax_id); n = (int) H5Sget_simple_extent_npoints(spc_id); H5Sclose(spc_id); buffer = malloc(n * sizeof(double)); if (buffer == NULL) { return (MI_ERROR); } H5Dread(volume->imax_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); real_range[1] = FLT_MIN; for (i = 0; i < n; i++) { if (buffer[i] > real_range[1]) { real_range[1] = buffer[i]; } } free(buffer); return (MI_NOERROR); } minc-2.2.00/libsrc2/datatype.c0000644000265600003100000000463312027132662012765 00000000000000/** \file datatype.c * \brief MINC 2.0 data type/space functions ************************************************************************/ #include #include #include "minc2.h" #include "minc2_private.h" /** Return the data class of a volume (See miclass_t). */ int miget_data_class(mihandle_t volume, miclass_t *volume_class) { *volume_class = volume->volume_class; return (MI_NOERROR); } /** Return the data type of a volume (See mitype_t). */ int miget_data_type(mihandle_t volume, mitype_t *data_type) { *data_type = volume->volume_type; return (MI_NOERROR); } int miget_data_type_size(mihandle_t volume, misize_t *voxel_size) { hid_t grp_id; hid_t dset_id; hid_t type_id; hid_t file_id = volume->hdf_id; grp_id = midescend_path(file_id, MI_FULLIMAGE_PATH); if (grp_id < 0) { return (MI_ERROR); } dset_id = H5Dopen1(grp_id, "image"); if (dset_id < 0) { return (MI_ERROR); } type_id = H5Dget_type(dset_id); if (type_id < 0) { return (MI_ERROR); } *voxel_size = H5Tget_size(type_id); H5Tclose(type_id); H5Dclose(dset_id); H5Gclose(grp_id); return (MI_NOERROR); } int miget_space_name(mihandle_t volume, char **name) { int length; int result; int i; /* This is the order of the search for candidates for the space type. The reason for this is complication is to permit support for older-style MINC files which associate the spacetype with individual dimensions. */ static const char *path_list[] = { "/minc-2.0/info", "/minc-2.0/dimensions/xspace", "/minc-2.0/dimensions/yspace", "/minc-2.0/dimensions/zspace", NULL }; /* Search for the spacetype attribute in all available paths. */ for (i = 0; path_list[i] != 0; i++) { result = miget_attr_length(volume, path_list[i], "spacetype", &length); if (result == MI_NOERROR) { break; } } if (result != MI_NOERROR) { /* Nothing found, so use the default. */ length = strlen(MI_NATIVE); *name = malloc(length + 1); strcpy(*name, MI_NATIVE); } else { *name = malloc(length + 1); result = miget_attr_values(volume, MI_TYPE_STRING, path_list[i], "spacetype", length, *name); } return (result); } int miset_space_name(mihandle_t volume, const char *name) { return miset_attr_values(volume, MI_TYPE_STRING, "/minc-2.0/info", "spacetype", strlen(name), name); } minc-2.2.00/libsrc2/dimension.c0000644000265600003100000013246012030075003013124 00000000000000/** \file dimension.c * \brief MINC 2.0 "dimension" Functions * \author Leila Baghdadi * * Functions to create, destroy, and manipulate MINC dimension objects. * All functions return MI_NOERROR upon success and MI_ERROR on failure. ************************************************************************/ #define _GNU_SOURCE 1 #include #include #include "minc2.h" #include "minc2_private.h" /*! Figure out whether a dimension is associated with a volume. \param dimension The dimension handle. \param volume A pointer to the volume handle. * * This method returns the volume handle associated with a given dimension * or an error if the specified handle is not associated with the volume. * \ingroup mi2Dim */ int miget_volume_from_dimension(midimhandle_t dimension, mihandle_t *volume) { if (dimension == NULL) { return (MI_ERROR); } if (dimension->volume_handle != NULL) { *volume = dimension->volume_handle; } else { return (MI_ERROR); } return (MI_NOERROR); } /*! Create a copy of a given dimension. \param dim_ptr The dimension handle of the dimension to copy. \param new_dim_ptr A pointer to the dimension handle of the copied dimension. * * This method creates a copy of the specified dimension and returns the handle * to the copied dimension or error on failure. * \ingroup mi2Dim */ int micopy_dimension(midimhandle_t dim_ptr, midimhandle_t *new_dim_ptr) { int i; midimhandle_t handle; if (dim_ptr == NULL) { return (MI_ERROR); } /* Allocate storage for the structure */ handle = (midimhandle_t)malloc(sizeof(struct midimension)); if (handle == NULL) { return (MI_ERROR); } handle->attr = dim_ptr->attr; handle->class = dim_ptr->class; /* Copy direction cosines */ handle->direction_cosines[MI2_X] = dim_ptr->direction_cosines[0]; handle->direction_cosines[MI2_Y] = dim_ptr->direction_cosines[1]; handle->direction_cosines[MI2_Z] = dim_ptr->direction_cosines[2]; switch (dim_ptr->flipping_order) { case MI_FILE_ORDER: handle->flipping_order = MI_FILE_ORDER; break; case MI_COUNTER_FILE_ORDER: handle->flipping_order = MI_COUNTER_FILE_ORDER; break; default: return (MI_ERROR); } handle->name =strdup(dim_ptr->name); handle->length = dim_ptr->length; if (dim_ptr->offsets != NULL) { handle->offsets = (double *) malloc(dim_ptr->length*sizeof(double)); if (handle->offsets == NULL) { return (MI_ERROR); } for (i=0; i < dim_ptr->length; i++) { handle->offsets[i] = dim_ptr->offsets[i]; } } else { handle->offsets = NULL; } // check to make sure start and step are defined! if ( dim_ptr->step != 0) { handle->start = dim_ptr->start; handle->step = dim_ptr->step; } else { handle->step = 0.0; } //check to make sure string is not empty or null if (dim_ptr->units == NULL || *dim_ptr->units == '\0') { handle->units = strdup("mm"); } else { handle->units = strdup(dim_ptr->units); } handle->width = dim_ptr->width; if (dim_ptr->widths != NULL) { handle->widths = (double *) malloc(dim_ptr->length*sizeof(double)); if (handle->widths == NULL) { return (MI_ERROR); } for (i=0; i < dim_ptr->length; i++) { handle->widths[i] = dim_ptr->widths[i]; } } else { handle->widths = NULL; } if(dim_ptr->comments == NULL) { handle->comments = NULL; } else { handle->comments = strdup(dim_ptr->comments); } handle->volume_handle = dim_ptr->volume_handle; *new_dim_ptr = handle; return (MI_NOERROR); } /*! Define a new dimension in a MINC volume. \param name A pointer to the string specifying the dimension name. \param class The class of the dimension. \param attr The attribute of the dimension. \param length The size of the dimension. \param new_dim_ptr A pointer to the dimension handle. * * This function defines a dimension that can be used in the definition * of a new MINC volume (see the create_volume function). The name may * be an arbitrary string of up to 128 alphanumeric characters. Any of * the "standard" names retained from MINC 1.0 retain their default * behaviors: MIxspace, MIyspace, and MIzspace default to spatial * dimensions, and MItime default to be a time dimension. MItfrequency * is a temporal frequency axis, and MIxfrequency, MIyfrequency, and * MIzfrequency are spatial frequency axes. Any other name may be used. * * When initially defined, a regularly-sampled dimension will have a * "start" value of zero, and a "separation" or "step" value of 1.0. An * irregular dimension will be initialized with all offsets equal to * zero. * * The size of the dimension may range from 0 to 2^32, which should provide * enough range to represent detail on the order of 10 Angstroms in * typical medical imaging applications. * * For the detailed defintion of \a class and \a type refer to the MINC 2.0 API * definition. * \ingroup mi2Dim */ int micreate_dimension(const char *name, midimclass_t class, midimattr_t attr, unsigned int length, midimhandle_t *new_dim_ptr) { midimhandle_t handle; int i; /* Allocate space for the new dimension */ handle = (midimhandle_t)malloc(sizeof(struct midimension)); if (handle == NULL) { return (MI_ERROR); } /* Duplicate the dimension name */ handle->name = strdup(name); /* Set the dimension comment to NULL unless otherwise */ handle->comments = NULL; switch (class) { case MI_DIMCLASS_SPATIAL: handle->class = MI_DIMCLASS_SPATIAL; if (strcmp(name, MIxspace) == 0) { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; handle->comments = strdup("X increases from patient left to right"); } else if (strcmp(name, MIyspace) == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 1.0; handle->direction_cosines[MI2_Z] = 0.0; handle->comments = strdup("Y increases from patient posterior to anterior"); } else if (strcmp(name, MIzspace) == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 1.0; handle->comments = strdup("Z increases from patient inferior to superior"); } else { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; handle->comments = NULL; } break; case MI_DIMCLASS_TIME: handle->class = MI_DIMCLASS_TIME; break; case MI_DIMCLASS_SFREQUENCY: handle->class = MI_DIMCLASS_SFREQUENCY; if (strcmp(name, "xfrequency") == 0) { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; } else if (strcmp(name, "yfrequency") == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 1.0; handle->direction_cosines[MI2_Z] = 0.0; } else if (strcmp(name, "zfrequency") == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 1.0; } else { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; } break; case MI_DIMCLASS_TFREQUENCY: handle->class = MI_DIMCLASS_TFREQUENCY; break; case MI_DIMCLASS_USER: handle->class = MI_DIMCLASS_USER; break; case MI_DIMCLASS_RECORD: handle->class = MI_DIMCLASS_RECORD; break; case MI_DIMCLASS_ANY: default: return (MI_ERROR); } handle->offsets = NULL; handle->attr = attr; if (attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) { handle->widths = (double *) malloc(length *sizeof(double)); for (i=0; i< length; i++) { handle->widths[i] = 1.0; } } else { handle->widths = NULL; } // do not set start and step if vector_dimension present if (strcmp(name,"vector_dimension")) { handle->start = 0.0; handle->step = 1.0; } else{ handle->step = 0.0; } handle->width = 1.0; handle->flipping_order = MI_FILE_ORDER; if (class != MI_DIMCLASS_SPATIAL && class != MI_DIMCLASS_SFREQUENCY ) { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; } handle->length = length; handle->units = strdup("mm"); /* volume_handle is the only NULL value once the dimension is created. */ handle->volume_handle = NULL; *new_dim_ptr = handle; return (MI_NOERROR); } /*! Delete the dimension definition. \param dim_prt The dimension handle. * * Note: The original document stated that a dimension has to be * associated with a given volume before it can be deleted. This * feature was erased from the document and not considered here. * \ingroup mi2Dim */ int mifree_dimension_handle(midimhandle_t dim_ptr) { if (dim_ptr == NULL) { return (MI_ERROR); } if (dim_ptr->name != NULL) { free(dim_ptr->name); } if (dim_ptr->offsets != NULL) { free(dim_ptr->offsets); } if (dim_ptr->units != NULL) { free(dim_ptr->units); } if (dim_ptr->widths !=NULL) { free(dim_ptr->widths); } free(dim_ptr); return (MI_NOERROR); } /*! Retrieve the list of dimensions defined in a MINC volume, * with the same class \a class and attribute \a attr. \param volume The volume handle. \param class The class of the dimensions. \param attr The attribute of the dimensions. \param order The order of the dimension (file or apparent). \param array_length The number of dimension to be retrieved. \param dimensions An array of dimension handles to be retrieved. * * This function is used to retrieve an array of dimension handles for a * MINC volume. It will place the handles of the first "array_length" * dimensions into the "dimensions[]" array, returning only those dimension * whose characteristics match the "class" and "attr" parameters. * The miorder_t is an enumerated type flag which determines whether the * dimension order is determined by the file or by the apparent order set by * the user. This function will fail if the user has not set the apparent * dimension order by calling either of * (miset_apparent_dimension_order(_by_name)) * before calling this function with MI_DIMORDER_APPARENT flag. * \ingroup mi2Dim */ int miget_volume_dimensions(mihandle_t volume, midimclass_t class, midimattr_t attr, miorder_t order, int array_length, midimhandle_t dimensions[]) { hsize_t number_of_dims; int i=0, max_dims; int num_ret_dims = 0; if (volume == NULL) { return (MI_ERROR); } /* make sure the user has set the apparernt order before * calling this function with MI_DIMORDER_APPARENT */ if (order == MI_DIMORDER_APPARENT && volume->dim_indices == NULL) { return (MI_ERROR); } number_of_dims = volume->number_of_dims; if (array_length > number_of_dims) { max_dims = number_of_dims; } else { max_dims = array_length; } /* Go through each dimension separately and figure out which one has a matching class and attribute. if the user has set the apparent order use the dim_indices to search the dimensions otherwise use dim_handles */ for (i=0; i < max_dims; i++) { midimhandle_t hdim; if (order == MI_DIMORDER_APPARENT) { hdim = volume->dim_handles[volume->dim_indices[i]]; } else { hdim = volume->dim_handles[i]; } if (class == MI_DIMCLASS_ANY || class == hdim->class) { if (attr == MI_DIMATTR_ALL || hdim->attr == attr) { dimensions[num_ret_dims++] = hdim; } } } return (num_ret_dims); } /*! Set apparent dimension order, based on an array of dimensions. You * may also set the dimension order by the name of the dimension, see * miset_apparent_dimension_order_by_name(). \param volume The volume handle. \param array_length The number of dimensions to be sorted. \param dimensions An "ordered" array of dimension handles. * * This method sets an apparent dimension order. The user can sort the * dimensions in any desired order. If the user specifies fewer dimensions * than the existing ones, then they are assumed to be added to the last. * \ingroup mi2Dim */ int miset_apparent_dimension_order(mihandle_t volume, int array_length, midimhandle_t dimensions[]) { int diff; int i=0, j=0, k=0; if (volume == NULL || array_length <= 0 ) { return (MI_ERROR); } /* If array_length was more than the number of dimensions the rest of the given dimensions will be ignored. */ diff = volume->number_of_dims - array_length; if (diff < 0) { diff = 0; } /* Allocated space for dimensions indices, if not already done. */ if (volume->dim_indices == NULL){ volume->dim_indices = (int *)malloc(volume->number_of_dims*sizeof(int)); memset(volume->dim_indices, -1, sizeof(volume->number_of_dims)); } if (diff > 0) { while(i < volume->number_of_dims && k < diff) { for(j=0; j < array_length; j++) { if(volume->dim_handles[i] == dimensions[j]) { break; } } if ( j == array_length) { volume->dim_indices[k] = i; k++; } i++; } } for (i=0; i < volume->number_of_dims; i++) { for (j=0; j < array_length; j++) { if (volume->dim_handles[i] == dimensions[j]) { volume->dim_indices[j+diff] = i; break; } } } /* printf(" apparent dimension order \n"); for(i=0; i < volume->number_of_dims; i++) { printf(" %d ", volume->dim_indices[i]); } printf("\n"); */ return (MI_NOERROR); } /*! Set apparent dimension order by name. \param volume The volume handle. \param array_length The number of dimensions to be sorted. \param names An "ordered" array of dimension names. * * This method sets an apparent dimension order by dimension name. Note that * all dimension names must be different or an error occurs. * \ingroup mi2Dim */ int miset_apparent_dimension_order_by_name(mihandle_t volume, int array_length, char **names) { int diff; int i=0, j=0, k=0; if (volume == NULL) { return (MI_ERROR); } if (names == NULL || array_length <= 0) { /* Reset the dimension ordering */ if (volume->dim_indices != NULL) { free(volume->dim_indices); volume->dim_indices = NULL; } return (MI_NOERROR); } /* Note that all dimension names must be different or an error occurs. */ for (i = 0; i < array_length; i++) { for (j = i + 1; j < array_length; j++) { if (strcmp(names[i], names[j]) == 0) { return (MI_ERROR); } } } /* If array_length was more than the number of dimensions the rest of the given dimensions will be ignored. */ diff = volume->number_of_dims - array_length; if (diff < 0) { diff = 0; } /* Allocated space for dimensions indices, if not already done. */ if (volume->dim_indices == NULL) { volume->dim_indices = (int *)malloc(volume->number_of_dims*sizeof(int)); memset(volume->dim_indices, -1, sizeof(volume->number_of_dims)); } i=0; j=0; k=0; if (diff > 0) { while(i < volume->number_of_dims && k < diff) { for(j=0; j < array_length; j++) { if(strcmp(volume->dim_handles[i]->name, names[j])) { break; } } if (j == 3) { volume->dim_indices[k] = i; k++; } i++; } } for (i = 0; i < volume->number_of_dims; i++) { for (j = 0; j < array_length; j++) { if (!strcmp(volume->dim_handles[i]->name, names[j])) { volume->dim_indices[j+diff] = i; break; } } } return (MI_NOERROR); } /*! Set the record flag and add a record dimension to the volume * dimensions so the volume would appear to have an extra dimension. \param volume The volume handle. \param record_flag The flag to determine whether there exist a record dimension in the volume. * * This method causes a volume to appear to have a record dimension. The record * dimension will be set to uniform and flat (i.e., the volume will appear to have * an extra dimension) * \ingroup mi2Dim */ int miset_apparent_record_dimension_flag(mihandle_t volume, int record_flag) { midimhandle_t handle; if (volume == NULL) { return (MI_ERROR); } /* Allocate space for the dimension */ handle = (midimhandle_t)malloc(sizeof(struct midimension)); if (handle == NULL) { return (MI_ERROR); } handle->class = MI_DIMCLASS_RECORD; handle->volume_handle = volume; volume->dim_handles[volume->number_of_dims] = handle; /* Add one to the number of dimensions so the volume will appear to have (n+1) dimensions */ volume->number_of_dims++; record_flag = 1; return (MI_NOERROR); } /*! Get the apparent order of voxels (i.e., the order that voxel indices increase/decrease) \param dimension The dimension handle \param flipping_order The order of voxels. \param sign The sign of the step value. * * This method gets the apparent order of voxels for the specified dimension * and the sign of the step values. * \ingroup mi2Dim */ int miget_dimension_apparent_voxel_order(midimhandle_t dimension, miflipping_t *flipping_order, miflipping_t *sign) { if (dimension == NULL) { return (MI_ERROR); } switch (dimension->flipping_order) { case MI_FILE_ORDER: *flipping_order = MI_FILE_ORDER; if (dimension->step > 0) { *sign = MI_POSITIVE; } else { *sign = MI_NEGATIVE; } break; case MI_COUNTER_FILE_ORDER: *flipping_order = MI_COUNTER_FILE_ORDER; if (dimension->step > 0) { *sign = MI_NEGATIVE; } else { *sign = MI_POSITIVE; } break; case MI_POSITIVE: *sign = MI_POSITIVE; if (dimension->step > 0) { *flipping_order = MI_FILE_ORDER; } else { *flipping_order = MI_COUNTER_FILE_ORDER; } break; case MI_NEGATIVE: *sign = MI_NEGATIVE; if (dimension->step > 0) { *flipping_order = MI_COUNTER_FILE_ORDER; } else { *flipping_order = MI_FILE_ORDER; } break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Set the apparent order of voxels. \param dimension The dimension handle. \param flipping_order The order of voxels. * * This method sets the apparent order of voxels for the specified dimension. * For the detailed description of voxel order refer to the MINC 2.0 API definition. * \ingroup mi2Dim */ int miset_dimension_apparent_voxel_order(midimhandle_t dimension, miflipping_t flipping_order) { if (dimension == NULL) { return (MI_ERROR); } switch (flipping_order) { case MI_FILE_ORDER: dimension->flipping_order = MI_FILE_ORDER; break; case MI_COUNTER_FILE_ORDER: dimension->flipping_order = MI_COUNTER_FILE_ORDER; break; case MI_POSITIVE: dimension->flipping_order = MI_POSITIVE; break; case MI_NEGATIVE: dimension->flipping_order = MI_NEGATIVE; break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Get the class of a MINC dimension. \param dimension The dimension handle. \param class A pointer to the dimension class. * * The "class" of a MINC dimension defines the general type of a dimension, * whether it is a spatial dimension, a time dimension, or a frequency dimension * as transformed from either space or time. User-defined dimension are also * permitted, with no default handling assumed. Finally, a record can be specified * as a dimension. * \ingroup mi2Dim */ int miget_dimension_class(midimhandle_t dimension, midimclass_t *class) { if (dimension == NULL) { return (MI_ERROR); } switch (dimension->class) { case MI_DIMCLASS_ANY: *class = MI_DIMCLASS_ANY; break; case MI_DIMCLASS_SPATIAL: *class = MI_DIMCLASS_SPATIAL; break; case MI_DIMCLASS_TIME: *class = MI_DIMCLASS_TIME; break; case MI_DIMCLASS_SFREQUENCY: *class = MI_DIMCLASS_SFREQUENCY; break; case MI_DIMCLASS_TFREQUENCY: *class = MI_DIMCLASS_TFREQUENCY; break; case MI_DIMCLASS_USER: *class = MI_DIMCLASS_USER; break; case MI_DIMCLASS_RECORD: *class = MI_DIMCLASS_RECORD; break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Set the class of a MINC dimension. \param dimension The dimension handle. \param class The dimension class. * * Refer to miget_dimension_class(). * \ingroup mi2Dim */ int miset_dimension_class(midimhandle_t dimension, midimclass_t class) { if (dimension == NULL) { return (MI_ERROR); } switch (class) { case MI_DIMCLASS_ANY: dimension->class = MI_DIMCLASS_ANY; break; case MI_DIMCLASS_SPATIAL: dimension->class = MI_DIMCLASS_SPATIAL; break; case MI_DIMCLASS_TIME: dimension->class = MI_DIMCLASS_TIME; break; case MI_DIMCLASS_SFREQUENCY: dimension->class = MI_DIMCLASS_SFREQUENCY; break; case MI_DIMCLASS_TFREQUENCY: dimension->class = MI_DIMCLASS_TFREQUENCY; break; case MI_DIMCLASS_USER: dimension->class = MI_DIMCLASS_USER; break; case MI_DIMCLASS_RECORD: dimension->class = MI_DIMCLASS_RECORD; break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Get the direction cosine vector of a given SPATIAL dimension. \param dimension The dimension handle. \param direction_cosines An array of direction_cosines(i.e., vector determining the direction cosine). * * Spatial dimension in MINC volumes may be associated with a vector of direction * cosines which define the precise orientation of the axis relative to "true" * x, y, or z coordinates. * \ingroup mi2Dim */ int miget_dimension_cosines(midimhandle_t dimension, double direction_cosines[3]) { if (dimension == NULL || (dimension->class != MI_DIMCLASS_SPATIAL && dimension->class != MI_DIMCLASS_SFREQUENCY)){ return (MI_ERROR); } direction_cosines[0] = dimension->direction_cosines[0]; direction_cosines[1] = dimension->direction_cosines[1]; direction_cosines[2] = dimension->direction_cosines[2]; return (MI_NOERROR); } /*! Set the direction cosine vector for a given SPATIAL dimension. \param dimension The dimension handle. \param direction_cosines An array of direction_cosines(i.e., vector determining the direction cosine). * * Refer to miget_dimension_cosines(). * \ingroup mi2Dim */ int miset_dimension_cosines(midimhandle_t dimension, const double direction_cosines[3]) { if (dimension == NULL || (dimension->class != MI_DIMCLASS_SPATIAL && dimension->class != MI_DIMCLASS_SFREQUENCY)) { return (MI_ERROR); } dimension->direction_cosines[0] = direction_cosines[0]; dimension->direction_cosines[1] = direction_cosines[1]; dimension->direction_cosines[2] = direction_cosines[2]; return (MI_NOERROR); } /*! Get the comments attribute for a given dimension. \param dimension The dimension handle. \param comments_ptr A string pointer for the comments. * * Get and Set the dimension description. Note that the spatial dimensions * (xspace, yspace, zspace) are initialized according to minc1 description. * All other dimensions will have an empty description unless set by the user. * The string pointer returned in \a *comments_ptr must be freed by the caller. * \ingroup mi2Dim */ int miget_dimension_description(midimhandle_t dimension, char **comments_ptr) { if (dimension == NULL) { return (MI_ERROR); } *comments_ptr = strdup(dimension->comments); return (MI_NOERROR); } /*! Set the comments attribute for a given dimension. \param dimension The dimension handle. \param comments_ptr A pointer for the comments. * * Refer to miget_dimension_description(). * \ingroup mi2Dim */ int miset_dimension_description(midimhandle_t dimension, const char *comments) { if (dimension == NULL || comments == NULL) { return (MI_ERROR); } if ((strlen(comments) + 1) <= MI2_CHAR_LENGTH) { dimension->comments = strdup(comments); } else { return (MI_ERROR); } return (MI_NOERROR); } /*! Get the identifier (name) of a MINC dimension. \param dimension The dimension handle. \param name_ptr A string pointer for returning the dimension name. * * Retrieves the name of the given dimension. * \ingroup mi2Dim */ int miget_dimension_name(midimhandle_t dimension, char **name_ptr) { if (dimension == NULL) { return (MI_ERROR); } *name_ptr = strdup(dimension->name); return (MI_NOERROR); } /*! Set the identifier (name) of a given MINC dimension. \param dimension The dimension handle. \param name_ptr A pointer for the dimension name. * * Rename the given dimension. * \ingroup mi2Dim */ int miset_dimension_name(midimhandle_t dimension, const char *name) { if (dimension == NULL || name == NULL) { return (MI_ERROR); } if ((strlen(name) + 1) > MI2_CHAR_LENGTH) { return (MI_ERROR); } /* Free the existing dimension name. */ if (dimension->name != NULL) { free(dimension->name); } dimension->name = strdup(name); return (MI_NOERROR); } /*! Get the untransformed world coordinates of points along a MINC dimension. \param dimension The dimension handle. \param array_length The number of dimensions. \param start_position The position in which to retrieve the offsets. \param offsets The array of offsets to be returned. * * Get or Set the dimension offsets, that is, the * absolute world coordinates of each sampled point along the dimension. * * The caller may retrieve up to "array_length" values, starting at the * integer index "start_position". Thus an arbitrary contiguous subset * of the dimension's offsets may be retrieved or stored. An error is * returned if the "start_position" exceeds the total size of the * dimension. If the value of "start_position" is legal, but the sum of * "start_position" and "array_length" exceeds the size of the dimension, * the function will get or set offsets up to the size of the dimension. * Any extra positions in the offsets[] array will be ignored. * \ingroup mi2Dim */ int miget_dimension_offsets(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, double offsets[]) { unsigned long end_position; unsigned long i, j; if (dimension == NULL || start_position > dimension->length ) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { end_position = dimension->length; } else { end_position = start_position + array_length; } if (dimension->offsets == NULL) { for (i = start_position, j = 0; i < end_position ; i++, j++) { /* For regularly sampled dimensions, the step value * is added to each value to get the next value. */ offsets[j] = dimension->start + (i * dimension->step); } } else { for (i = start_position, j = 0; i < end_position ; i++, j++) { offsets[j] = dimension->offsets[i]; } } return (MI_NOERROR); } /*! Set the absolute world coordinates of points along a MINC dimension. \param dimension The dimension handle. \param array_length The number of dimensions. \param start_position The position in which to retrieve the offsets. \param offsets The array of offsets to be set. * * Refer to miget_dimension_offsets(). * \ingroup mi2Dim */ int miset_dimension_offsets(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, const double offsets[]) { unsigned long end_position; unsigned long i, j; /* Check to see whether the dimension is regularly sampled. */ if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) == 0 || start_position > dimension->length ) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { end_position = dimension->length; } else { end_position = start_position + array_length; } /* Allocate space for the offsets if not already done. */ if (dimension->offsets == NULL) { dimension->offsets = (double *) malloc(dimension->length * sizeof(double)); } for (i = start_position, j = 0; i < end_position; i++, j++) { dimension->offsets[i] = offsets[j] ; } return (MI_NOERROR); } /*! Get the sampling flag for a MINC dimension. \param dimension The dimension handle. \param sampling_flag The flag to determine regular/irregular sampling dimensions. * * This flag is true (non-zero) if the dimension is sampled at regular * intervals, and false if the dimension is sampled irregularly. * If a dimension has regular sampling, the miget_dimension_separation() * may be used to retrieve the sampling interval, and the * miget_dimension_start() may be used to retrieve the origin * value along the axis. * * If a dimension has irregular sampling, the miget_dimension_offsets() * may be used to retrieve the positions of each sample along that axis. * \ingroup mi2Dim */ int miget_dimension_sampling_flag(midimhandle_t dimension, miboolean_t *sampling_flag) { if (dimension == NULL) { return (MI_ERROR); } *sampling_flag = (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) != 0; return (MI_NOERROR); } /*! Set the sampling flag for a MINC dimension. \param dimension The dimension handle. \param sampling_flag The flag to determine regular/irregular sampling dimensions. * * Refer to miget_dimension_sampling_flag(). * \ingroup mi2Dim */ int miset_dimension_sampling_flag(midimhandle_t dimension, miboolean_t sampling_flag) { if (dimension == NULL) { return (MI_ERROR); } if (sampling_flag) { dimension->attr |= MI_DIMATTR_NOT_REGULARLY_SAMPLED; dimension->attr &= ~MI_DIMATTR_REGULARLY_SAMPLED; } else { dimension->attr &= ~MI_DIMATTR_NOT_REGULARLY_SAMPLED; dimension->attr |= MI_DIMATTR_REGULARLY_SAMPLED; } return (MI_NOERROR); } /*! Get the constant sampling interval (step) for a single dimension. \param dimension The dimension handle. \param voxel_order The order in which the voxel indices increase/decrease. \param separation_ptr The Pointer to the dimension sampling interval (step). * * Gets or sets the constant sampling interval defined on a regularly-sampled * dimension. While it is legal to call these functions for an irregularly- * sampled dimension, the values will be ignored. * \ingroup mi2Dim */ int miget_dimension_separation(midimhandle_t dimension, mivoxel_order_t voxel_order, double *separation_ptr) { if (dimension == NULL || dimension->step == 0) { return (MI_ERROR); } if (voxel_order == MI_ORDER_FILE) { *separation_ptr = dimension->step; } else { if (dimension->flipping_order == MI_COUNTER_FILE_ORDER) { *separation_ptr = -dimension->step; } else if (dimension->flipping_order == MI_POSITIVE) { if (dimension->step > 0) { *separation_ptr = dimension->step; } else { *separation_ptr = -dimension->step; } } else if (dimension->flipping_order == MI_NEGATIVE) { if (dimension->step < 0) { *separation_ptr = dimension->step; } else { *separation_ptr = -dimension->step; } } else { *separation_ptr = dimension->step; } } return (MI_NOERROR); } /*! Set the sampling interval (step) for a single dimension. \param dimension The dimension handle. \param separation The dimension sampling interval (step). * * Refer to miget_dimension_separation(). * \ingroup mi2Dim */ int miset_dimension_separation(midimhandle_t dimension, double separation) { /* file-order of voxels is assumed. */ if (dimension == NULL || dimension->step == 0) { return (MI_ERROR); } dimension->step = separation; /* If not explicitly set, the width will be assumed to be equal to the dimension's step size. */ //dimension->width = separation; return (MI_NOERROR); } /*! Get the sampling interval (STEP) for a list of dimensions. \param dimensions An array of dimension handles. \param voxel_order The order in which the voxel indices increase/decrease. \param array_length The number of dimensions in the dimesions array. \param separations An array of dimensions sampling intervals (step) values. * * Get or Set the scalar separation (sampling interval) * associated with each of the dimensions in the input "dimensions[]" * array. The "array_length" parameter specifies the size of both the * input and output arrays. While it is legal to call these functions for * an irregularly-sampled dimension, the values will be ignored. * \ingroup mi2Dim */ int miget_dimension_separations(const midimhandle_t dimensions[], mivoxel_order_t voxel_order, int array_length, double separations[]) { int i; for (i=0; i< array_length; i++) { miget_dimension_separation(dimensions[i], voxel_order, &separations[i]); } return (MI_NOERROR); } /*! Set the sampling interval (STEP) for a list of dimensions. \param dimensions An array of dimension handles. \param array_length The number of dimensions in the dimesions array. \param separations An array of dimensions sampling intervals (step) values. * * Refer to miget_dimension_separations(). * \ingroup mi2Dim */ int miset_dimension_separations(const midimhandle_t dimensions[], int array_length, const double separations[]) { int i; for (i=0; i< array_length; i++) { miset_dimension_separation(dimensions[i], separations[i]); } return (MI_NOERROR); } /*! Get the length of a MINC dimension. \param dimension The dimension handle. \param size_ptr A pointer to the dimension size. * * Get or Set the size (or length) of a MINC 2 dimension * object used in creating a new volume. The size of a dimension * associated with an existing volume cannot be changed. * \ingroup mi2Dim */ int miget_dimension_size(midimhandle_t dimension, unsigned int *size_ptr) { if (dimension == NULL) { return (MI_ERROR); } *size_ptr = dimension->length; return (MI_NOERROR); } /*! Set the length of a MINC dimension if not associated with a volume. \param dimension The dimension handle. \param size The size of the dimension. * * Refer to miget_dimension_size(). * \ingroup mi2Dim */ int miset_dimension_size(midimhandle_t dimension, unsigned int size) { /* Check whether the dimension is associated with a volume. */ if (dimension == NULL || dimension->volume_handle != NULL) { return (MI_ERROR); } dimension->length = size; return (MI_NOERROR); } /*! Retrieve the length of all dimensions in dimensions array. \param dimensions An array of dimension handles. \param array_length The number of dimensions in the dimensions array \param sizes An array of dimension sizes. * * This function will copy the lengths of each of the dimensions listed in the * "dimensions[]" array into the "sizes[]" array. The parameter "array_length" * specifies the length of both of the arrays. * \ingroup mi2Dim */ int miget_dimension_sizes(const midimhandle_t dimensions[], int array_length, unsigned int sizes[]) { int i; for ( i = 0; i < array_length; i++) { miget_dimension_size(dimensions[i], &sizes[i]); } return (MI_NOERROR); } /*! Get the start value of a MINC dimension. \param dimension The dimension handle. \param voxel_order The order in which the voxel indices increase/decrease. \param start_ptr A pointer to the start value. * * Get or set the origin of the dimension in world * coordinates. While a "start" value may be legally associated with any * dimension, it is considered meaningless when associated with an * irregularly sampled dimension. * \ingroup mi2Dim */ int miget_dimension_start(midimhandle_t dimension, mivoxel_order_t voxel_order, double *start_ptr) { /* If voxel_order is set to apparent file order (i.e., 1) start = start + step * (n-1) */ if (dimension == NULL || dimension->step == 0) { return (MI_ERROR); } if (voxel_order == MI_ORDER_FILE) { *start_ptr = dimension->start; } else { // L.B March 16/2011, Properly reflect voxel ordering if (dimension->flipping_order == MI_COUNTER_FILE_ORDER) { *start_ptr = dimension->start + (dimension->step * (dimension->length-1)); } else if (dimension->flipping_order == MI_POSITIVE) { if (dimension->step > 0) { *start_ptr = dimension->start; } else { *start_ptr = dimension->start + (dimension->step * (dimension->length-1)); } } else if (dimension->flipping_order == MI_NEGATIVE) { if (dimension->step < 0) { *start_ptr = dimension->start; } else { *start_ptr = dimension->start + (dimension->step * (dimension->length-1)); } } } return (MI_NOERROR); } /*! Set the start of a MINC dimension. \param dimension The dimension handle. \param start The start of the dimension. * * Refer to miget_dimension_start(). * \ingroup mi2Dim */ int miset_dimension_start(midimhandle_t dimension, double start) { if (dimension == NULL || dimension->step == 0) { return (MI_ERROR); } dimension->start = start; return (MI_NOERROR); } /*! Get the start values for MINC dimensions in dimensions array. \param dimensions The array of dimension handles. \param voxel_order The order in which the voxel indices increase/decrease. \param array_length The number of dimensions in the dimensions array. \param starts The array of dimension starts. * * Get or Set the start value for an array of * regularly-sampled dimensions. The start value defines the origin of * that dimension. While it is legal to call these functions for an * irregularly-sampled dimension, the values will be ignored. * \ingroup mi2Dim */ int miget_dimension_starts(const midimhandle_t dimensions[], mivoxel_order_t voxel_order, int array_length, double starts[]) { int i; for (i=0; i < array_length; i++) { miget_dimension_start(dimensions[i], voxel_order, &starts[i]); } return (MI_NOERROR); } /*! Set the start values for MINC dimensions in dimensions array. \param dimensions The array of dimension handles. \param array_length The number of dimensions in the dimensions array. \param starts The array of dimension starts. * * Refer to miget_dimension_starts(). * \ingroup mi2Dim */ int miset_dimension_starts(const midimhandle_t dimensions[], int array_length, const double starts[]) { int i; for (i=0; iunits); return (MI_NOERROR); } /*! Set the unit string for a MINC dimension. \param dimension The dimension handle. \param units A pointer to the dimension units. * * Set the units for an existing dimension. * The new string must be no greater than 128 characters in length, * including the trailing zero byte. * \ingroup mi2Dim */ int miset_dimension_units(midimhandle_t dimension, const char *units) { if (dimension == NULL || units == NULL) { return (MI_ERROR); } if (strlen(units) + 1 > MI2_CHAR_LENGTH) { return (MI_ERROR); } dimension->units = strdup(units); return (MI_NOERROR); } /*! Get A single full-width half-maximum value from a *regularly sampled dimension. \param dimension The dimension handle. \param width_ptr A pointer to the FWHM value. * * Get or Set the dimension width, that is, the * full-width half-maximum values of each sampled point along the dimension. * These functions are used to set a constant width for regularly-sampled * dimensions. * \ingroup mi2Dim */ int miget_dimension_width(midimhandle_t dimension, double *width_ptr) { if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) != 0) { return (MI_ERROR); } *width_ptr = dimension->width; return (MI_NOERROR); } /*! Set the A single full-width half-maximum value for a *regularly sampled dimension. \param dimension The dimension handle. \param width The FWHM value. * * Refer to miget_dimension_width(). * \ingroup mi2Dim */ int miset_dimension_width(midimhandle_t dimension, double width) { if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) != 0) { return (MI_ERROR); } /* Check to make sure width value is positive. */ if (width < 0) { dimension->width = -width; } else { dimension->width = width; } return (MI_NOERROR); } /*! Get the full-width half-maximum value for points along an *irregularly sampled dimension. \param dimension The dimension handle. \param voxel_order The order in which the voxel indices increase/decrease. \param array_length The number of width in the widths array. \param start_position Index for starting position. \param widths An array of width values to be retrieved. * * Get or Set the dimension widths, that is, the * full-width half-maximum values of each sampled point along the * dimension. * The caller may retrieve up to "array_length" values, starting at the * integer index "start_position". Thus an arbitrary contiguous subset * of the dimension's widths may be retrieved or stored. An error is * returned if the "start_position" exceeds the total size of the * dimension. If the value of "start_position" is legal, but the sum of * "start_position" and "array_length" exceeds the size of the dimension, * the function will get or set widths up to the size of the dimension. * Any extra positions in the widths[] array will be ignored. * \ingroup mi2Dim */ int miget_dimension_widths(midimhandle_t dimension, mivoxel_order_t voxel_order, unsigned long array_length, unsigned long start_position, double widths[]) { unsigned long diff; int i, j = 0; if (dimension == NULL || start_position > dimension->length) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { diff = dimension->length; } else { diff = array_length; } /* Allocate space for the widths array */ widths = (double *) malloc(diff*sizeof(double)); /* Check to see whether the dimension is regularly sampled. */ if (start_position == 0) { diff--; } if (dimension->widths == NULL) { for (i=start_position; i <= diff; i++) { widths[j] = dimension->width; j++; } } else { /* If the apparent order is requested, the widths are returned REVERSE (flip) order. */ if (voxel_order == 0) { for (i=start_position; i <= diff; i++) { widths[j] = dimension->widths[i]; j++; } } else { for (i=diff; i >= start_position; i--) { widths[j] = dimension->widths[i]; j++; } } } return (MI_NOERROR); } /*! Set the full-width half-maximum value for points along an *irregularly sampled dimension. \param dimension The dimension handle. \param array_length The number of width in the widths array. \param start_position Index for starting position. \param widths An array of width values to be set. * * Refer to miget_dimension_widths(). * \ingroup mi2Dim */ int miset_dimension_widths(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, const double widths[]) { unsigned long diff; int i, j=0; /* Check to see whether the dimension is regularly sampled. */ if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) == 0 || start_position > dimension->length) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { diff = dimension->length; } else { diff = array_length; } /* Allocate space for widths array if not already done */ if (dimension->widths == NULL) { dimension->widths = (double *) malloc(dimension->length*sizeof(double)); } if (start_position == 0) { diff--; } for (i=start_position; i <= diff; i++) { if (widths[i] < 0) { dimension->widths[i] = -1 * widths[j]; } else { dimension->widths[i] = widths[j]; } j++; } return (MI_NOERROR); } minc-2.2.00/libsrc2/free.c0000644000265600003100000000120312027132662012061 00000000000000/** \file free.c * \brief MINC 2.0 "free" functions ************************************************************************/ #include "minc2.h" #include /*! Free space allocated for string storage by a MINC function. \param name_ptr A pointer to the space to be freed. */ int mifree_name(char *name_ptr) { if (name_ptr == NULL) { return (MI_ERROR); } free(name_ptr); return (MI_NOERROR); } /*! not certain we really need this... */ int mifree_names(char **name_pptr) { if (name_pptr == NULL) { return (MI_ERROR); } while (*name_pptr != NULL) { free(*name_pptr++); } return (MI_NOERROR); } minc-2.2.00/libsrc2/grpattr.c0000644000265600003100000005112212030075003012615 00000000000000/** \file grpattr.c * \brief MINC 2.0 group/attribute functions * \author Bert Vincent and Leila Baghdadi * * Functions to manipulate attributes and groups. ************************************************************************/ #include #include #include "minc2.h" #include "minc2_private.h" #define MILIST_MAX_PATH 256 #define MILIST_RECURSE 0x0001 struct milistframe { struct milistframe *next; hid_t grp_id; int att_idx; int grp_idx; char relpath[MILIST_MAX_PATH]; }; struct milistdata { int flags; char *name_ptr; int name_len; struct milistframe *frame_ptr; /* recursive frame */ }; /*! Start listing the objects in a group. */ int milist_start(mihandle_t vol, const char *path, int flags, milisthandle_t *handle) { hid_t grp_id; char fullpath[256]; struct milistdata *data; struct milistframe *frame; strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /*grp_id = H5Gopen1(vol->hdf_id, fullpath); if (grp_id < 0) { return (MI_ERROR); }*/ grp_id = midescend_path(vol->hdf_id, fullpath); if (grp_id < 0) { return (MI_ERROR); } data = (struct milistdata *) malloc(sizeof (struct milistdata)); if (data == NULL) { return (MI_ERROR); } frame = (struct milistframe *) malloc(sizeof (struct milistframe)); frame->next = NULL; frame->grp_id = grp_id; frame->att_idx = 0; frame->grp_idx = 0; strcpy(frame->relpath, path); data->frame_ptr = frame; data->flags = flags; *handle = data; return (MI_NOERROR); } static int milist_recursion(milisthandle_t handle, char *path) { hid_t tmp_id; struct milistdata *data = (struct milistdata *) handle; herr_t r; struct milistframe *frame; for(;;){ H5E_BEGIN_TRY { r = H5Gget_objtype_by_idx(data->frame_ptr->grp_id, data->frame_ptr->grp_idx); } H5E_END_TRY; r--; if (r < 0) { /* End of this group, need to pop the frame. */ frame = data->frame_ptr->next; //H5Gclose(data->frame_ptr->grp_id); H5E_BEGIN_TRY { tmp_id = H5Gclose(data->frame_ptr->grp_id); if (tmp_id < 0) { tmp_id = H5Dclose(data->frame_ptr->grp_id); } } H5E_END_TRY; free(data->frame_ptr); data->frame_ptr = frame; if (frame == NULL) { return (MI_ERROR); } } else { data->frame_ptr->grp_idx++; /* If the object is a group, we need to recurse into it. */ r = 1; if (r == H5G_GROUP) { char tmp[256]; int l; H5Gget_objname_by_idx(data->frame_ptr->grp_id, data->frame_ptr->grp_idx - 1, tmp, sizeof(tmp)); frame = malloc(sizeof(struct milistframe)); if (frame == NULL) { return (MI_ERROR); } frame->grp_idx = 0; frame->att_idx = 0; frame->grp_id = H5Gopen1(data->frame_ptr->grp_id, tmp); strcpy(frame->relpath, data->frame_ptr->relpath); l = strlen(frame->relpath); if (l > 0 && frame->relpath[l - 1] != '/') { strcat(frame->relpath, "/"); } strcat(frame->relpath, tmp); /* Start working on the next frame. */ frame->next = data->frame_ptr; data->frame_ptr = frame; strncpy(path, data->frame_ptr->relpath, MILIST_MAX_PATH); break; /* Out of inner for(;;) */ } } } return (MI_NOERROR); } static herr_t milist_attr_op(hid_t loc_id, const char *attr_name, void *op_data) { struct milistdata *data = (struct milistdata *) op_data; strncpy(data->name_ptr, attr_name, data->name_len); return (1); } /*! Get attributes at a given path */ int milist_attr_next(mihandle_t vol, milisthandle_t handle, char *path, int maxpath, char *name, int maxname) { struct milistdata *data = (struct milistdata *) handle; herr_t r; data->name_ptr = name; data->name_len = maxname; for (;;) { H5E_BEGIN_TRY { r = H5Aiterate1(data->frame_ptr->grp_id, &data->frame_ptr->att_idx, milist_attr_op, data); } H5E_END_TRY; if (r > 0) { strncpy(path, data->frame_ptr->relpath, maxpath); return (MI_NOERROR); } else if (data->flags & MILIST_RECURSE) { r = milist_recursion(handle, path); if ( r == MI_ERROR) { return(MI_ERROR); } } else { return (MI_ERROR); } } return (MI_NOERROR); } /*! Finish listing attributes or groups */ int milist_finish(milisthandle_t handle) { hid_t tmp_id; struct milistdata *data = (struct milistdata *) handle; struct milistframe *frame; if (data == NULL) { return (MI_ERROR); } while ((frame = data->frame_ptr) != NULL) { data->frame_ptr = frame->next; //H5Gclose(frame->grp_id); H5E_BEGIN_TRY { tmp_id = H5Gclose(frame->grp_id); if (tmp_id < 0) { tmp_id = H5Dclose(frame->grp_id); } } H5E_END_TRY; free(frame); } free(data); return (MI_NOERROR); } static herr_t milist_grp_op(hid_t loc_id, const char *name, void *op_data) { struct milistdata *data = (struct milistdata *) op_data; H5G_stat_t statbuf; H5Gget_objinfo(loc_id,name, FALSE, &statbuf); if (statbuf.type == H5G_GROUP) { int l; l = strlen(data->frame_ptr->relpath); if (l > 0 && data->frame_ptr->relpath[l-1] != '/') { strcat(data->frame_ptr->relpath, "/"); } strcat(data->frame_ptr->relpath, name); } return(1); } /*! Get the group at given path */ int milist_grp_next(milisthandle_t handle, char *path, int maxpath) { struct milistdata *data = (struct milistdata *) handle; herr_t r; if (!(data->flags & MILIST_RECURSE)) { char fullpath[256]; char tmp[256]; strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); strncat(fullpath, data->frame_ptr->relpath, sizeof (fullpath) - strlen(fullpath)); strcpy(tmp, data->frame_ptr->relpath); H5E_BEGIN_TRY { r = H5Giterate(data->frame_ptr->grp_id,fullpath, &data->frame_ptr->grp_idx, milist_grp_op, data); } H5E_END_TRY; if ( r > 0 ) { strncpy(path, data->frame_ptr->relpath, maxpath); strncpy(data->frame_ptr->relpath, tmp, maxpath); return (MI_NOERROR); } else { return (MI_ERROR); } } else if (data->flags & MILIST_RECURSE) { r = milist_recursion(handle, path); if ( r == MI_ERROR) { return(MI_ERROR); } } else { return (MI_ERROR); } return (MI_NOERROR); } /*! Create a group at "path" using "name". */ int micreate_group(mihandle_t vol, const char *path, const char *name) { hid_t hdf_file; hid_t hdf_grp; hid_t hdf_new_grp; char fullpath[256]; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /* Search through the path, descending into each group encountered. */ hdf_grp = midescend_path(hdf_file, fullpath); if (hdf_grp < 0) { return (MI_ERROR); } H5E_BEGIN_TRY { /* See if the group already exists. If so, just return. */ hdf_new_grp = H5Gopen1(hdf_grp, name); if (hdf_new_grp >= 0) { H5Gclose(hdf_new_grp); return (MI_NOERROR); } /* Actually create the requested group. */ hdf_new_grp = H5Gcreate1(hdf_grp, name, 0); if (hdf_new_grp < 0) { return (MI_ERROR); } } H5E_END_TRY; /* Close the handles we created. */ H5Gclose(hdf_new_grp); H5Gclose(hdf_grp); return (MI_NOERROR); } /*! Delete the named attribute. */ int midelete_attr(mihandle_t vol, const char *path, const char *name) { hid_t tmp_id; hid_t hdf_file; hid_t hdf_grp; herr_t hdf_result; char fullpath[256]; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /* Search through the path, descending into each group encountered. */ hdf_grp = midescend_path(hdf_file, fullpath); if (hdf_grp < 0) { return (MI_ERROR); } /* Delete the attribute from the path. */ hdf_result = H5Adelete(hdf_grp, name); if (hdf_result < 0) { return (MI_ERROR); } /* Close the handles we created (PROPERLY!) */ H5E_BEGIN_TRY { tmp_id = H5Gclose(hdf_grp); if (tmp_id < 0) { tmp_id = H5Dclose(hdf_grp); } } H5E_END_TRY; return (MI_NOERROR); } /** Delete the subgroup \a name from the group \a path */ int midelete_group(mihandle_t vol, const char *path, const char *name) { hid_t hdf_file; hid_t hdf_grp; herr_t hdf_result; char fullpath[256]; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /* Search through the path, descending into each group encountered. */ hdf_grp = midescend_path(hdf_file, fullpath); if (hdf_grp < 0) { return (MI_ERROR); } H5E_BEGIN_TRY { /* Delete the group (or any object, really) from the path. */ hdf_result = H5Gunlink(hdf_grp, name); if (hdf_result < 0) { hdf_result = MI_ERROR; } else { hdf_result = MI_NOERROR; } } H5E_END_TRY; /* Close the handles we created. */ H5Gclose(hdf_grp); return (hdf_result); } /** Get the length of a attribute */ int miget_attr_length(mihandle_t vol, const char *path, const char *name, int *length) { hid_t tmp_id; hid_t hdf_file; hid_t hdf_grp; hid_t hdf_attr; hsize_t hdf_dims[1]; /* TODO: symbolic constant for "1" here? */ hid_t hdf_space; hid_t hdf_type; char fullpath[256]; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /* Search through the path, descending into each group encountered. */ hdf_grp = midescend_path(hdf_file, fullpath); if (hdf_grp < 0) { return (MI_ERROR); } hdf_attr = H5Aopen_name(hdf_grp, name); if (hdf_attr < 0) { return (MI_ERROR); } hdf_space = H5Aget_space(hdf_attr); if (hdf_space < 0) { return (MI_ERROR); } hdf_type = H5Aget_type(hdf_attr); if (hdf_type < 0) { return (MI_ERROR); } switch (H5Sget_simple_extent_ndims(hdf_space)) { case 0: /* Scalar */ /* String types need to return the length of the string. */ if (H5Tget_class(hdf_type) == H5T_STRING) { *length = H5Tget_size(hdf_type); } else { *length = 1; } break; case 1: H5Sget_simple_extent_dims(hdf_space, hdf_dims, NULL); *length = hdf_dims[0]; break; default: /* For now, we allow only scalars and vectors. No multidimensional * arrays for MINC 2.0 attributes. */ return (MI_ERROR); } H5Tclose(hdf_type); H5Sclose(hdf_space); H5Aclose(hdf_attr); H5E_BEGIN_TRY { tmp_id = H5Gclose(hdf_grp); if (tmp_id < 0) { tmp_id = H5Dclose(hdf_grp); } } H5E_END_TRY; return (MI_NOERROR); } /** Get the type of an attribute. */ int miget_attr_type(mihandle_t vol, const char *path, const char *name, mitype_t *data_type) { hid_t tmp_id; hid_t hdf_file; hid_t hdf_grp; hid_t hdf_attr; hid_t hdf_type; char fullpath[256]; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /* Search through the path, descending into each group encountered. */ hdf_grp = midescend_path(hdf_file, fullpath); if (hdf_grp < 0) { return (MI_ERROR); } hdf_attr = H5Aopen_name(hdf_grp, name); if (hdf_attr < 0) { return (MI_ERROR); } hdf_type = H5Aget_type(hdf_attr); switch (H5Tget_class(hdf_type)) { case H5T_FLOAT: if (H5Tget_size(hdf_type) == sizeof(float)) { *data_type = MI_TYPE_FLOAT; } else { *data_type = MI_TYPE_DOUBLE; } break; case H5T_STRING: *data_type = MI_TYPE_STRING; break; case H5T_INTEGER: *data_type = MI_TYPE_INT; break; default: return (MI_ERROR); } H5Tclose(hdf_type); H5Aclose(hdf_attr); H5E_BEGIN_TRY { tmp_id = H5Gclose(hdf_grp); if (tmp_id < 0) { tmp_id = H5Dclose(hdf_grp); } } H5E_END_TRY; return (MI_NOERROR); } /** Copy all attribute given a path */ int micopy_attr(mihandle_t vol, const char *path, mihandle_t new_vol) { milisthandle_t hlist; mitype_t data_type; char namebuf[256]; char pathbuf[256]; char valstr[128]; float valflt; long vallng; int r; int length; r = milist_start(vol, path, 1, &hlist); if (r == MI_NOERROR) { while (milist_attr_next(vol, hlist, pathbuf, sizeof(pathbuf), namebuf, sizeof(namebuf)) == MI_NOERROR) { miget_attr_type(vol,pathbuf, namebuf,&data_type); switch(data_type) { case MI_TYPE_STRING: miget_attr_length(vol,pathbuf,namebuf,&length); miget_attr_values(vol, MI_TYPE_STRING, pathbuf, namebuf, length, valstr); miset_attr_values(new_vol, MI_TYPE_STRING, pathbuf, namebuf, length, valstr); break; case MI_TYPE_FLOAT: miget_attr_values(vol, MI_TYPE_FLOAT, pathbuf, namebuf, 1, &valflt); miset_attr_values(new_vol, MI_TYPE_FLOAT, pathbuf, namebuf, 1, &valflt); break; case MI_TYPE_INT: miget_attr_values(vol, MI_TYPE_INT, pathbuf, namebuf, 1, &vallng); miset_attr_values(new_vol, MI_TYPE_INT, pathbuf, namebuf, 1, &vallng); break; default: return (MI_ERROR); } } } else { return (MI_ERROR); } milist_finish(hlist); return (MI_NOERROR); } /** Get the values of an attribute. */ int miget_attr_values(mihandle_t vol, mitype_t data_type, const char *path, const char *name, int length, void *values) { hid_t tmp_id; hid_t hdf_file; hid_t hdf_grp; hid_t mtyp_id; hid_t hdf_space; hid_t hdf_attr; char fullpath[256]; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } if (strcmp(name,"history")) { strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); } else { strncpy(fullpath, MI_ROOT_PATH "/" , sizeof (fullpath)); } if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /* Search through the path, descending into each group encountered. */ hdf_grp = midescend_path(hdf_file, fullpath); if (hdf_grp < 0) { return (MI_ERROR); } hdf_attr = H5Aopen_name(hdf_grp, name); if (hdf_attr < 0) { return (MI_ERROR); } switch (data_type) { case MI_TYPE_INT: mtyp_id = H5Tcopy(H5T_NATIVE_INT); break; case MI_TYPE_FLOAT: mtyp_id = H5Tcopy(H5T_NATIVE_FLOAT); break; case MI_TYPE_DOUBLE: mtyp_id = H5Tcopy(H5T_NATIVE_DOUBLE); break; case MI_TYPE_STRING: mtyp_id = H5Tcopy(H5T_C_S1); H5Tset_size(mtyp_id, length); break; default: return (MI_ERROR); } hdf_space = H5Aget_space(hdf_attr); if (hdf_space < 0) { return (MI_ERROR); } /* If we're retrieving a vector, make certain the length passed into this * function is sufficient. */ if (H5Sget_simple_extent_ndims(hdf_space) == 1) { hsize_t hdf_dims[1]; H5Sget_simple_extent_dims(hdf_space, hdf_dims, NULL); if (length < hdf_dims[0]) { return (MI_ERROR); } } H5Aread(hdf_attr, mtyp_id, values); H5Aclose(hdf_attr); H5Tclose(mtyp_id); H5Sclose(hdf_space); H5E_BEGIN_TRY { tmp_id = H5Gclose(hdf_grp); if (tmp_id < 0) { tmp_id = H5Dclose(hdf_grp); } } H5E_END_TRY; return (MI_NOERROR); } /** Set the values of an attribute. */ int miset_attr_values(mihandle_t vol, mitype_t data_type, const char *path, const char *name, int length, const void *values) { hid_t hdf_file; hid_t hdf_grp; int result; char fullpath[256]; hid_t tmp_id; char *std_name; char *pch; int i,slength; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } strncpy(fullpath, MI_ROOT_PATH "/" MI_INFO_NAME, sizeof (fullpath)); if (*path != '/') { strncat(fullpath, "/", sizeof (fullpath) - strlen(fullpath)); } strncat(fullpath, path, sizeof (fullpath) - strlen(fullpath)); /* find last occurance of '/' */ pch = strrchr(path,'/'); if(pch !=NULL) { slength = strlen(path) - (pch-path); std_name = malloc(slength); for (i=0; i < slength; i++) std_name[i] = path[pch-path+1+i]; std_name[slength]='\0'; } else { std_name = malloc(strlen(path) + 1); strcpy(std_name, path); } /* might need to create standard dataset first*/ if (!strcmp(std_name,"acquisition") || !strcmp(std_name,"patient") || !strcmp(std_name,"study") ) { H5E_BEGIN_TRY { tmp_id = H5Dopen1(hdf_file, fullpath); if (tmp_id < 0) { create_standard_dataset(hdf_file,std_name); } else { H5Dclose(tmp_id); } } H5E_END_TRY; } else { H5E_BEGIN_TRY { tmp_id = H5Dopen1(hdf_file, fullpath); if (tmp_id < 0) { create_dataset(hdf_file,std_name); } else { H5Dclose(tmp_id); } } H5E_END_TRY; } free(std_name); /* Search through the path, descending into each group encountered. */ hdf_grp = midescend_path(hdf_file, fullpath); if (hdf_grp < 0) { return (MI_ERROR); } result = miset_attr_at_loc(hdf_grp, name, data_type, length, values); if (result < 0) { return (MI_ERROR); } /* added the following instead H5Gclose(hdf_grp) */ H5E_BEGIN_TRY { tmp_id = H5Gclose(hdf_grp); if (tmp_id < 0) { tmp_id = H5Dclose(hdf_grp); } } H5E_END_TRY; return (MI_NOERROR); } int miadd_history_attr(mihandle_t vol, int length, const void *values) { int result; hid_t hdf_file; hid_t hdf_grp; hid_t tmp_id; /* Get a handle to the actual HDF file */ hdf_file = vol->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } hdf_grp = midescend_path(hdf_file, "/minc-2.0"); if (hdf_grp < 0) { return (MI_ERROR); } result = miset_attr_at_loc(hdf_grp, "history", MI_TYPE_STRING, length, values); if (result < 0) { return (MI_ERROR); } /* added the following instead H5Gclose(hdf_grp) */ H5E_BEGIN_TRY { tmp_id = H5Gclose(hdf_grp); if (tmp_id < 0) { tmp_id = H5Dclose(hdf_grp); } } H5E_END_TRY; return (MI_NOERROR); } minc-2.2.00/libsrc2/hyper.c0000644000265600003100000006014612030075003012267 00000000000000/** \file hyper.c * \brief MINC 2.0 Hyperslab Functions * \author Bert Vincent * * Functions to manipulate hyperslabs of volume image data. ************************************************************************/ #include #include #include "minc2.h" #include "minc2_private.h" #define MIRW_OP_READ 1 #define MIRW_OP_WRITE 2 typedef unsigned long mioffset_t; /** In-place array dimension restructuring. * * Based on Chris H.Q. Ding, "An Optimal Index Reshuffle Algorithm for * Multidimensional Arrays and its Applications for Parallel Architectures" * IEEE Transactions on Parallel and Distributed Systems, Vol.12, No.3, * March 2001, pp.306-315. * * I rewrote the algorithm in "C" an generalized it to N dimensions. * * Guaranteed to do the minimum number of memory moves, but requires * that we allocate a bitmap of nelem/8 bytes. The paper suggests * ways to eliminate the bitmap - I'll work on it. */ /** * Map a set of array coordinates to a linear offset in the array memory. */ static mioffset_t index_to_offset(int ndims, const unsigned long sizes[], const unsigned long index[]) { mioffset_t offset = index[0]; int i; for (i = 1; i < ndims; i++) { offset *= sizes[i]; offset += index[i]; } return (offset); } /** * Map a linear offset to a set of coordinates in a multidimensional array. */ static void offset_to_index(int ndims, const unsigned long sizes[], mioffset_t offset, unsigned long index[]) { int i; for (i = ndims - 1; i > 0; i--) { index[i] = offset % sizes[i]; offset /= sizes[i]; } index[0] = offset; } /* Trivial bitmap test & set. */ #define BIT_TST(bm, i) (bm[(i) / 8] & (1 << ((i) % 8))) #define BIT_SET(bm, i) (bm[(i) / 8] |= (1 << ((i) % 8))) /** The main restructuring code. */ MNCAPI void restructure_array(int ndims, /* Dimension count */ unsigned char *array, /* Raw data */ const unsigned long *lengths_perm, /* Permuted lengths */ int el_size, /* Element size, in bytes */ const int *map, /* Mapping array */ const int *dir) /* Direction array, in permuted order */ { unsigned long index[MI2_MAX_VAR_DIMS]; /* Raw indices */ unsigned long index_perm[MI2_MAX_VAR_DIMS]; /* Permuted indices */ unsigned long lengths[MI2_MAX_VAR_DIMS]; /* Raw (unpermuted) lengths */ unsigned char *temp; mioffset_t offset_start; mioffset_t offset_next; mioffset_t offset; unsigned char *bitmap; size_t total; int i; if ((temp = malloc(el_size)) == NULL) { return; } /** * Permute the lengths from their "output" configuration back into * their "raw" or native order: **/ for (i = 0; i < ndims; i++) { //lengths[i] = lengths_perm[map[i]]; lengths[map[i]] = lengths_perm[i]; } /** * Calculate the total size of the array, in elements. **/ total = 1; for (i = 0; i < ndims; i++) { total *= lengths[i]; } /** * Allocate a bitmap with enough space to hold one bit for each * element in the array. **/ bitmap = calloc((total + 8 - 1) / 8, 1); /* bit array */ if (bitmap == NULL) { return; } for (offset_start = 0; offset_start < total; offset_start++) { /** * Look for an unset bit - that's where we start the next * cycle. **/ if (!BIT_TST(bitmap, offset_start)) { /** * Found a cycle we have not yet performed. **/ offset_next = -1; /* Initialize. */ #ifdef DEBUG printf("%ld", offset_start); #endif /* DEBUG */ /** * Save the first element in this cycle. **/ memcpy(temp, array + (offset_start * el_size), el_size); /** * We've touched this location. **/ BIT_SET(bitmap, offset_start); offset = offset_start; /** * Do until the cycle repeats. **/ while (offset_next != offset_start) { /** * Compute the index from the offset and permuted length. **/ offset_to_index(ndims, lengths_perm, offset, index_perm); /** * Permute the index into the alternate arrangement. **/ for (i = 0; i < ndims; i++) { if (dir[i] < 0) { // index[i] = lengths[i] - index_perm[map[i]] - 1; index[map[i]] = lengths[map[i]] - index_perm[i] - 1; } else { //index[i] = index_perm[map[i]]; index[map[i]] = index_perm[i]; } } /** * Calculate the next offset from the permuted index. **/ offset_next = index_to_offset(ndims, lengths, index); #ifdef DEBUG if (offset_next >= total) { printf("Fatal - offset %ld out of bounds!\n", offset_next); printf("lengths %ld,%ld,%ld\n", lengths[0],lengths[1],lengths[2]); printf("index %ld,%ld,%ld\n", index_perm[0], index_perm[0], index_perm[2]); exit(-1); } #endif /** * If we are not at the end of the cycle... **/ if (offset_next != offset_start) { /** * Note that we've touched a new location. **/ BIT_SET(bitmap, offset_next); #ifdef DEBUG printf(" - %ld", offset_next); #endif /* DEBUG */ /** * Move from old to new location. **/ memcpy(array + (offset * el_size), array + (offset_next * el_size), el_size); /** * Advance offset to the next location in the cycle. **/ offset = offset_next; } } /** * Store the first value in the cycle, which we saved in * 'tmp', into the last offset in the cycle. **/ memcpy(array + (offset * el_size), temp, el_size); #ifdef DEBUG printf("\n"); #endif /* DEBUG */ } } free(bitmap); /* Get rid of the bitmap. */ free(temp); } /** Calculates and returns the number of bytes required to store the * hyperslab specified by the \a n_dimensions and the * \a count parameters. */ int miget_hyperslab_size(mitype_t volume_data_type, /**< Data type of a voxel. */ int n_dimensions, /**< Dimensionality */ const unsigned long count[], /**< Dimension lengths */ misize_t *size_ptr) /**< Returned byte count */ { int voxel_size; misize_t temp; int i; hid_t type_id; type_id = mitype_to_hdftype(volume_data_type, TRUE); if (type_id < 0) { return (MI_ERROR); } voxel_size = H5Tget_size(type_id); temp = 1; for (i = 0; i < n_dimensions; i++) { temp *= count[i]; } *size_ptr = (temp * voxel_size); H5Tclose(type_id); return (MI_NOERROR); } /** "semiprivate" function for translating coordinates. */ int mitranslate_hyperslab_origin(mihandle_t volume, const unsigned long start[], const unsigned long count[], hssize_t hdf_start[], hsize_t hdf_count[], int dir[]) /* direction vector in file order */ { int n_different = 0; int file_i; int ndims = volume->number_of_dims; int j; for(j=0; jdim_indices != NULL) { /* Have to swap indices */ user_i = volume->dim_indices[file_i]; if (user_i != file_i) { n_different++; } } else { user_i = file_i; } hdim = volume->dim_handles[user_i]; //hdim = volume->dim_handles[file_i]; switch (hdim->flipping_order) { case MI_FILE_ORDER: //hdf_start[file_i] = start[user_i]; hdf_start[user_i] = start[file_i]; dir[file_i] = 1; /* Set direction positive */ break; case MI_COUNTER_FILE_ORDER: //hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; hdf_start[user_i] = hdim->length - start[file_i] - count[file_i]; dir[file_i] = -1; /* Set direction negative */ break; case MI_POSITIVE: if (hdim->step > 0) { /* Positive? */ //hdf_start[file_i] = start[user_i]; /* Use raw file order. */ hdf_start[user_i] = start[file_i]; dir[file_i] = 1; /* Set direction positive */ } else { //hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; hdf_start[user_i] = hdim->length - start[file_i] - count[file_i]; dir[file_i] = -1; /* Set direction negative */ } break; case MI_NEGATIVE: if (hdim->step < 0) { /* Negative? */ //hdf_start[file_i] = start[user_i]; /* Use raw file order */ hdf_start[user_i] = start[file_i]; dir[file_i] = 1; /* Set direction positive */ } else { //hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; hdf_start[user_i] = hdim->length - start[file_i] - count[file_i]; dir[file_i] = -1; /* Set direction negative */ } break; } //hdf_count[file_i] = count[user_i]; hdf_count[user_i] = count[file_i]; } return (n_different); } /** Read/write a hyperslab of data. This is the simplified function * which performs no value conversion. It is much more efficient than * mirw_hyperslab_icv() */ static int mirw_hyperslab_raw(int opcode, mihandle_t volume, mitype_t midatatype, const unsigned long start[], const unsigned long count[], void *buffer) { hid_t dset_id = -1; hid_t mspc_id = -1; hid_t fspc_id = -1; hid_t type_id = -1; int result = MI_ERROR; hsize_t hdf_start[MI2_MAX_VAR_DIMS]; hsize_t hdf_count[MI2_MAX_VAR_DIMS]; int dir[MI2_MAX_VAR_DIMS]; /* Direction vector in file order */ int ndims; int n_different = 0; /* Disallow write operations to anything but the highest resolution. */ if (opcode == MIRW_OP_WRITE && volume->selected_resolution != 0) { return (MI_ERROR); } dset_id = volume->image_id; if (dset_id < 0) { goto cleanup; } fspc_id = H5Dget_space(dset_id); if (fspc_id < 0) { goto cleanup; } if (midatatype == MI_TYPE_UNKNOWN) { type_id = H5Tcopy(volume->mtype_id); } else { type_id = mitype_to_hdftype(midatatype, TRUE); } ndims = volume->number_of_dims; if (ndims == 0) { /* A scalar volume is possible but extremely unlikely, not to * mention useless! */ mspc_id = H5Screate(H5S_SCALAR); } else { n_different = mitranslate_hyperslab_origin(volume, start, count, hdf_start, hdf_count, dir); mspc_id = H5Screate_simple(ndims, hdf_count, NULL); if (mspc_id < 0) { goto cleanup; } } result = H5Sselect_hyperslab(fspc_id, H5S_SELECT_SET, hdf_start, NULL, hdf_count, NULL); if (result < 0) { goto cleanup; } if (opcode == MIRW_OP_READ) { result = H5Dread(dset_id, type_id, mspc_id, fspc_id, H5P_DEFAULT, buffer); /* Restructure the array after reading the data in file orientation. */ if (n_different != 0) { restructure_array(ndims, buffer, count, H5Tget_size(type_id), volume->dim_indices, dir); } } else { volume->is_dirty = TRUE; /* Mark as modified. */ /* Restructure array before writing to file. */ if (n_different != 0) { unsigned long icount[MI2_MAX_VAR_DIMS]; int idir[MI2_MAX_VAR_DIMS]; int imap[MI2_MAX_VAR_DIMS]; int i; /* Invert before calling */ for (i = 0; i < ndims; i++) { //icount[i] = count[volume->dim_indices[i]]; icount[volume->dim_indices[i]] = count[i]; //idir[i] = dir[volume->dim_indices[i]]; idir[volume->dim_indices[i]] = dir[i]; // this one was correct the original way imap[volume->dim_indices[i]] = i; } restructure_array(ndims, buffer, icount, H5Tget_size(type_id), imap, idir); } result = H5Dwrite(dset_id, type_id, mspc_id, fspc_id, H5P_DEFAULT, buffer); } cleanup: if (type_id >= 0) { H5Tclose(type_id); } if (mspc_id >= 0) { H5Sclose(mspc_id); } if (fspc_id >= 0) { H5Sclose(fspc_id); } return (result); } /** Read/write a hyperslab of data, performing dimension remapping * and data rescaling as needed. */ static int mirw_hyperslab_icv(int opcode, mihandle_t volume, int icv, const unsigned long start[], const unsigned long count[], void *buffer) { int ndims; int nbytes; int nc_type; int result = MI_ERROR; long icv_start[MI2_MAX_VAR_DIMS]; long icv_count[MI2_MAX_VAR_DIMS]; int dir[MI2_MAX_VAR_DIMS]; /* Direction, 1 or -1, in file order */ int n_different = 0; /* Disallow write operations to anything but the highest resolution. */ if (opcode == MIRW_OP_WRITE && volume->selected_resolution != 0) { return (MI_ERROR); } miicv_inqint(icv, MI_ICV_TYPE, &nc_type); nbytes = MI2typelen(nc_type); ndims = volume->number_of_dims; if (ndims != 0) { int i; hssize_t hdf_start[MI2_MAX_VAR_DIMS]; hsize_t hdf_count[MI2_MAX_VAR_DIMS]; n_different = mitranslate_hyperslab_origin(volume, start, count, hdf_start, hdf_count, dir); for (i = 0; i < ndims; i++) { icv_start[i] = hdf_start[i]; icv_count[i] = hdf_count[i]; } } if (opcode == MIRW_OP_READ) { result = miicv_get(icv, icv_start, icv_count, buffer); /* Now we have to restructure the array. * Count must be in raw order here. */ if (result == MI_NOERROR && n_different != 0) { restructure_array(ndims, buffer, count, nbytes, volume->dim_indices, dir); } } else { volume->is_dirty = TRUE; /* Flag as modified */ /* Restructure the data before writing. * Count must be in raw order here. */ if (n_different != 0) { restructure_array(ndims, buffer, count, nbytes, volume->dim_indices, dir); } result = miicv_put(icv, icv_start, icv_count, buffer); } return (result); } /** Reads the real values in the volume from the interval min through * max, mapped to the maximum representable range for the requested * data type. Float type is NOT an allowed data type. */ int miget_hyperslab_normalized(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], double min, double max, void *buffer) { hid_t file_id; int var_id; int icv; int result; int is_signed; int nctype; if (min > max) { return (MI_ERROR); } file_id = volume->hdf_id; if (file_id < 0) { return (MI_ERROR); } var_id = ncvarid(file_id, MIimage); if (var_id < 0) { return (MI_ERROR); } nctype = mitype_to_nctype(buffer_data_type, &is_signed); if (nctype == NC_FLOAT || nctype == NC_DOUBLE) { return (MI_ERROR); } if ((icv = miicv_create()) < 0) { return (MI_ERROR); } result = miicv_setint(icv, MI_ICV_TYPE, nctype); result = miicv_setstr(icv, MI_ICV_SIGN, is_signed ? MI_SIGNED : MI_UNSIGNED); result = miicv_setdbl(icv, MI_ICV_IMAGE_MIN, min); result = miicv_setdbl(icv, MI_ICV_IMAGE_MAX, max); result = miicv_setint(icv, MI_ICV_USER_NORM, TRUE); result = miicv_setint(icv, MI_ICV_DO_NORM, TRUE); result = miicv_attach(icv, file_id, var_id); if (result == MI_NOERROR) { result = mirw_hyperslab_icv(MIRW_OP_READ, volume, icv, start, count, buffer); miicv_detach(icv); } miicv_free(icv); return (result); } /** Get a hyperslab from the file, with the assistance of a MINC image * conversion variable (ICV). */ int miget_hyperslab_with_icv(mihandle_t volume, /**< A MINC 2.0 volume handle */ int icv, /**< The ICV to use */ mitype_t buffer_data_type, /**< Output datatype */ const unsigned long start[], /**< Start coordinates */ const unsigned long count[], /**< Lengths of edges */ void *buffer) /**< Output memory buffer */ { hid_t file_id; int var_id; int result; int is_signed; int nctype; file_id = volume->hdf_id; var_id = ncvarid(file_id, MIimage); nctype = mitype_to_nctype(buffer_data_type, &is_signed); miicv_setint(icv, MI_ICV_TYPE, nctype); miicv_setstr(icv, MI_ICV_SIGN, is_signed ? MI_SIGNED : MI_UNSIGNED); result = miicv_attach(icv, file_id, var_id); if (result == MI_NOERROR) { result = mirw_hyperslab_icv(MIRW_OP_READ, volume, icv, start, count, buffer); miicv_detach(icv); } return (result); } /** Write a hyperslab to the file, with the assistance of a MINC image * conversion variable (ICV). */ int miset_hyperslab_with_icv(mihandle_t volume, /**< A MINC 2.0 volume handle */ int icv, /**< The ICV to use */ mitype_t buffer_data_type, /**< Output datatype */ const unsigned long start[], /**< Start coordinates */ const unsigned long count[], /**< Lengths of edges */ void *buffer) /**< Output memory buffer */ { hid_t file_id; int var_id; int result; int is_signed; int nctype; file_id = volume->hdf_id; var_id = ncvarid(file_id, MIimage); nctype = mitype_to_nctype(buffer_data_type, &is_signed); miicv_setint(icv, MI_ICV_TYPE, nctype); miicv_setstr(icv, MI_ICV_SIGN, is_signed ? MI_SIGNED : MI_UNSIGNED); result = miicv_attach(icv, file_id, var_id); if (result == MI_NOERROR) { result = mirw_hyperslab_icv(MIRW_OP_WRITE, volume, icv, start, count, (void *) buffer); miicv_detach(icv); } return (result); } /** Read a hyperslab from the file into the preallocated buffer, * converting from the stored "voxel" data range to the desired * "real" (float or double) data range. */ int miget_real_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer) { hid_t file_id; int var_id; int icv; int result; int is_signed; int nctype; int i; midimhandle_t hdim; file_id = volume->hdf_id; var_id = ncvarid(file_id, MIimage); nctype = mitype_to_nctype(buffer_data_type, &is_signed); if ((icv = miicv_create()) < 0) { return (MI_ERROR); } miicv_setint(icv, MI_ICV_TYPE, nctype); miicv_setstr(icv, MI_ICV_SIGN, is_signed ? MI_SIGNED : MI_UNSIGNED); miicv_setint(icv, MI_ICV_DO_RANGE, TRUE); miicv_setint(icv, MI_ICV_DO_NORM, TRUE); //figure out whether we need to flip image L.B May 18/2011 for (i=0; i < volume->number_of_dims ; i++) { hdim = volume->dim_handles[i]; switch (hdim->flipping_order) { case MI_FILE_ORDER: miicv_setint(icv, MI_ICV_DO_DIM_CONV, FALSE); break; case MI_COUNTER_FILE_ORDER: case MI_POSITIVE: if (hdim->step < 0) miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE); break; case MI_NEGATIVE: if (hdim->step > 0) miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE); break; default: return; } } result = miicv_attach(icv, file_id, var_id); if (result == MI_NOERROR) { result = mirw_hyperslab_icv(MIRW_OP_READ, volume, icv, start, count, (void *) buffer); miicv_detach(icv); } miicv_free(icv); return (result); } /** Write a hyperslab to the file from the preallocated buffer, * converting from the stored "voxel" data range to the desired * "real" (float or double) data range. */ int miset_real_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer) { hid_t file_id; int var_id; int icv; int result; int is_signed; int nctype; file_id = volume->hdf_id; var_id = ncvarid(file_id, MIimage); nctype = mitype_to_nctype(buffer_data_type, &is_signed); if ((icv = miicv_create()) < 0) { return (MI_ERROR); } miicv_setint(icv, MI_ICV_TYPE, nctype); miicv_setstr(icv, MI_ICV_SIGN, is_signed ? MI_SIGNED : MI_UNSIGNED); result = miicv_attach(icv, file_id, var_id); if (result == MI_NOERROR) { result = mirw_hyperslab_icv(MIRW_OP_WRITE, volume, icv, start, count, (void *) buffer); miicv_detach(icv); } miicv_free(icv); return (result); } /** Read a hyperslab from the file into the preallocated buffer, * with no range conversions or normalization. Type conversions will * be performed if necessary. */ int miget_voxel_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer) { return mirw_hyperslab_raw(MIRW_OP_READ, volume, buffer_data_type, start, count, buffer); } /** Write a hyperslab to the file from the preallocated buffer, * with no range conversions or normalization. Type conversions will * be performed if necessary. */ int miset_voxel_value_hyperslab(mihandle_t volume, mitype_t buffer_data_type, const unsigned long start[], const unsigned long count[], void *buffer) { return mirw_hyperslab_raw(MIRW_OP_WRITE, volume, buffer_data_type, start, count, (void *) buffer); } minc-2.2.00/libsrc2/label.c0000644000265600003100000001121212027132662012220 00000000000000 /** * \file label.c * \brief MINC 2.0 Label functions * \author Bert Vincent * * This small set of three functions are intended to allow for the * definition of labeled, or enumerated, volumes. * * Labeled volumes must have been created with the class MI_CLASS_LABEL, * and with any integer subtype. * ************************************************************************/ #include #include #include "minc2.h" #include "minc2_private.h" #define MI_LABEL_MAX 128 int miswap2(unsigned short tmp) { unsigned char *x = (unsigned char *) &tmp; unsigned char t = x[0]; x[0] = x[1]; x[1] = t; return (tmp); } int miswap4(unsigned int tmp) { unsigned char *x = (unsigned char *) &tmp; unsigned char t = x[0]; x[0] = x[3]; x[3] = t; t = x[1]; x[1] = x[2]; x[2] = t; return (tmp); } /** This function associates a label name with an integer value for the given volume. Functions which read and write voxel values will read/write in integer values, and must call miget_label_name() to discover the descriptive text string which corresponds to the integer value. */ int midefine_label(mihandle_t volume, int value, const char *name) { int result; if (volume == NULL || name == NULL) { return (MI_ERROR); } if (strlen(name) > MI_LABEL_MAX) { return (MI_ERROR); } if (volume->volume_class != MI_CLASS_LABEL) { return (MI_ERROR); } if (volume->ftype_id <= 0 || volume->mtype_id <= 0) { return (MI_ERROR); } result = H5Tenum_insert(volume->mtype_id, name, &value); if (result < 0) { return (MI_ERROR); } /* We might have to swap these values before adding them to * the file type. */ if (H5Tget_order(volume->ftype_id) != H5Tget_order(volume->mtype_id)) { switch (H5Tget_size(volume->ftype_id)) { case 2: value = miswap2((unsigned short) value); break; case 4: value = miswap4((unsigned int) value); break; } } result = H5Tenum_insert(volume->ftype_id, name, &value); if (result < 0) { return (MI_ERROR); } return (MI_NOERROR); } /** For a labelled volume, this function retrieves the text name associated with a given integer value. The name pointer returned must be freed by calling mifree_name(). */ int miget_label_name(mihandle_t volume, int value, char **name) { int result; if (volume == NULL || name == NULL) { return (MI_ERROR); } if (volume->volume_class != MI_CLASS_LABEL) { return (MI_ERROR); } if (volume->mtype_id <= 0) { return (MI_ERROR); } *name = malloc(MI_LABEL_MAX); if (*name == NULL) { return (MI_ERROR); } H5E_BEGIN_TRY { result = H5Tenum_nameof(volume->mtype_id, &value, *name, MI_LABEL_MAX); } H5E_END_TRY; if (result < 0) { return (MI_ERROR); } return (MI_NOERROR); } /** This function is the inverse of miget_label_name(). It is called to determine what integer value, if any, corresponds to the given text string. */ int miget_label_value(mihandle_t volume, const char *name, int *value_ptr) { int result; if (volume == NULL || name == NULL || value_ptr == NULL) { return (MI_ERROR); } if (volume->volume_class != MI_CLASS_LABEL) { return (MI_ERROR); } if (volume->mtype_id <= 0) { return (MI_ERROR); } H5E_BEGIN_TRY { result = H5Tenum_valueof(volume->mtype_id, name, value_ptr); } H5E_END_TRY; if (result < 0) { return (MI_ERROR); } return (MI_NOERROR); } /** This function returns the number of defined labels, if any, or zero. */ int miget_number_of_defined_labels(mihandle_t volume, int *number_of_labels) { int result; if (volume == NULL) { return (MI_ERROR); } if (volume->volume_class != MI_CLASS_LABEL) { return (MI_ERROR); } if (volume->mtype_id <= 0) { return (MI_ERROR); } H5E_BEGIN_TRY { result = H5Tget_nmembers(volume->mtype_id); } H5E_END_TRY; if (result < 0) { return (MI_ERROR); } else { *number_of_labels = result; } return (MI_NOERROR); } /** This function returns the label value associated with an index (0,1,...) */ int miget_label_value_by_index(mihandle_t volume, int idx, int *value) { int result; if (volume == NULL) { return (MI_ERROR); } if (volume->volume_class != MI_CLASS_LABEL) { return (MI_ERROR); } if (volume->mtype_id <= 0) { return (MI_ERROR); } H5E_BEGIN_TRY { result = H5Tget_member_value(volume->mtype_id,idx,value); } H5E_END_TRY; if (result < 0) { return (MI_ERROR); } return (MI_NOERROR); } minc-2.2.00/libsrc2/m2util.c0000644000265600003100000015635212030075003012361 00000000000000/** \file m2util.c * \brief MINC 2.0 Private utility functions * \author Leila Baghdadi, Bert Vincent * ************************************************************************/ #include #include #include #include #include #include "minc2.h" #include "minc2_private.h" /* Uggh!!! The HDF5 team changed the definition of the H5Tconvert(), * H5Tregister(), and H5T_conv_t functions, and the result is that we * have to special-case these types. I am bummed. */ #if (H5_VERS_MAJOR > 1) || (H5_VERS_MINOR > 6) || (H5_VERS_RELEASE > 2) #define H5_NELEMENTS_T size_t #else #define H5_NELEMENTS_T hsize_t #endif /* They also redefined the type of the 4th argument to H5Sselect_elements. * This is harmless as long as sizeof(hssize_t) == sizeof(hsize_t). */ #if (H5_VERS_MAJOR > 1) || (H5_VERS_MINOR > 6) || (H5_VERS_RELEASE > 3) #define H5_START_T hsize_t #else #define H5_START_T hssize_t #endif /*! Convert a MINC 2 datatype into a HDF5 datatype. Actually returns a copy * of the datatype, so the returned value must be explicitly freed with a * call to H5Tclose(). * \param mitype The MINC 2 data type to convert * \param is_native Convert to native type if TRUE */ hid_t mitype_to_hdftype(mitype_t mitype, int is_native) { hid_t type_id; if (is_native) { /* Native types are in the byte-ordering of the native system. * They are appropriate for the "in-memory" types for data. */ switch (mitype) { case MI_TYPE_BYTE: type_id = H5Tcopy(H5T_NATIVE_SCHAR); break; case MI_TYPE_SHORT: type_id = H5Tcopy(H5T_NATIVE_SHORT); break; case MI_TYPE_INT: type_id = H5Tcopy(H5T_NATIVE_INT); break; case MI_TYPE_FLOAT: type_id = H5Tcopy(H5T_NATIVE_FLOAT); break; case MI_TYPE_DOUBLE: type_id = H5Tcopy(H5T_NATIVE_DOUBLE); break; case MI_TYPE_UBYTE: type_id = H5Tcopy(H5T_NATIVE_UCHAR); break; case MI_TYPE_USHORT: type_id = H5Tcopy(H5T_NATIVE_USHORT); break; case MI_TYPE_UINT: type_id = H5Tcopy(H5T_NATIVE_UINT); break; case MI_TYPE_SCOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 4); H5Tinsert(type_id, "real", 0, H5T_NATIVE_SHORT); H5Tinsert(type_id, "imag", 2, H5T_NATIVE_SHORT); break; case MI_TYPE_ICOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 8); H5Tinsert(type_id, "real", 0, H5T_NATIVE_INT); H5Tinsert(type_id, "imag", 4, H5T_NATIVE_INT); break; case MI_TYPE_FCOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 8); H5Tinsert(type_id, "real", 0, H5T_NATIVE_FLOAT); H5Tinsert(type_id, "imag", 4, H5T_NATIVE_FLOAT); break; case MI_TYPE_DCOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 16); H5Tinsert(type_id, "real", 0, H5T_NATIVE_DOUBLE); H5Tinsert(type_id, "imag", 8, H5T_NATIVE_DOUBLE); break; default: type_id = H5Tcopy(mitype); /* It is a standard HDF type handle? */ break; } } else { /* The non-native types are standardized to be in * "little-endian" form. That's an arbitrary decision which * could certainly be debated. */ switch (mitype) { case MI_TYPE_BYTE: type_id = H5Tcopy(H5T_STD_I8LE); break; case MI_TYPE_SHORT: type_id = H5Tcopy(H5T_STD_I16LE); break; case MI_TYPE_INT: type_id = H5Tcopy(H5T_STD_I32LE); break; case MI_TYPE_FLOAT: type_id = H5Tcopy(H5T_IEEE_F32LE); break; case MI_TYPE_DOUBLE: type_id = H5Tcopy(H5T_IEEE_F64LE); break; case MI_TYPE_UBYTE: type_id = H5Tcopy(H5T_STD_U8LE); break; case MI_TYPE_USHORT: type_id = H5Tcopy(H5T_STD_U16LE); break; case MI_TYPE_UINT: type_id = H5Tcopy(H5T_STD_U32LE); break; case MI_TYPE_SCOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 4); H5Tinsert(type_id, "real", 0, H5T_STD_I16LE); H5Tinsert(type_id, "imag", 2, H5T_STD_I16LE); break; case MI_TYPE_ICOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 8); H5Tinsert(type_id, "real", 0, H5T_STD_I32LE); H5Tinsert(type_id, "imag", 4, H5T_STD_I32LE); break; case MI_TYPE_FCOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 8); H5Tinsert(type_id, "real", 0, H5T_IEEE_F32LE); H5Tinsert(type_id, "imag", 4, H5T_IEEE_F32LE); break; case MI_TYPE_DCOMPLEX: type_id = H5Tcreate(H5T_COMPOUND, 16); H5Tinsert(type_id, "real", 0, H5T_IEEE_F64LE); H5Tinsert(type_id, "imag", 8, H5T_IEEE_F64LE); break; default: type_id = H5Tcopy(mitype); /* It is a standard HDF type handle? */ break; } } return (type_id); } /*! Convert a MINC 2 datatype into a NetCDF datatype. * \param mitype The MINC 2 data type to convert * \param is_signed Set to TRUE if the data type is signed, FALSE if unsigned. */ int mitype_to_nctype(mitype_t mitype, int *is_signed) { int nctype; *is_signed = 1; /* Assume signed by default. */ switch (mitype) { case MI_TYPE_BYTE: nctype = NC_BYTE; break; case MI_TYPE_SHORT: nctype = NC_SHORT; break; case MI_TYPE_INT: nctype = NC_INT; break; case MI_TYPE_FLOAT: nctype = NC_FLOAT; break; case MI_TYPE_DOUBLE: nctype = NC_DOUBLE; break; case MI_TYPE_UBYTE: nctype = NC_BYTE; *is_signed = 0; break; case MI_TYPE_USHORT: nctype = NC_SHORT; *is_signed = 0; break; case MI_TYPE_UINT: nctype = NC_INT; *is_signed = 1; break; default: nctype = -1; /* ERROR!! */ break; } return (nctype); } /*! Return the group or dataset ID of the last item in a "path", * specified like a UNIX pathname /black/white/red etc. * \param file_id The HDF5 handle of the file (or group) at which to start * the search. * \param path A string consisting of a slash-separated list of * HDF5 groupnames */ hid_t midescend_path(hid_t file_id, const char *path) { hid_t tmp_id; /* Put H5E_BEGIN_TRY/H5E_END_TRY around this to avoid the overzealous * automatic error reporting of HDF5. */ H5E_BEGIN_TRY { tmp_id = H5Dopen1(file_id, path); /* If the dataset open fails, try opening the object as a group. */ if (tmp_id < 0) { tmp_id = H5Gopen1(file_id, path); } } H5E_END_TRY; return (tmp_id); } /** Get the number of voxels in the file - this is the total number, * not just spatial dimensions */ mi_i64_t miget_voxel_count(int mincid) { int imgid; int dim[MI2_MAX_VAR_DIMS]; int idim; int ndims; mi_i64_t nvoxels; long length; /* Get the dimension ids for the image variable */ imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Loop over them to get the total number of voxels */ nvoxels = 1; for (idim = 0; idim < ndims; idim++) { (void)ncdiminq(mincid, dim[idim], NULL, &length); nvoxels *= length; } return (nvoxels); } int miset_attr_at_loc(hid_t hdf_loc, const char *name, mitype_t data_type, int length, const void *values) { hid_t ftyp_id; hid_t mtyp_id; hid_t spc_id; hid_t hdf_attr; hsize_t hdf_len; H5E_BEGIN_TRY { /* Delete attribute if it already exists. */ H5Adelete(hdf_loc, name); } H5E_END_TRY; switch (data_type) { case MI_TYPE_INT: ftyp_id = H5Tcopy(H5T_STD_I32LE); mtyp_id = H5Tcopy(H5T_NATIVE_INT); break; case MI_TYPE_FLOAT: ftyp_id = H5Tcopy(H5T_IEEE_F32LE); mtyp_id = H5Tcopy(H5T_NATIVE_FLOAT); break; case MI_TYPE_DOUBLE: ftyp_id = H5Tcopy(H5T_IEEE_F64LE); mtyp_id = H5Tcopy(H5T_NATIVE_DOUBLE); break; case MI_TYPE_STRING: ftyp_id = H5Tcopy(H5T_C_S1); H5Tset_size(ftyp_id, length); mtyp_id = H5Tcopy(ftyp_id); length = 1; /* Apparent length is one. */ break; default: return (MI_ERROR); } if (length == 1) { spc_id = H5Screate(H5S_SCALAR); } else { hdf_len = (hsize_t) length; spc_id = H5Screate_simple(1, &hdf_len, NULL); } if (spc_id < 0) { return (MI_ERROR); } hdf_attr = H5Acreate1(hdf_loc, name, ftyp_id, spc_id, H5P_DEFAULT); if (hdf_attr < 0) { return (MI_ERROR); } H5Awrite(hdf_attr, mtyp_id, values); H5Aclose(hdf_attr); H5Tclose(ftyp_id); H5Tclose(mtyp_id); H5Sclose(spc_id); return (MI_NOERROR); } /** Set an attribute from a minc file */ int miset_attribute(mihandle_t volume, const char *path, const char *name, mitype_t data_type, int length, const void *values) { hid_t hdf_file; hid_t hdf_loc; /* Get a handle to the actual HDF file */ hdf_file = volume->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } /* Search through the path, descending into each group encountered. */ hdf_loc = midescend_path(hdf_file, path); if (hdf_loc < 0) { return (MI_ERROR); } miset_attr_at_loc(hdf_loc, name, data_type, length, values); /* The hdf_loc identifier could be a group or a dataset. */ if (H5Iget_type(hdf_loc) == H5I_GROUP) { H5Gclose(hdf_loc); } else { H5Dclose(hdf_loc); } return (MI_NOERROR); } /** Get a double attribute from a minc file */ int miget_attribute(mihandle_t volume, const char *path, const char *name, mitype_t data_type, int length, void *values) { hid_t hdf_file; hid_t hdf_loc; hid_t mtyp_id = -1; /* Parameter type */ hid_t spc_id = -1; hid_t hdf_attr = -1; int status = MI_ERROR; /* Guilty until proven innocent */ /* Get a handle to the actual HDF file */ hdf_file = volume->hdf_id; if (hdf_file < 0) { return (MI_ERROR); } /* Find the group or dataset referenced by the path. */ hdf_loc = midescend_path(hdf_file, path); if (hdf_loc < 0) { return (MI_ERROR); } H5E_BEGIN_TRY { hdf_attr = H5Aopen_name(hdf_loc, name); } H5E_END_TRY; if (hdf_attr < 0) { goto cleanup; } switch (data_type) { case MI_TYPE_INT: mtyp_id = H5Tcopy(H5T_NATIVE_INT); break; case MI_TYPE_UINT: mtyp_id = H5Tcopy(H5T_NATIVE_UINT); break; case MI_TYPE_FLOAT: mtyp_id = H5Tcopy(H5T_NATIVE_FLOAT); break; case MI_TYPE_DOUBLE: mtyp_id = H5Tcopy(H5T_NATIVE_DOUBLE); break; case MI_TYPE_STRING: mtyp_id = H5Tcopy(H5T_C_S1); H5Tset_size(mtyp_id, length); break; default: goto cleanup; } spc_id = H5Aget_space(hdf_attr); if (spc_id < 0) { goto cleanup; } /* If we're retrieving a vector, make certain the length passed into this * function is sufficient. */ if (H5Sget_simple_extent_ndims(spc_id) == 1) { hsize_t hdf_dims[1]; H5Sget_simple_extent_dims(spc_id, hdf_dims, NULL); if (length < hdf_dims[0]) { goto cleanup; } } if (H5Aread(hdf_attr, mtyp_id, values) < 0) { goto cleanup; } status = MI_NOERROR; /* We succeeded! */ /* Be certain that the string is null-terminated. */ if (data_type == MI_TYPE_STRING) { hid_t atype; /* Attribute type */ int alength; atype = H5Aget_type(hdf_attr); alength = H5Tget_size(atype); ((char *)values)[alength] = '\0'; H5Tclose(atype); } cleanup: if (hdf_attr >= 0) { H5Aclose(hdf_attr); } if (mtyp_id >= 0) { H5Tclose(mtyp_id); } if (spc_id >= 0) { H5Sclose(spc_id); } if (hdf_loc >= 0) { /* The hdf_loc identifier could be a group or a dataset. */ if (H5Iget_type(hdf_loc) == H5I_GROUP) { H5Gclose(hdf_loc); } else { H5Dclose(hdf_loc); } } return (status); } /* Get the mapping from spatial dimension - x, y, z - to file dimensions * and vice-versa. */ void mifind_spatial_dims(int mincid, int space_to_dim[], int dim_to_space[]) { int imgid, dim[MI2_MAX_VAR_DIMS]; int idim, ndims, world_index; char dimname[MAX_NC_NAME]; /* Set default values */ for (idim = 0; idim < 3; idim++) space_to_dim[idim] = -1; for (idim = 0; idim < MI2_MAX_VAR_DIMS; idim++) dim_to_space[idim] = -1; /* Get the dimension ids for the image variable */ imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Loop over them to find the spatial ones */ for (idim = 0; idim < ndims; idim++) { /* Get the name and check that this is a spatial dimension */ (void)ncdiminq(mincid, dim[idim], dimname, NULL); if (!strcmp(dimname, MIxspace)) { world_index = MI2_X; } else if (!strcmp(dimname, MIyspace)) { world_index = MI2_Y; } else if (!strcmp(dimname, MIzspace)) { world_index = MI2_Z; } else { continue; } space_to_dim[world_index] = idim; dim_to_space[idim] = world_index; } } /** Get the voxel to world transform (for column vectors) */ void miget_voxel_to_world(mihandle_t volume, mi_lin_xfm_t voxel_to_world) { int i; int j; int k; double dircos[MI2_3D]; double step; double start; /* Zero the matrix */ for (i = 0; i < MI2_LIN_XFM_SIZE; i++) { for (j = 0; j < MI2_LIN_XFM_SIZE; j++) { voxel_to_world[i][j] = 0.0; } voxel_to_world[i][i] = 1.0; } for (j = 0; j < volume->number_of_dims; j++) { midimhandle_t hdim = volume->dim_handles[j]; if (hdim->class == MI_DIMCLASS_SPATIAL || hdim->class == MI_DIMCLASS_SFREQUENCY) { k = hdim->world_index; } else { continue; } start = hdim->start; step = hdim->step; dircos[0] = hdim->direction_cosines[0]; dircos[1] = hdim->direction_cosines[1]; dircos[2] = hdim->direction_cosines[2]; minormalize_vector(dircos); /* Put them in the matrix */ for (i = 0; i < MI2_3D; i++) { voxel_to_world[i][k] = step * dircos[i]; voxel_to_world[i][MI2_3D] += start * dircos[i]; } } } /** Normalize a 3 element vector */ void minormalize_vector(double vector[MI2_3D]) { int i; double magnitude; magnitude = 0.0; for (i = 0; i < MI2_3D; i++) { magnitude += (vector[i] * vector[i]); } magnitude = sqrt(magnitude); if (magnitude > 0.0) { for (i = 0; i < MI2_3D; i++) { vector[i] /= magnitude; } } } /** Transforms a coordinate through a linear transform */ void mitransform_coord(double out_coord[], mi_lin_xfm_t transform, const double in_coord[]) { int i, j; double in_homogeneous[MI2_3D + 1]; double out_homogeneous[MI2_3D + 1]; for (i = 0; i < MI2_3D; i++) { in_homogeneous[i] = in_coord[i]; } in_homogeneous[MI2_3D] = 1.0; for (i = 0; i < MI2_3D + 1; i++) { out_homogeneous[i] = 0.0; for (j = 0; j < MI2_3D + 1; j++) { out_homogeneous[i] += transform[i][j] * in_homogeneous[j]; } } #if 0 printf("W = %f\n", out_homogeneous[3]); #endif /* 0 */ for (i = 0; i < MI2_3D; i++) { out_coord[i] = out_homogeneous[i]; } } /** For conversions from double to integer, rounding may be performed * by setting this variable to non-zero. * However, at present, no API is available to control this. */ static int rounding_enabled = FALSE; static void miswap8(unsigned char *tmp_ptr) { unsigned char x; x = tmp_ptr[0]; tmp_ptr[0] = tmp_ptr[7]; tmp_ptr[7] = x; x = tmp_ptr[1]; tmp_ptr[1] = tmp_ptr[6]; tmp_ptr[6] = x; x = tmp_ptr[2]; tmp_ptr[2] = tmp_ptr[5]; tmp_ptr[5] = x; x = tmp_ptr[3]; tmp_ptr[3] = tmp_ptr[4]; tmp_ptr[4] = x; } static void miswap4(unsigned char *tmp_ptr) { unsigned char x; x = tmp_ptr[0]; tmp_ptr[0] = tmp_ptr[3]; tmp_ptr[3] = x; x = tmp_ptr[1]; tmp_ptr[1] = tmp_ptr[2]; tmp_ptr[2] = x; } static void miswap2(unsigned char *tmp_ptr) { unsigned char x; x = tmp_ptr[0]; tmp_ptr[0] = tmp_ptr[1]; tmp_ptr[1] = x; } /** Generic HDF5 integer-to-double converter. */ static herr_t mi2_int_to_dbl(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, H5_NELEMENTS_T nelements, size_t buf_stride, size_t bkg_stride, void *buf_ptr, void *bkg_ptr, hid_t dset_xfer_plist) { unsigned char *dst_ptr; unsigned char *src_ptr; int src_nb; int dst_nb; H5T_sign_t src_sg; double t; int dst_cnt; int src_cnt; int src_swap; int dst_swap; switch (cdata->command) { case H5T_CONV_INIT: cdata->need_bkg = H5T_BKG_NO; src_nb = H5Tget_size(src_id); if (src_nb != 1 && src_nb != 2 && src_nb != 4) { return (-1); } dst_nb = H5Tget_size(dst_id); if (dst_nb != 8) { return (-1); } break; case H5T_CONV_CONV: src_nb = H5Tget_size(src_id); src_sg = H5Tget_sign(src_id); dst_nb = H5Tget_size(dst_id); if (buf_stride == 0) { dst_cnt = dst_nb; src_cnt = src_nb; } else { dst_cnt = buf_stride; src_cnt = buf_stride; } /* Convert starting from "far side" of buffer... (Hope this works!) */ dst_ptr = ((unsigned char *) buf_ptr) + ((nelements - 1) * dst_nb); src_ptr = ((unsigned char *) buf_ptr) + ((nelements - 1) * src_nb); if (H5Tget_order(H5T_NATIVE_INT) != H5Tget_order(src_id)) { src_swap = 1; } else { src_swap = 0; } if (H5Tget_order(H5T_NATIVE_DOUBLE) != H5Tget_order(dst_id)) { dst_swap = 1; } else { dst_swap = 0; } if (src_sg == H5T_SGN_2) { switch (src_nb) { case 4: while (nelements-- > 0) { if (src_swap) { miswap4(src_ptr); } t = *(int *)src_ptr; *(double *)dst_ptr = t; if (dst_swap) { miswap8(dst_ptr); } src_ptr -= src_cnt; dst_ptr -= dst_cnt; } break; case 2: while (nelements-- > 0) { if (src_swap) { miswap2(src_ptr); } t = *(short *)src_ptr; *(double *)dst_ptr = t; if (dst_swap) { miswap8(dst_ptr); } src_ptr -= src_cnt; dst_ptr -= dst_cnt; } break; case 1: while (nelements-- > 0) { t = *(char *)src_ptr; *(double *)dst_ptr = t; if (dst_swap) { miswap8(dst_ptr); } src_ptr -= src_cnt; dst_ptr -= dst_cnt; } break; default: /* Should not happen! */ break; } } else { switch (src_nb) { case 4: while (nelements-- > 0) { if (src_swap) { miswap4(src_ptr); } t = *(unsigned int *)src_ptr; *(double *)dst_ptr = t; if (dst_swap) { miswap8(dst_ptr); } src_ptr -= src_cnt; dst_ptr -= dst_cnt; } break; case 2: while (nelements-- > 0) { if (src_swap) { miswap2(src_ptr); } t = *(unsigned short *)src_ptr; *(double *)dst_ptr = t; if (dst_swap) { miswap8(dst_ptr); } src_ptr -= src_cnt; dst_ptr -= dst_cnt; } break; case 1: while (nelements-- > 0) { t = *(unsigned char *)src_ptr; *(double *)dst_ptr = t; if (dst_swap) { miswap8(dst_ptr); } src_ptr -= src_cnt; dst_ptr -= dst_cnt; } break; default: /* Should not happen! */ break; } } break; case H5T_CONV_FREE: break; default: /* Unknown command */ return (-1); } return (0); } /** Generic HDF5 double-to-integer converter. */ static herr_t mi2_dbl_to_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, H5_NELEMENTS_T nelements, size_t buf_stride, size_t bkg_stride, void *buf_ptr, void *bkg_ptr, hid_t dset_xfer_plist) { unsigned char *dst_ptr; unsigned char *src_ptr; int src_nb; int dst_nb; H5T_sign_t dst_sg; double t; int dst_cnt; int src_cnt; int src_swap; int dst_swap; switch (cdata->command) { case H5T_CONV_INIT: cdata->need_bkg = H5T_BKG_NO; /* Verify that we can handle this conversion. */ src_nb = H5Tget_size(src_id); if (src_nb != 8) { return (-1); } dst_nb = H5Tget_size(dst_id); if (dst_nb != 4 && dst_nb != 2 && dst_nb != 1) { return (-1); } break; case H5T_CONV_CONV: dst_nb = H5Tget_size(dst_id); dst_sg = H5Tget_sign(dst_id); src_nb = H5Tget_size(src_id); dst_ptr = (unsigned char *) buf_ptr; src_ptr = (unsigned char *) buf_ptr; if (H5Tget_order(H5T_NATIVE_DOUBLE) != H5Tget_order(src_id)) { src_swap = 1; } else { src_swap = 0; } if (H5Tget_order(H5T_NATIVE_INT) != H5Tget_order(dst_id)) { dst_swap = 1; } else { dst_swap = 0; } /* The logic of HDF5 seems to be that if a stride is specified, * both the source and destination pointers should advance by that * amount. This seems wrong to me, but I've examined the HDF5 sources * and that's what their own type converters do. */ if (buf_stride == 0) { dst_cnt = dst_nb; src_cnt = src_nb; } else { dst_cnt = buf_stride; src_cnt = buf_stride; } if (rounding_enabled) { if (dst_sg == H5T_SGN_2) { switch (dst_nb) { case 4: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = rint(*(double *) src_ptr); if (t > INT_MAX) { t = INT_MAX; } else if (t < INT_MIN) { t = INT_MIN; } *((int *)dst_ptr) = (int) t; if (dst_swap) { miswap4(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 2: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = rint(*(double *) src_ptr); if (t > SHRT_MAX) { t = SHRT_MAX; } else if (t < SHRT_MIN) { t = SHRT_MIN; } *((short *)dst_ptr) = (short) t; if (dst_swap) { miswap2(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 1: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = rint(*(double *) src_ptr); if (t > CHAR_MAX) { t = CHAR_MAX; } else if (t < CHAR_MIN) { t = CHAR_MIN; } *((char *)src_ptr) = (char) t; dst_ptr += dst_cnt; src_ptr += src_cnt; } break; default: /* Can't handle this! */ break; } } else { switch (dst_nb) { case 4: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = rint(*(double *)src_ptr); if (t > UINT_MAX) { t = UINT_MAX; } else if (t < 0) { t = 0; } *((unsigned int *)dst_ptr) = (unsigned int) t; if (dst_swap) { miswap4(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 2: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = rint(*(double *)src_ptr); if (t > USHRT_MAX) { t = USHRT_MAX; } else if (t < 0) { t = 0; } *((unsigned short *)dst_ptr) = (unsigned short) t; if (dst_swap) { miswap2(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 1: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = rint(*(double *)src_ptr); if (t > UCHAR_MAX) { t = UCHAR_MAX; } else if (t < 0) { t = 0; } *((unsigned char *)dst_ptr) = (unsigned char) t; dst_ptr += dst_cnt; src_ptr += src_cnt; } break; default: /* Can't handle any other values */ break; } } } else { if (dst_sg == H5T_SGN_2) { switch (dst_nb) { case 4: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = (int)(*(double *) src_ptr); if (t > INT_MAX) { t = INT_MAX; } else if (t < INT_MIN) { t = INT_MIN; } *((int *)dst_ptr) = (int) t; if (dst_swap) { miswap4(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 2: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = (int)(*(double *) src_ptr); if (t > SHRT_MAX) { t = SHRT_MAX; } else if (t < SHRT_MIN) { t = SHRT_MIN; } *((short *)dst_ptr) = (short) t; if (dst_swap) { miswap4(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 1: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = (int)(*(double *) src_ptr); if (t > CHAR_MAX) { t = CHAR_MAX; } else if (t < CHAR_MIN) { t = CHAR_MIN; } *((char *)src_ptr) = (char) t; dst_ptr += dst_cnt; src_ptr += src_cnt; } break; default: /* Can't handle this! */ break; } } else { switch (dst_nb) { case 4: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = (int)(*(double *)src_ptr); if (t > UINT_MAX) { t = UINT_MAX; } else if (t < 0) { t = 0; } *((unsigned int *)dst_ptr) = (unsigned int) t; if (dst_swap) { miswap4(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 2: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = (int)(*(double *)src_ptr); if (t > USHRT_MAX) { t = USHRT_MAX; } else if (t < 0) { t = 0; } *((unsigned short *)dst_ptr) = (unsigned short) t; if (dst_swap) { miswap2(dst_ptr); } dst_ptr += dst_cnt; src_ptr += src_cnt; } break; case 1: while (nelements-- > 0) { if (src_swap) { miswap8(src_ptr); } t = (int)(*(double *)src_ptr); if (t > UCHAR_MAX) { t = UCHAR_MAX; } else if (t < 0) { t = 0; } *((unsigned char *)dst_ptr) = (unsigned char) t; dst_ptr += dst_cnt; src_ptr += src_cnt; } break; default: /* Can't handle any other values */ break; } } } break; case H5T_CONV_FREE: break; default: /* Unknown command */ return (-1); } return (0); } /** Initialize some critical pieces of the library. For now all this does is install the double-to-integer and integer-to-double conversion functions. */ void miinit(void) { H5Tregister(H5T_PERS_SOFT, "i2d", H5T_NATIVE_INT, H5T_NATIVE_DOUBLE, mi2_int_to_dbl); H5Tregister(H5T_PERS_SOFT, "d2i", H5T_NATIVE_DOUBLE, H5T_NATIVE_INT, mi2_dbl_to_int); } /** HDF5 type conversion function for converting an arbitrary integer type to * an arbitrary enumerated type. The beauty part of this is that it is * not necessary to actually perform any real conversion! */ herr_t mi2_null_conv(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, H5_NELEMENTS_T nelements, size_t buf_stride, size_t bkg_stride, void *buf_ptr, void *bkg_ptr, hid_t dset_xfer_plist) { switch (cdata->command) { case H5T_CONV_INIT: break; case H5T_CONV_CONV: break; case H5T_CONV_FREE: break; default: /* Unknown command */ return (-1); } return (0); } /** This function should be called when a labeled volume is created or opened in order to facilitate conversions from the integer to the enumerated type. */ void miinit_enum(hid_t type_id) { H5Tregister(H5T_PERS_SOFT, "i2e", H5T_NATIVE_INT, type_id, mi2_null_conv); H5Tregister(H5T_PERS_SOFT, "e2i", type_id, H5T_NATIVE_INT, mi2_null_conv); H5Tregister(H5T_PERS_SOFT, "d2e", H5T_NATIVE_DOUBLE, type_id, mi2_dbl_to_int); H5Tregister(H5T_PERS_SOFT, "e2d", type_id, H5T_NATIVE_DOUBLE, mi2_int_to_dbl); } int minc_create_thumbnail(mihandle_t volume, int grp) { char path[MI2_MAX_PATH]; hid_t grp_id; /* Don't handle negative or overly large numbers! */ if (grp <= 0 || grp > MI2_MAX_RESOLUTION_GROUP) { return (MI_ERROR); } sprintf(path, "/minc-2.0/image/%d", grp); grp_id = H5Gcreate1(volume->hdf_id, path, 0); if (grp_id < 0) { return (MI_ERROR); } H5Gclose(grp_id); return (MI_NOERROR); } /** Function to downsample a single slice of an image. * \param in_ptr the 3D input slice, scale x isize[1] x isize[2] * \param out_ptr the 2D output slice, osize[1] x osize[2] */ static void midownsample_slice(double *in_ptr, double *out_ptr, hsize_t isize[], hsize_t osize[], int scale) { int j, k; int x, y, z; double d; hsize_t total; total = scale * scale * scale; /* These two loops iterate over all of the voxels in the 2D output * image. */ for (j = 0; j < osize[1]; j++) { for (k = 0; k < osize[2]; k++) { /* The three inner loops iterate all scale^3 * voxels in the input image which will be averaged * to form the output image. */ d = 0; for (x = 0; x < scale; x++) { for (y = 0; y < scale; y++) { for (z = 0; z < scale; z++) { int x1,y1,z1; double t; x1 = x; y1 = y + (j * scale); z1 = z + (k * scale); t = in_ptr[((x1 * isize[1]) + y1) * isize[2] + z1]; d += t; } } } d /= total; out_ptr[(j * osize[2]) + k] = d; } } } /** Convert the hyperslab from real to voxel values, calculating and * returning the minimum and maximum real values for the slab. This * could form the basis for a public function one day, but for now it * is considered private. */ static void miconvert_hyperslab_to_voxel(mihandle_t volume, hssize_t start[], hsize_t count[], double *slab_ptr, double *max_ptr, double *min_ptr) { /* This code is not intended to be a general hyperslab-to-voxel * converter yet. That is why it is not public. */ double real_min, real_max; /* Minimum and maximum values */ hsize_t index; hsize_t total; double voxel_range, voxel_offset; double real_range, real_offset; int i; double tmp_val; real_min = DBL_MAX; real_max = -DBL_MAX; total = 1; for (i = 0; i < volume->number_of_dims; i++) { total *= count[i]; } /* Find the global minimum and maximum for this hyperslab. */ for (index = 0; index < total; index++) { tmp_val = slab_ptr[index]; if (tmp_val > real_max) { real_max = tmp_val; } if (tmp_val < real_min) { real_min = tmp_val; } } voxel_range = volume->valid_max - volume->valid_min; voxel_offset = volume->valid_min; real_range = real_max - real_min; real_offset = real_min; for (index = 0; index < total; index++) { tmp_val = slab_ptr[index]; tmp_val = (tmp_val - real_offset) / real_range; tmp_val = (tmp_val * voxel_range) + voxel_offset; slab_ptr[index] = rint(tmp_val); } if (min_ptr != NULL) { *min_ptr = real_min; } if (max_ptr != NULL) { *max_ptr = real_max; } } /** Convert the hyperslab from voxel to real values. This could form * the basis for a public function one day, but for now it is * considered private. */ static void miconvert_hyperslab_to_real(mihandle_t volume, hssize_t start[], hsize_t count[], double *slab_ptr) { /* This code is not intended to be a general hyperslab-to-real * converter yet. That is why it is not public. */ double real_min, real_max; /* Minimum and maximum values */ hsize_t index; hsize_t total; double voxel_range, voxel_offset; double real_range, real_offset; int i; double tmp_val; unsigned long pos[MI2_MAX_VAR_DIMS]; int r; total = 1; for (i = 0; i < volume->number_of_dims; i++) { total *= count[i]; pos[i] = start[i]; } voxel_offset = volume->valid_min; voxel_range = volume->valid_max - volume->valid_min; /* Get the initial real minimum & maximum. */ r = miget_slice_range(volume, pos, volume->number_of_dims, &real_max, &real_min); if (r == MI_ERROR) { fprintf(stderr, "Oops - failed to get slice range\n"); } real_offset = real_min; real_range = real_max - real_min; for (index = 0; index < total; index++) { /* Since this calculation may cross slice boundaries, I need to * grab the correct real minimum and maximum for the coordinates * I happen to be in at the time. * * This next loop attempts to keep track of the current position, * and reloads the minimum and maximum whenever we change any other * than the fastest-varying dimension. */ for (i = volume->number_of_dims - 1; i >= 0; i--) { pos[i]++; if (pos[i] >= count[i]) { pos[i] = start[i]; r = miget_slice_range(volume, pos, volume->number_of_dims, &real_max, &real_min); if (r == MI_ERROR) { fprintf(stderr, "Oops - failed to get slice range\n"); } real_offset = real_min; real_range = real_max - real_min; } else { break; } } tmp_val = (slab_ptr[index] - voxel_offset) / voxel_range; slab_ptr[index] = (tmp_val * real_range) + real_offset; } } /** Update an individual thumbnail for the \a volume. Updates group * number \a ogrp from source group \a igrp. The whole image tree must * be rooted at \a loc_id. */ int minc_update_thumbnail(mihandle_t volume, hid_t loc_id, int igrp, int ogrp) { hsize_t isize[MI2_MAX_VAR_DIMS]; hsize_t osize[MI2_MAX_VAR_DIMS]; hsize_t count[MI2_MAX_VAR_DIMS]; H5_START_T start[MI2_MAX_VAR_DIMS]; hid_t idst_id; /* Input dataset */ hid_t odst_id; /* Output dataset */ hid_t ifspc_id; /* Input "file" dataspace */ hid_t ofspc_id; /* Output "file" dataspace */ hid_t typ_id; /* Type ID */ hid_t imspc_id; /* Input memory dataspace */ hid_t omspc_id; /* Output memory dataspace */ char path[MI2_MAX_PATH]; int ndims; /* Number of dimensions in the image */ int scale; int i; /* Generic loop counter */ double *in_ptr; double *out_ptr; int slice; int in_bytes; int out_bytes; double smax, smin; /* Slice minimum and maximum */ hid_t omax_id; /* Output image-max dataset */ hid_t omin_id; /* Output image-min dataset */ hid_t tfspc_id; /* Dimensionality of image-max/image-min */ hid_t tmspc_id; hid_t dcpl_id; /* Dataset creation property list */ miinit(); /* Check arguments for basic validity. */ if (ogrp <= igrp) { return (MI_ERROR); } /* Calculate scale factor (always a power of 2) */ for (i = igrp, scale = 1; i < ogrp; i++, scale <<= 1) ; /* Open the input path. */ sprintf(path, "%d/image", igrp); idst_id = H5Dopen1(loc_id, path); if (idst_id < 0) { return (MI_ERROR); } /* Get the input type. */ typ_id = H5Dget_type(idst_id); /* Get the input dataspace. */ ifspc_id = H5Dget_space(idst_id); /* Get the input dataset creation property list */ dcpl_id = H5Dget_create_plist(idst_id); ndims = H5Sget_simple_extent_ndims(ifspc_id); H5Sget_simple_extent_dims(ifspc_id, isize, NULL); /* Calculate the size of the new thumbnail. */ for (i = 0; i < ndims; i++) { osize[i] = isize[i] / scale; if (osize[i] == 0) { /* Too small? */ return (MI_ERROR); } } /* Create dataspace for new resolution */ ofspc_id = H5Screate_simple(ndims, osize, NULL); sprintf(path, "%d/image", ogrp); H5E_BEGIN_TRY { odst_id = H5Dcreate1(loc_id, path, typ_id, ofspc_id, H5P_DEFAULT); } H5E_END_TRY; if (odst_id < 0) { odst_id = H5Dopen1(loc_id, path); if (odst_id < 0) { return (MI_ERROR); } } H5Pclose(dcpl_id); /* No longer needed. */ if (volume->volume_class == MI_CLASS_REAL) { /* TODO: This is a bit of a hack - I need a better way to get the * dimensionality of the source image-min and image-max. */ tfspc_id = H5Screate_simple(1, &osize[0], NULL); /* Create a simple scalar dataspace. */ tmspc_id = H5Screate(H5S_SCALAR); sprintf(path, "%d/image-max", ogrp); H5E_BEGIN_TRY { omax_id = H5Dcreate1(loc_id, path, H5T_IEEE_F64LE, tfspc_id, H5P_DEFAULT); } H5E_END_TRY; if (omax_id < 0) { omax_id = H5Dopen1(loc_id, path); } sprintf(path, "%d/image-min", ogrp); H5E_BEGIN_TRY { omin_id = H5Dcreate1(loc_id, path, H5T_IEEE_F64LE, tfspc_id, H5P_DEFAULT); } H5E_END_TRY; if (omin_id < 0) { omin_id = H5Dopen1(loc_id, path); } } /* Calculate the input buffer size - scale slices. */ in_bytes = scale * isize[1] * isize[2] * sizeof(double); in_ptr = malloc(in_bytes); out_bytes = osize[1] * osize[2] * sizeof(double); out_ptr = malloc(out_bytes); count[0] = scale; count[1] = isize[1]; count[2] = isize[2]; imspc_id = H5Screate_simple(ndims, count, NULL); count[0] = 1; count[1] = osize[1]; count[2] = osize[2]; omspc_id = H5Screate_simple(ndims, count, NULL); /* * read image & TODO: convert to "real" range. */ for (slice = 0; slice < osize[0]; slice++) { start[0] = slice * scale; start[1] = 0; start[2] = 0; count[0] = scale; count[1] = isize[1]; count[2] = isize[2]; H5Sselect_hyperslab(ifspc_id, H5S_SELECT_SET, start, NULL, count, NULL); H5Dread(idst_id, H5T_NATIVE_DOUBLE, imspc_id, ifspc_id, H5P_DEFAULT, in_ptr); /* Scale slice from voxel to real values. */ miconvert_hyperslab_to_real(volume, start, count, in_ptr); midownsample_slice(in_ptr, out_ptr, isize, osize, scale); start[0] = slice; start[1] = 0; start[2] = 0; count[0] = 1; count[1] = osize[1]; count[2] = osize[2]; H5Sselect_hyperslab(ofspc_id, H5S_SELECT_SET, start, NULL, count, NULL); miconvert_hyperslab_to_voxel(volume, start, count, out_ptr, &smax, &smin); H5Dwrite(odst_id, H5T_NATIVE_DOUBLE, omspc_id, ofspc_id, H5P_DEFAULT, out_ptr); if (volume->volume_class == MI_CLASS_REAL) { /* Select the right point in tfspc_id */ H5Sselect_elements(tfspc_id, H5S_SELECT_SET, 1, (const H5_START_T **) &start[0]); H5Dwrite(omax_id, H5T_NATIVE_DOUBLE, tmspc_id, tfspc_id, H5P_DEFAULT, &smax); H5Dwrite(omin_id, H5T_NATIVE_DOUBLE, tmspc_id, tfspc_id, H5P_DEFAULT, &smin); } } free(in_ptr); free(out_ptr); H5Dclose(omax_id); H5Dclose(omin_id); H5Sclose(tfspc_id); H5Sclose(tmspc_id); H5Sclose(omspc_id); H5Sclose(imspc_id); H5Dclose(odst_id); H5Tclose(typ_id); H5Sclose(ofspc_id); H5Sclose(ifspc_id); return (MI_NOERROR); } /** Cycle through and update each of the lower-resolution images in * the file. */ int minc_update_thumbnails(mihandle_t volume) { int grp_no, prv_grp_no; hid_t grp_id; hsize_t n; hsize_t i; char name[MI2_MAX_PATH]; grp_id = H5Gopen1(volume->hdf_id, "/minc-2.0/image"); if (grp_id < 0) { return (MI_ERROR); /* Error opening group. */ } if (H5Gget_num_objs(grp_id, &n) < 0) { return (MI_ERROR); /* Error getting object count. */ } grp_no = -1; for (i = 0; i < n; i++) { if (H5Gget_objname_by_idx(grp_id, i, name, MI2_MAX_PATH) < 0) { return (MI_ERROR); } prv_grp_no = grp_no; grp_no = atoi(name); if (grp_no != 0) { minc_update_thumbnail(volume, grp_id, prv_grp_no, grp_no); } } H5Gclose(grp_id); return (MI_NOERROR); } double * alloc1d(int n) { return ((double *) malloc(sizeof(double) * n)); } double ** alloc2d(int n, int m) { double **mat; int i; mat = (double **) malloc(n * sizeof(double *)); if (mat == NULL) { return NULL; } for (i = 0; i < n; i++) { mat[i] = (double *) malloc(m * sizeof(double)); if (mat[i] == NULL) { return NULL; } } return (mat); } void free2d(int n, double **mat) { int i; for (i = 0; i < n; i++) { free(mat[i]); } free(mat); } /** Function for create a NON-STANDARD dataset other than --> (acquisition, patient, study) */ int create_dataset(hid_t hdf_file, const char *name) { hid_t dataset_info; hid_t dataspace_info; hid_t grp_info; int result; grp_info = H5Gopen1(hdf_file, "/minc-2.0/info"); if (grp_info < 0) { return (MI_ERROR); } dataspace_info = H5Screate(H5S_SCALAR); if (dataspace_info < 0) { return (MI_ERROR); } dataset_info = H5Dcreate1(grp_info, name, H5T_STD_I32LE, dataspace_info, H5P_DEFAULT); if (dataset_info < 0) { return (MI_ERROR); } H5Dclose(dataset_info); H5Sclose(dataspace_info); H5Gclose(grp_info); return (MI_NOERROR); } /** Function for create a dataset (acquisition, patient, study) */ int create_standard_dataset(hid_t hdf_file, const char *name) { hid_t dataset_info; hid_t dataspace_info; hid_t grp_info; int result; grp_info = H5Gopen1(hdf_file, "/minc-2.0/info"); if (grp_info < 0) { return (MI_ERROR); } dataspace_info = H5Screate(H5S_SCALAR); if (dataspace_info < 0) { return (MI_ERROR); } dataset_info = H5Dcreate1(grp_info, name, H5T_STD_I32LE, dataspace_info, H5P_DEFAULT); if (dataset_info < 0) { return (MI_ERROR); } result = miset_attr_at_loc(dataset_info,MIvarid, MI_TYPE_STRING, strlen(MI_STDVAR), MI_STDVAR); if (result < 0){ return (MI_ERROR); } result = miset_attr_at_loc(dataset_info,MIvartype, MI_TYPE_STRING, strlen(MI_GROUP), MI_GROUP); if (result < 0){ return (MI_ERROR); } result = miset_attr_at_loc(dataset_info,MIversion, MI_TYPE_STRING, strlen(MI_VERSION_2_0), MI_VERSION_2_0); if (result < 0){ return (MI_ERROR); } H5Dclose(dataset_info); H5Sclose(dataspace_info); H5Gclose(grp_info); return (MI_NOERROR); } /** Performs scaled maximal pivoting gaussian elimination as a numerically robust method to solve systems of linear equations. */ int scaled_maximal_pivoting_gaussian_elimination(int n, int row[], double **a, int n_values, double **solution ) { int i, j, k, p, v, tmp; double *s, val, best_val, m, scale_factor; int success; s = alloc1d( n ); for ( i = 0; i < n; i++ ) row[i] = i; for ( i = 0; i < n; i++ ) { s[i] = fabs( a[i][0] ); for ( j = 1; j < n; j++ ) { if ( fabs(a[i][j]) > s[i] ) s[i] = fabs(a[i][j]); } if ( s[i] == 0.0 ) { free( s ); return ( FALSE ); } } success = TRUE; for ( i = 0; i < n-1; i++ ) { p = i; best_val = a[row[i]][i] / s[row[i]]; best_val = fabs( best_val ); for ( j = i+1; j < n; j++ ) { val = a[row[j]][i] / s[row[j]]; val = fabs( val ); if ( val > best_val ) { best_val = val; p = j; } } if ( a[row[p]][i] == 0.0 ) { success = FALSE; break; } if ( i != p ) { tmp = row[i]; row[i] = row[p]; row[p] = tmp; } for ( j = i+1; j < n; j++ ) { if ( a[row[i]][i] == 0.0 ) { success = FALSE; break; } m = a[row[j]][i] / a[row[i]][i]; for ( k = i+1; k < n; k++ ) a[row[j]][k] -= m * a[row[i]][k]; for ( v = 0; v < n_values; v++ ) solution[row[j]][v] -= m * solution[row[i]][v]; } if ( !success ) break; } if ( success && a[row[n-1]][n-1] == 0.0 ) success = FALSE; if ( success ) { for ( i = n-1; i >= 0; --i ) { for ( j = i+1; j < n; j++ ) { scale_factor = a[row[i]][j]; for ( v = 0; v < n_values; v++ ) solution[row[i]][v] -= scale_factor * solution[row[j]][v]; } for ( v = 0; v < n_values; v++ ) solution[row[i]][v] /= a[row[i]][i]; } } free( s ); return( success ); } int scaled_maximal_pivoting_gaussian_elimination_real(int n, double **coefs, int n_values, double **values ) { int i, j, v, *row; double **a, **solution; int success; row = (int *) alloc1d( n ); /* Ugly and wasteful but OK for 1D array */ a = alloc2d( n, n ); solution = alloc2d( n, n_values ); for (i = 0; i < n; i++) { for ( j = 0; j < n; j++ ) a[i][j] = coefs[i][j]; for ( v = 0; v < n_values; v++ ) solution[i][v] = values[v][i]; } success = scaled_maximal_pivoting_gaussian_elimination( n, row, a, n_values, solution ); if ( success ) { for ( i = 0; i < n; i++ ) { for ( v = 0; v < n_values; v++ ) { values[v][i] = solution[row[i]][v]; } } } free(a); free(solution); free(row); return ( success ); } /** Computes the inverse of a square matrix. */ static int invert_4x4_matrix(double matrix[4][4], /**< Input matrix */ double inverse[4][4]) /**< Output (inverted) matrix */ { int result; int i, j; double **mtmp; double **itmp; mtmp = alloc2d(4, 4); itmp = alloc2d(4, 4); /* Start off with the identity matrix. */ for ( i = 0; i < 4; i++ ) { for ( j = 0; j < 4; j++ ) { itmp[i][j] = 0.0; mtmp[i][j] = matrix[i][j]; } itmp[i][i] = 1.0; } result = scaled_maximal_pivoting_gaussian_elimination_real( 4, mtmp, 4, itmp ); if ( result ) { for ( i = 0; i < 4; i++) { for ( j = 0; j < 4; j++ ) { inverse[i][j] = itmp[j][i]; } } } free(mtmp); free(itmp); return (result ? MI_NOERROR : MI_ERROR); } /** Fills in the transform with the identity matrix. */ static void mimake_identity_transform(mi_lin_xfm_t transform) { int i, j; for (i = 0; i < MI2_LIN_XFM_SIZE; i++) { for (j = 0; j < MI2_LIN_XFM_SIZE; j++) { transform[i][j] = 0.0; } transform[i][i] = 1.0; } } /** Function for inverting a MINC linear transform. */ int miinvert_transform(mi_lin_xfm_t transform, mi_lin_xfm_t inverse ) { int result; result = invert_4x4_matrix( transform, inverse ); if (result != MI_NOERROR) { mimake_identity_transform(inverse); } return ( result ); } /** Function to read a scalar variable of HDF5 type \a type_id from the given * \a path relative to the HDF5 file or group \a loc_id. */ int miget_scalar(hid_t loc_id, hid_t type_id, const char *path, void *data) { hid_t dset_id; hid_t spc_id; int result = MI_ERROR; H5E_BEGIN_TRY { dset_id = H5Dopen1(loc_id, path); } H5E_END_TRY; if (dset_id >= 0) { spc_id = H5Dget_space(dset_id); if (spc_id >= 0) { if (H5Sget_simple_extent_ndims(spc_id) == 0) { if (H5Dread(dset_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) >= 0) { result = MI_NOERROR; } } H5Sclose(spc_id); } H5Dclose(dset_id); } return (result); } minc-2.2.00/libsrc2/record.c0000644000265600003100000000641312027132662012426 00000000000000/**\file record.c * \brief MINC 2.0 Record Functions * \author Bert Vincent */ #include #include "minc2.h" #include "minc2_private.h" /** This method gets the name of the record dimension * TODO: set record name?? */ int miget_record_name(mihandle_t volume, char **name) { return (MI_NOERROR); } /** This method gets the length (i.e., number of fields in the case of * uniform records and number of bytes for non_uniform ones) of the * record. */ int miget_record_length(mihandle_t volume, int *length) { if (volume == NULL || length == NULL) { return (MI_ERROR); } if (volume->volume_class == MI_CLASS_UNIFORM_RECORD || volume->volume_class == MI_CLASS_NON_UNIFORM_RECORD) { *length = H5Tget_nmembers(volume->ftype_id); return (MI_NOERROR); } return (MI_ERROR); } /** This method returns the field name for the given field index. Memory * for returned string is allocated on the heap and should be released using * mifree_name(). */ int miget_record_field_name(mihandle_t volume, int index, char **name) { if (volume == NULL || name == NULL) { return (MI_ERROR); } /* Get the field name. The H5Tget_member_name() function allocates * the memory for the string using malloc(), so we can return the * pointer directly without any further manipulations. */ *name = H5Tget_member_name(volume->ftype_id, index); if (*name == NULL) { return (MI_ERROR); } return (MI_NOERROR); } /** This method sets a field name for the volume record. The volume * must be of class "MI_CLASS_UNIFORM_RECORD". The size of record * type will be increased if necessary to accomodate the new field. */ int miset_record_field_name(mihandle_t volume, int index, const char *name) { hid_t mtype_id; hid_t ftype_id; int offset; if (volume == NULL || name == NULL) { return (MI_ERROR); } if (volume->volume_class != MI_CLASS_UNIFORM_RECORD && volume->volume_class != MI_CLASS_NON_UNIFORM_RECORD) { return (MI_ERROR); } /* Get the type of the record's fields. This is recorded as the * type of the volume. */ ftype_id = mitype_to_hdftype(volume->volume_type, FALSE); mtype_id = mitype_to_hdftype(volume->volume_type, TRUE); /* Calculate the offset of the new member. */ offset = index * H5Tget_size(ftype_id); /* If the offset plus the size of the member is larger than the * current size of the structure, increase the size of the structure. */ if (offset + H5Tget_size(ftype_id) > H5Tget_size(volume->ftype_id)) { H5Tset_size(volume->ftype_id, offset + H5Tget_size(ftype_id)); } if (offset + H5Tget_size(mtype_id) > H5Tget_size(volume->mtype_id)) { H5Tset_size(volume->mtype_id, offset + H5Tget_size(mtype_id)); } /* Actually define the field within the structure. */ H5Tinsert(volume->ftype_id, name, offset, ftype_id); H5Tinsert(volume->mtype_id, name, offset, mtype_id); /* Delete the HDF5 type object returned by mitype_to_hdftype(). */ H5Tclose(ftype_id); H5Tclose(mtype_id); return (MI_NOERROR); } minc-2.2.00/libsrc2/slice.c0000644000265600003100000002701512027132662012250 00000000000000/** * \file slice.c * \brief MINC 2.0 Slice/volume scale functions * \author Bert Vincent * * These functions get and set the real minimum and maximum values for * either a particular slice or an entire volume. * * Each of the slice scale functions take an array of long integer * coordinates to specify the slice to consider. The order of these * coordinates is always raw file (voxel) order, rather than the * apparent order. * * If slice scaling is not enabled, the slice scaling functions will * use the appropriate global volume scale value. ************************************************************************/ #include #include #include "minc2.h" #include "minc2_private.h" #define MIRW_SCALE_SET 0x0001 #define MIRW_SCALE_GET 0x0000 #define MIRW_SCALE_MIN 0x0002 #define MIRW_SCALE_MAX 0x0000 /* Forward declaration */ static int mirw_volume_minmax(int opcode, mihandle_t volume, double *value); /** Get the minimum or maximum value for the slice containing the given point. */ static int mirw_slice_minmax(int opcode, mihandle_t volume, const unsigned long start_positions[], int array_length, double *value) { hid_t dset_id; hid_t fspc_id; hid_t mspc_id; hssize_t hdf_start[MI2_MAX_VAR_DIMS]; hsize_t hdf_count[MI2_MAX_VAR_DIMS]; unsigned long count[MI2_MAX_VAR_DIMS]; int dir[MI2_MAX_VAR_DIMS]; int ndims; int i; int result; if (volume == NULL || value == NULL) { return (MI_ERROR); /* Bad parameters */ } if (!volume->has_slice_scaling) { return mirw_volume_minmax(opcode, volume, value); } if (opcode & MIRW_SCALE_MIN) { dset_id = volume->imin_id; } else { dset_id = volume->imax_id; } fspc_id = H5Dget_space(dset_id); if (fspc_id < 0) { return (MI_ERROR); } ndims = H5Sget_simple_extent_ndims(fspc_id); if (ndims > array_length) { ndims = array_length; } for (i = 0; i < ndims; i++) { count[i] = 1; } mitranslate_hyperslab_origin(volume, start_positions, count, hdf_start, hdf_count, dir); result = H5Sselect_elements(fspc_id, H5S_SELECT_SET, 1, (const hsize_t **) &hdf_start); if (result < 0) { return (MI_ERROR); } /* Create a trivial scalar space to read the single value. */ mspc_id = H5Screate(H5S_SCALAR); if (opcode & MIRW_SCALE_SET) { result = H5Dwrite(dset_id, H5T_NATIVE_DOUBLE, mspc_id, fspc_id, H5P_DEFAULT, value); } else { result = H5Dread(dset_id, H5T_NATIVE_DOUBLE, mspc_id, fspc_id, H5P_DEFAULT, value); } if (result < 0) { return (MI_ERROR); } H5Sclose(fspc_id); H5Sclose(mspc_id); return (MI_NOERROR); } /** This function sets \a slice_min to the minimum real value of voxels in the slice containing the coordinates \a start_positions. The \a array_length may be less than or equal to the number of dimensions in the volume, extra coordinates will be ignored. Specifying too few coordinates will trigger an error. Coordinates must always be specified in raw file order. */ int miget_slice_min(mihandle_t volume, const unsigned long start_positions[], int array_length, double *slice_min) { return (mirw_slice_minmax(MIRW_SCALE_MIN + MIRW_SCALE_GET, volume, start_positions, array_length, slice_min)); } /** This function sets \a slice_max to the maximum real value of voxels in the slice containing the coordinates \a start_positions. The \a array_length may be less than or equal to the number of dimensions in the volume, extra coordinates will be ignored. Specifying too few coordinates will trigger an error. Coordinates must always be specified in raw file order. */ int miget_slice_max(mihandle_t volume, const unsigned long start_positions[], int array_length, double *slice_max) { return (mirw_slice_minmax(MIRW_SCALE_MAX + MIRW_SCALE_GET, volume, start_positions, array_length, slice_max)); } /** This function sets minimum real value of values in the slice containing the coordinates \a start_positions. The \a array_length may be less than or equal to the number of dimensions in the volume, extra coordinates will be ignored. Specifying too few coordinates will trigger an error. Coordinates must always be specified in raw file order. */ int miset_slice_min(mihandle_t volume, const unsigned long start_positions[], int array_length, double slice_min) { return (mirw_slice_minmax(MIRW_SCALE_MIN + MIRW_SCALE_SET, volume, start_positions, array_length, &slice_min)); } /** This function sets maximum real value of values in the slice containing the coordinates \a start_positions. The \a array_length may be less than or equal to the number of dimensions in the volume, extra coordinates will be ignored. Specifying too few coordinates will trigger an error. Coordinates must always be specified in raw file order. */ int miset_slice_max(mihandle_t volume, const unsigned long start_positions[], int array_length, double slice_max) { return (mirw_slice_minmax(MIRW_SCALE_MAX + MIRW_SCALE_SET, volume, start_positions, array_length, &slice_max)); } /** This function gets both the minimum and maximum real value of voxels in the slice containing the coordinates \a start_positions. The \a array_length may be less than or equal to the number of dimensions in the volume, extra coordinates will be ignored. Specifying too few coordinates will trigger an error. Coordinates must always be specified in raw file order. */ int miget_slice_range(mihandle_t volume, const unsigned long start_positions[], int array_length, double *slice_max, double *slice_min) { int r; r = mirw_slice_minmax(MIRW_SCALE_MAX + MIRW_SCALE_GET, volume, start_positions, array_length, slice_max); if (r < 0) { *slice_max = 1.0; } r = mirw_slice_minmax(MIRW_SCALE_MIN + MIRW_SCALE_GET, volume, start_positions, array_length, slice_min); if (r < 0) { *slice_min = 0.0; } return (MI_NOERROR); } /** This function the minimum and maximum real value of voxels in the slice containing the coordinates \a start_positions. The \a array_length may be less than or equal to the number of dimensions in the volume, extra coordinates will be ignored. Specifying too few coordinates will trigger an error. Coordinates must always be specified in raw file order. */ int miset_slice_range(mihandle_t volume, const unsigned long start_positions[], int array_length, double slice_max, double slice_min) { int r; r = mirw_slice_minmax(MIRW_SCALE_MAX + MIRW_SCALE_SET, volume, start_positions, array_length, &slice_max); if (r < 0) { return (MI_ERROR); } r = mirw_slice_minmax(MIRW_SCALE_MIN + MIRW_SCALE_SET, volume, start_positions, array_length, &slice_min); if (r < 0) { return (MI_ERROR); } return (MI_NOERROR); } /*! Internal function to read/write the volume global minimum or * maximum real range. */ static int mirw_volume_minmax(int opcode, mihandle_t volume, double *value) { hid_t dset_id; hid_t fspc_id; hid_t mspc_id; int result; if (volume == NULL || value == NULL) { return (MI_ERROR); } if (volume->has_slice_scaling) { return (MI_ERROR); } if ((opcode & MIRW_SCALE_SET) == 0) { if (opcode & MIRW_SCALE_MIN) { *value = volume->scale_min; return (MI_NOERROR); } else { *value = volume->scale_max; return (MI_NOERROR); } } if (opcode & MIRW_SCALE_MIN) { dset_id = volume->imin_id; } else { dset_id = volume->imax_id; } fspc_id = H5Dget_space(dset_id); if (fspc_id < 0) { return (MI_ERROR); } /* Make certain the value is a scalar. */ if (H5Sget_simple_extent_ndims(fspc_id) != 0) { return (MI_ERROR); } /* Create a trivial scalar space to read the single value. */ mspc_id = H5Screate(H5S_SCALAR); if (opcode & MIRW_SCALE_SET) { result = H5Dwrite(dset_id, H5T_NATIVE_DOUBLE, mspc_id, fspc_id, H5P_DEFAULT, value); } else { result = H5Dread(dset_id, H5T_NATIVE_DOUBLE, mspc_id, fspc_id, H5P_DEFAULT, value); } if (result < 0) { return (MI_ERROR); } /* Update the "cached" values. */ if (opcode & MIRW_SCALE_MIN) { volume->scale_min = *value; } else { volume->scale_max = *value; } H5Sclose(fspc_id); H5Sclose(mspc_id); return (MI_NOERROR); } /** This function returns the minimum real value of voxels in the entire \a volume. If per-slice scaling is enabled, this function will return an error. */ int miget_volume_min(mihandle_t volume, double *vol_min) { return (mirw_volume_minmax(MIRW_SCALE_MIN + MIRW_SCALE_GET, volume, vol_min)); } /** This function returns the maximum real value of voxels in the entire \a volume. If per-slice scaling is enabled, this function will return an error. */ int miget_volume_max(mihandle_t volume, double *vol_max) { return (mirw_volume_minmax(MIRW_SCALE_MAX + MIRW_SCALE_GET, volume, vol_max)); } /** This function sets the minimum real value of voxels in the entire \a volume. If per-slice scaling is enabled, this function will return an error. */ int miset_volume_min(mihandle_t volume, double vol_min) { return (mirw_volume_minmax(MIRW_SCALE_MIN + MIRW_SCALE_SET, volume, &vol_min)); } /** This function sets the maximum real value of voxels in the entire \a volume. If per-slice scaling is enabled, this function will return an error. */ int miset_volume_max(mihandle_t volume, double vol_max) { return (mirw_volume_minmax(MIRW_SCALE_MAX + MIRW_SCALE_SET, volume, &vol_max)); } /** This function retrieves the maximum and minimum real values of voxels in the entire \a volume. If per-slice scaling is enabled, this function will return an error. */ int miget_volume_range(mihandle_t volume, double *vol_max, double *vol_min) { int r; r = mirw_volume_minmax(MIRW_SCALE_MAX + MIRW_SCALE_GET, volume, vol_max); if (r < 0) { return (MI_ERROR); } r = mirw_volume_minmax(MIRW_SCALE_MIN + MIRW_SCALE_GET, volume, vol_min); if (r < 0) { return (MI_ERROR); } return (MI_NOERROR); } /** This function sets the maximum and minimum real values of voxels in the entire \a volume. If per-slice scaling is enabled, this function will return an error. */ int miset_volume_range(mihandle_t volume, double vol_max, double vol_min) { int r; r = mirw_volume_minmax(MIRW_SCALE_MAX + MIRW_SCALE_SET, volume, &vol_max); if (r < 0) { return (MI_ERROR); } r = mirw_volume_minmax(MIRW_SCALE_MIN + MIRW_SCALE_SET, volume, &vol_min); if (r < 0) { return (MI_ERROR); } return (MI_NOERROR); } /*! Function to get the volume's slice-scaling flag. */ int miget_slice_scaling_flag(mihandle_t volume, miboolean_t *slice_scaling_flag) { if (volume == NULL || slice_scaling_flag == NULL) { return (MI_ERROR); } *slice_scaling_flag = volume->has_slice_scaling; return (MI_NOERROR); } /*! Function to set the volume's slice-scaling flag. */ int miset_slice_scaling_flag(mihandle_t volume, miboolean_t slice_scaling_flag) { if (volume == NULL) { return (MI_ERROR); } volume->has_slice_scaling = slice_scaling_flag; return (MI_NOERROR); } minc-2.2.00/libsrc2/valid.c0000644000265600003100000001022112027132662012237 00000000000000/** \file valid.c * \brief MINC 2.0 Valid Min/Max and Range Functions. * \author Bert Vincent * * These functions set and get the valid range of the datatype of a volume. * This range refers to the maximum values of the datatype as stored in the * file, not to the range of the "real" values. For example, many scanners * store voxel data as unsigned, 12-bit integers. Since there is no explicit * 12-bit data type in MINC, we may use these functions to set the valid range * in the image to 0..4095. ************************************************************************/ #include #include #include "minc2.h" #include "minc2_private.h" /** This function gets the maximum valid value specific to the data * type of the \a volume parameter. * \retval MI_ERROR on failure * \retval MI_NOERROR on success */ int miget_volume_valid_max(mihandle_t volume, /**< MINC 2.0 volume handle */ double *valid_max) /**< the output value */ { if (volume == NULL || valid_max == NULL) { return (MI_ERROR); /* Invalid arguments */ } *valid_max = volume->valid_max; return (MI_NOERROR); } /** This function sets the maximum valid value specific to the data * type of the \a volume parameter. * \retval MI_ERROR on failure * \retval MI_NOERROR on success */ int miset_volume_valid_max(mihandle_t volume, /**< MINC 2.0 volume handle */ double valid_max) /**< the new maximum value */ { if (volume == NULL) { return (MI_ERROR); /* Invalid arguments */ } /* TODO?: Should we require valid max to have some specific relationship * to valid_min? */ volume->valid_max = valid_max; misave_valid_range(volume); return (MI_NOERROR); } /** This function gets the minimum valid value specific to the data * type of the \a volume parameter. * \retval MI_ERROR on failure * \retval MI_NOERROR on success */ int miget_volume_valid_min(mihandle_t volume, /**< MINC 2.0 volume handle */ double *valid_min) /**< the output value */ { if (volume == NULL || valid_min == NULL) { return (MI_ERROR); /* Invalid arguments. */ } *valid_min = volume->valid_min; return (MI_NOERROR); } /** This function sets the minimum valid value specific to the data * type of the \a volume parameter. * \retval MI_ERROR on failure * \retval MI_NOERROR on success */ int miset_volume_valid_min(mihandle_t volume, /**< MINC 2.0 volume handle */ double valid_min) /**< the new minimum value */ { if (volume == NULL) { return (MI_ERROR); /* Invalid arguments */ } volume->valid_min = valid_min; misave_valid_range(volume); return (MI_NOERROR); } /** This function gets the minimum and maximum valid value specific to the * data type of the \a volume parameter. * \retval MI_ERROR on failure * \retval MI_NOERROR on success */ int miget_volume_valid_range(mihandle_t volume, /**< MINC 2.0 volume handle */ double *valid_max, /**< the output maximum value */ double *valid_min) /**< the output minimum value */ { if (volume == NULL || valid_min == NULL || valid_max == NULL) { return (MI_ERROR); } *valid_min = volume->valid_min; *valid_max = volume->valid_max; return (MI_NOERROR); } /** This function sets the minimum and maximum valid value specific to the * data type of the \a volume parameter. * \retval MI_ERROR on failure * \retval MI_NOERROR on success */ int miset_volume_valid_range(mihandle_t volume, /**< MINC 2.0 volume handle */ double valid_max, /**< the new maximum value */ double valid_min) /**< the output minimum value */ { if (volume == NULL) { return (MI_ERROR); } /* TODO?: Again, should we require minvalid_min = valid_min; volume->valid_max = valid_max; misave_valid_range(volume); return (MI_NOERROR); } minc-2.2.00/libsrc2/volprops.c0000644000265600003100000003217112027132662013034 00000000000000/** \file volprops.c * \brief MINC 2.0 Volume properties functions * \author Leila Baghdadi * * These functions manipulate "volume properties" objects, which are * used to control several options related to MINC 2.0 volume structure. * These include compression, blocking, multi-resolution, and record s * structure. * * This approach was adopted with the intent that it would make the * default volume creation as simple as possible, while allowing a * lot of control for more advanced applications. This approach to * managing properties is also believed to be more readily extensible than * any obvious alternative. ************************************************************************/ #define _GNU_SOURCE 1 #include #include #include "minc2.h" #include "minc2_private.h" /** * \defgroup mi2VPrp MINC 2.0 Volume Properties Functions */ /** Maximum number of elements in a filter parameter list. */ #define MI2_MAX_CD_ELEMENTS 100 /*! Create a volume property list. The new list will be returned in the * \a props parameter. When the program is finished * using the property list it should call mifree_volume_props() to free the * memory associated with the list. * \param props A pointer to the returned volume properties handle. * \ingroup mi2VPrp */ int minew_volume_props(mivolumeprops_t *props) { mivolumeprops_t handle; handle = (mivolumeprops_t)malloc(sizeof(struct mivolprops)); if (handle == NULL) { return (MI_ERROR); } /* Initialize all the fields. */ handle->enable_flag = FALSE; handle->depth = 0; handle->compression_type = MI_COMPRESS_NONE; handle->zlib_level = 0; handle->edge_count = 0; handle->edge_lengths = NULL; handle->max_lengths = 0; handle->record_length = 0; handle->record_name = NULL; handle->template_flag = 0; *props = handle; return (MI_NOERROR); } /*! Destroy a volume property list. * \param props The volume property list to delete. * \ingroup mi2VPrp */ int mifree_volume_props(mivolumeprops_t props) { if (props == NULL) { return (MI_ERROR); } if (props->edge_lengths != NULL) { free(props->edge_lengths); } if (props->record_name != NULL) { free(props->record_name); } free(props); return (MI_NOERROR); } /*! Get a copy of the volume property list. When the program is finished * using the property list it should call mifree_volume_props() to free the * memory associated with the list. * \param volume A volume handle * \param props A pointer to the returned volume properties handle. * \ingroup mi2VPrp */ int miget_volume_props(mihandle_t volume, mivolumeprops_t *props) { mivolumeprops_t handle; hid_t hdf_vol_dataset; hid_t hdf_plist; int nfilters; unsigned int flags; size_t cd_nelmts; unsigned int cd_values[MI2_MAX_CD_ELEMENTS]; char fname[MI2_CHAR_LENGTH]; int fcode; if (volume->hdf_id < 0) { return (MI_ERROR); } hdf_vol_dataset = midescend_path(volume->hdf_id, "/minc-2.0/image/0/image"); if (hdf_vol_dataset < 0) { return (MI_ERROR); } hdf_plist = H5Dget_create_plist(hdf_vol_dataset); if (hdf_plist < 0) { return (MI_ERROR); } handle = (mivolumeprops_t)malloc(sizeof(struct mivolprops)); if (handle == NULL) { return (MI_ERROR); } /* Get the layout of the raw data for a dataset. */ if (H5Pget_layout(hdf_plist) == H5D_CHUNKED) { hsize_t dims[MI2_MAX_VAR_DIMS]; int i; /* Returns chunk dimensionality */ handle->edge_count = H5Pget_chunk(hdf_plist, MI2_MAX_VAR_DIMS, dims); if (handle->edge_count < 0) { return (MI_ERROR); } handle->edge_lengths = (int *)malloc(handle->edge_count*sizeof(int)); if (handle->edge_lengths == NULL) { return (MI_ERROR); } for (i = 0; i < handle->edge_count; i++) { handle->edge_lengths[i] = dims[i]; } /* Get the number of filters in the pipeline */ nfilters = H5Pget_nfilters(hdf_plist); if (nfilters == 0) { handle->zlib_level = 0; handle->compression_type = MI_COMPRESS_NONE; } else { for (i = 0; i < nfilters; i++) { cd_nelmts = MI2_MAX_CD_ELEMENTS; fcode = H5Pget_filter1(hdf_plist, i, &flags, &cd_nelmts, cd_values, sizeof(fname), fname); switch (fcode) { case H5Z_FILTER_DEFLATE: handle->compression_type = MI_COMPRESS_ZLIB; handle->zlib_level = cd_values[0]; break; case H5Z_FILTER_SHUFFLE: break; case H5Z_FILTER_FLETCHER32: break; case H5Z_FILTER_SZIP: break; default: break; } } } } else { handle->edge_count = 0; handle->edge_lengths = NULL; handle->zlib_level = 0; handle->compression_type = MI_COMPRESS_NONE; } *props = handle; H5Pclose(hdf_plist); H5Dclose(hdf_vol_dataset); return (MI_NOERROR); } /*! Set multi-resolution properties. The \a enable_flag determines * whether or not thumbnail images will be calculated at all. The \a * depth parameter determines the lowest-resolution image that will be * available. The full resolution image is considered to be image #0, * the half resolution image is image #1, the quarter-resolution image * is #2, etc. Therefore a \a depth value of 2 implies both the half * and quarter resolution thumbnails will be calculated and stored in * the file. * \param props A volume property list handle * \param enable_flag TRUE if multiresolution support should be enabled in * this file. * \param depth The maximum depth of multiresolution data * to support. * \ingroup mi2VPrp */ int miset_props_multi_resolution(mivolumeprops_t props, miboolean_t enable_flag, int depth) { if (props == NULL || depth > MI2_MAX_RESOLUTION_GROUP || depth <= 0) { return (MI_ERROR); } props->enable_flag = enable_flag; props->depth = depth; return (MI_NOERROR); } /*! Get multi-resolution properties. Returns the value of the \a enable_flag * and \a depth parameters. * \param props A volume property list handle * \param enable_flag Pointer to a boolean which will be set to TRUE if * multiresolution has been enabled. * \param depth Pointer to a integer which will contain the maximum resolution * depth enabled if multiresolution is enabled. * \ingroup mi2VPrp */ int miget_props_multi_resolution(mivolumeprops_t props, miboolean_t *enable_flag, int *depth) { if (props == NULL || enable_flag == NULL || depth == NULL) { return (MI_ERROR); } *enable_flag = props->enable_flag; *depth = props->depth; return (MI_NOERROR); } /*! Select a different resolution from a multi-resolution image. * \ingroup mi2VPrp */ int miselect_resolution(mihandle_t volume, int depth) { hid_t grp_id; char path[MI2_MAX_PATH]; if ( volume->hdf_id < 0 || depth > MI2_MAX_RESOLUTION_GROUP || depth < 0) { return (MI_ERROR); } grp_id = H5Gopen1(volume->hdf_id, "/minc-2.0/image"); if (grp_id < 0) { return (MI_ERROR); } /* Check given depth with the available depth in file. Make sure the selected resolution does exist. */ if (depth > volume->create_props->depth) { return (MI_ERROR); } else if (depth != 0) { if (minc_update_thumbnail(volume, grp_id, 0, depth) < 0) { return (MI_ERROR); } } volume->selected_resolution = depth; if (volume->image_id >= 0) { H5Dclose(volume->image_id); } sprintf(path, "%d/image", depth); volume->image_id = H5Dopen1(grp_id, path); if (volume->volume_class == MI_CLASS_REAL) { if (volume->imax_id >= 0) { H5Dclose(volume->imax_id); } sprintf(path, "%d/image-max", depth); volume->imax_id = H5Dopen1(grp_id, path); if (volume->imin_id >= 0) { H5Dclose(volume->imin_id); } sprintf(path, "%d/image-min", depth); volume->imin_id = H5Dopen1(grp_id, path); } return (MI_NOERROR); } /*! Compute or recompute all resolution groups. * * \ingroup mi2VPrp */ int miflush_from_resolution(mihandle_t volume, int depth) { if ( volume->hdf_id < 0 || depth > MI2_MAX_RESOLUTION_GROUP || depth <= 0) { return (MI_ERROR); } if (depth > volume->create_props->depth) { return (MI_ERROR); } else { if (minc_update_thumbnails(volume) < 0) { return (MI_ERROR); } volume->is_dirty = FALSE; } return (MI_NOERROR); } /*! Set compression type for a volume property list * Note that enabling compression will automatically * enable blocking with default parameters. * \param props A volume properties list * \param compression_type The type of compression to use (MI_COMPRESS_NONE * or MI_COMPRESS_ZLIB) * \ingroup mi2VPrp */ int miset_props_compression_type(mivolumeprops_t props, micompression_t compression_type) { int i; int edge_lengths[MI2_MAX_VAR_DIMS]; if (props == NULL) { return (MI_ERROR); } switch (compression_type) { case MI_COMPRESS_NONE: props->compression_type = MI_COMPRESS_NONE; break; case MI_COMPRESS_ZLIB: props->compression_type = MI_COMPRESS_ZLIB; props->zlib_level = MI2_DEFAULT_ZLIB_LEVEL; for (i = 0; i < MI2_MAX_VAR_DIMS; i++) { edge_lengths[i] = MI2_CHUNK_SIZE; } miset_props_blocking(props, MI2_MAX_VAR_DIMS, edge_lengths); break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Get compression type for a volume property list * \param props A volume property list handle * \param compression_type A pointer to a variable to which the current * compression type will be assigned. * \ingroup mi2VPrp */ int miget_props_compression_type(mivolumeprops_t props, micompression_t *compression_type) { if (props == NULL) { return (MI_ERROR); } *compression_type = props->compression_type; return (MI_NOERROR); } /*! Set zlib compression properties for a volume list. The \a zlib_level * parameter may range from 1 to 9, where higher numbers request that the * library attempt to use more memory (and possibly processing power) to * achieve the highest possible compression ratio. * * \param props A volume property list handle * \param zlib_level An integer specifying the desired compression level. * \ingroup mi2VPrp */ int miset_props_zlib_compression(mivolumeprops_t props, int zlib_level) { if (props == NULL || zlib_level > MI2_MAX_ZLIB_LEVEL) { return (MI_ERROR); } props->zlib_level = zlib_level; return (MI_NOERROR); } /*! Get zlib compression properties from a volume property list. * \param props A volume property list handle * \param zlib_level Pointer to an integer variable that will receive the * current compression level. * \ingroup mi2VPrp */ int miget_props_zlib_compression(mivolumeprops_t props, int *zlib_level) { if (props == NULL) { return (MI_ERROR); } *zlib_level = props->zlib_level; return (MI_NOERROR); } /*! Set blocking structure properties for the volume * \param props A volume property list handle * \param edge_count * \param edge_lengths * \ingroup mi2VPrp */ int miset_props_blocking(mivolumeprops_t props, int edge_count, const int *edge_lengths) { int i; if (props == NULL || edge_count > MI2_MAX_VAR_DIMS) { return (MI_ERROR); } if (props->edge_lengths != NULL) { free(props->edge_lengths); props->edge_lengths = NULL; } props->edge_count = edge_count; if (edge_count != 0) { props->edge_lengths = (int *) malloc(edge_count*sizeof(int)); if (props->edge_lengths == NULL) { return (MI_ERROR); } for (i=0; i< edge_count; i++){ props->edge_lengths[i] = edge_lengths[i]; } } return (MI_NOERROR); } /*! Get blocking structure properties for the volume * \param props The properties structure from which to get the information * \param edge_count Returns the number of edges (dimensions) in a block * \param edge_lengths The lengths of the edges * \param max_lengths The number of elements of the edge_lengths array * \ingroup mi2VPrp */ int miget_props_blocking(mivolumeprops_t props, int *edge_count, int *edge_lengths, int max_lengths) { int i; if (props == NULL) { return (MI_ERROR); } *edge_count = props->edge_count; /* If max_lengths is greater than the actual edge count, reduce max_lengths * to the edge_count */ if (max_lengths > props->edge_count) { max_lengths = props->edge_count; } edge_lengths = (int *) malloc(max_lengths *sizeof(int)); for (i=0; i< max_lengths; i++){ edge_lengths[i] = props->edge_lengths[i]; } return (MI_NOERROR); } /*! Set properties for uniform/nonuniform record dimension * \ingroup mi2VPrp */ int miset_props_record(mivolumeprops_t props, long record_length, char *record_name) { if (props == NULL) { return (MI_ERROR); } if (record_length > 0) { props->record_length = record_length; } if (props->record_name != NULL) { free(props->record_name); props->record_name = NULL; } props->record_name = strdup(record_name); return (MI_NOERROR); } /*! Set the template volume flag * \ingroup mi2VPrp */ int miset_props_template(mivolumeprops_t props, int template_flag) { if (props == NULL) { return (MI_ERROR); } props->template_flag = template_flag; return (MI_NOERROR); } minc-2.2.00/libsrc2/volume.c0000644000265600003100000012171412027132662012461 00000000000000/** \file volume.c * \brief MINC 2.0 Volume Functions * \author Leila Baghdadi, Bert Vincent * * Functions to create, open, and close MINC volume objects. ************************************************************************/ #include #include #include #include #include #include "minc2.h" #include "minc2_private.h" /** * \defgroup mi2Vol MINC 2.0 Volume Functions */ /* Forward declarations */ static void miinit_default_range(mitype_t mitype, double *valid_max, double *valid_min); static void miread_valid_range(mihandle_t volume, double *valid_max, double *valid_min); static int _miset_volume_class(mihandle_t volume, miclass_t volclass); static int _miget_volume_class(mihandle_t volume, miclass_t *volclass); /** Create the actual image for the volume. Note that the image dataset muct be created in the hierarchy before the image data can be added. \ingroup mi2Vol */ int micreate_volume_image(mihandle_t volume) { char dimorder[MI2_CHAR_LENGTH]; int i; hid_t dataspace_id; hid_t dset_id; hsize_t hdf_size[MI2_MAX_VAR_DIMS]; /* Try creating IMAGE dataset i.e. /minc-2.0/image/0/image */ dimorder[0] = '\0'; /* Set string to empty */ for (i = 0; i < volume->number_of_dims; i++) { hdf_size[i] = volume->dim_handles[i]->length; /* Create the dimorder string, ordered comma-separated list of dimension names. */ strcat(dimorder, volume->dim_handles[i]->name); if (i != volume->number_of_dims - 1) { strcat(dimorder, ","); } } /* Create a SIMPLE dataspace */ dataspace_id = H5Screate_simple(volume->number_of_dims, hdf_size, NULL); if (dataspace_id < 0) { return (MI_ERROR); } dset_id = H5Dcreate1(volume->hdf_id, "/minc-2.0/image/0/image", volume->ftype_id, dataspace_id, volume->plist_id); if (dset_id < 0) { return (MI_ERROR); } volume->image_id = dset_id; hdf_var_declare(volume->hdf_id, "image", "/minc-2.0/image/0/image", volume->number_of_dims, hdf_size); /* Create the dimorder attribute, ordered comma-separated list of dimension names. */ miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, strlen(dimorder), dimorder); H5Sclose(dataspace_id); if (volume->volume_class == MI_CLASS_REAL) { int ndims; hid_t dcpl_id; double dtmp; dcpl_id = H5Pcreate(H5P_DATASET_CREATE); if (dcpl_id < 0) { return (MI_ERROR); } if (volume->has_slice_scaling) { /* TODO: Find the slowest-varying spatial dimension; that forms * the basis for the image-min and image-max variables. Right * now this is an oversimplification! */ ndims = volume->number_of_dims - 2; dataspace_id = H5Screate_simple(ndims, hdf_size, NULL); } else { ndims = 0; dataspace_id = H5Screate(H5S_SCALAR); } if (ndims != 0) { dimorder[0] = '\0'; /* Set string to empty */ for (i = 0; i < ndims; i++) { /* Create the dimorder string, ordered comma-separated list of dimension names. */ strcat(dimorder, volume->dim_handles[i]->name); if (i != volume->number_of_dims - 1) { strcat(dimorder, ","); } } } /* Create the image minimum dataset for FULL-RESOLUTION storage of data */ dtmp = 0.0; H5Pset_fill_value(dcpl_id, H5T_NATIVE_DOUBLE, &dtmp); dset_id = H5Dcreate1(volume->hdf_id, "/minc-2.0/image/0/image-min", H5T_IEEE_F64LE, dataspace_id, dcpl_id); if (ndims != 0) { miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, strlen(dimorder), dimorder); } volume->imin_id = dset_id; hdf_var_declare(volume->hdf_id, "image-min", "/minc-2.0/image/0/image-min", ndims, hdf_size); /* Create the image maximum dataset for FULL-RESOLUTION storage of data */ dtmp = 1.0; H5Pset_fill_value(dcpl_id, H5T_NATIVE_DOUBLE, &dtmp); dset_id = H5Dcreate1(volume->hdf_id, "/minc-2.0/image/0/image-max", H5T_IEEE_F64LE, dataspace_id, dcpl_id); if (ndims != 0) { miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, strlen(dimorder), dimorder); } volume->imax_id = dset_id; hdf_var_declare(volume->hdf_id, "image-max", "/minc-2.0/image/0/image-max", ndims, hdf_size); H5Sclose(dataspace_id); H5Pclose(dcpl_id); } return (MI_NOERROR); } /** Set up the array of conversions from voxel to world coordinate order. */ static int miset_volume_world_indices(mihandle_t hvol) { int i; for (i = 0; i < hvol->number_of_dims; i++) { midimhandle_t hdim = hvol->dim_handles[i]; hdim->world_index = -1; if (hdim->class == MI_DIMCLASS_SPATIAL) { if (!strcmp(hdim->name, MIxspace)) { hdim->world_index = MI2_X; } else if (!strcmp(hdim->name, MIyspace)) { hdim->world_index = MI2_Y; } else if (!strcmp(hdim->name, MIzspace)) { hdim->world_index = MI2_Z; } } else if (hdim->class == MI_DIMCLASS_SFREQUENCY) { if (!strcmp(hdim->name, MIxfrequency)) { hdim->world_index = MI2_X; } else if (!strcmp(hdim->name, MIyfrequency)) { hdim->world_index = MI2_Y; } else if (!strcmp(hdim->name, MIzfrequency)) { hdim->world_index = MI2_Z; } } } return (MI_NOERROR); } /** Create and initialize a MINC 2.0 volume structure. */ static mihandle_t mialloc_volume_handle(void) { mihandle_t handle = (mihandle_t) malloc(sizeof(struct mivolume)); if (handle != NULL) { /* Clear the memory by default. */ memset(handle, 0, sizeof(struct mivolume)); /* Set the defaults for the data structure */ handle->scale_min = 0.0; handle->scale_max = 1.0; handle->image_id = -1; handle->imax_id = -1; handle->imin_id = -1; handle->plist_id = -1; handle->has_slice_scaling = FALSE; handle->is_dirty = FALSE; handle->dim_indices = NULL; handle->selected_resolution = 0; } return (handle); } /** Create a volume with the specified name, dimensions, type, class, volume properties and retrieve the volume handle. \ingroup mi2Vol */ int micreate_volume(const char *filename, int number_of_dimensions, midimhandle_t dimensions[], mitype_t volume_type, miclass_t volume_class, mivolumeprops_t create_props, mihandle_t *volume) { int i; int stat; hid_t file_id; hid_t hdf_type; hid_t hdf_plist; hid_t fspc_id; hsize_t dim[1]; hid_t grp_id; herr_t status; hid_t dataset_id = -1; hid_t dataset_width = -1; hid_t dataspace_id = -1; char *name; int size; hsize_t hdf_size[MI2_MAX_VAR_DIMS]; mihandle_t handle; mivolumeprops_t props_handle; char ident_str[128]; hid_t tmp_type; /* Initialization. For the actual body of this function look at m2utils.c */ miinit(); /* Validate the parameters. */ if (filename == NULL) { return (MI_ERROR); } if (dimensions == NULL && number_of_dimensions != 0) { return (MI_ERROR); } /* Allocate space for the volume handle */ handle = mialloc_volume_handle(); if (handle == NULL) { return (MI_ERROR); } /* Initialize some of the variables associated with the volume handle. */ handle->mode = MI2_OPEN_RDWR; handle->number_of_dims = number_of_dimensions; /* convert minc type to hdf type */ hdf_type = mitype_to_hdftype(volume_type, FALSE); /* Setting up volume type_id */ switch (volume_class) { case MI_CLASS_REAL: case MI_CLASS_INT: handle->ftype_id = hdf_type; handle->mtype_id = H5Tget_native_type(handle->ftype_id, H5T_DIR_ASCEND); break; case MI_CLASS_LABEL: /* A volume of class LABEL must have an integer type (positive). */ switch (volume_type) { case MI_TYPE_UBYTE: case MI_TYPE_USHORT: case MI_TYPE_UINT: case MI_TYPE_BYTE: case MI_TYPE_SHORT: case MI_TYPE_INT: handle->ftype_id = H5Tenum_create(hdf_type); if (handle->ftype_id < 0) { return (MI_ERROR); } tmp_type = H5Tget_native_type(hdf_type, H5T_DIR_ASCEND); H5Tclose(hdf_type); hdf_type = tmp_type; /* Create an enumerated type with the native type as it's base. */ handle->mtype_id = H5Tenum_create(hdf_type); if (handle->mtype_id < 0) { return (MI_ERROR); } H5Tclose(hdf_type); miinit_enum(handle->ftype_id); miinit_enum(handle->mtype_id); break; default: return (MI_ERROR); } break; case MI_CLASS_COMPLEX: switch (volume_type) { case MI_TYPE_SCOMPLEX: case MI_TYPE_ICOMPLEX: case MI_TYPE_FCOMPLEX: case MI_TYPE_DCOMPLEX: handle->ftype_id = hdf_type; handle->mtype_id = mitype_to_hdftype(volume_type, TRUE); break; default: return (MI_ERROR); } break; case MI_CLASS_UNIFORM_RECORD: handle->ftype_id = H5Tcreate(H5T_COMPOUND, H5Tget_size(hdf_type)); handle->mtype_id = H5Tcreate(H5T_COMPOUND, H5Tget_size(hdf_type)); H5Tclose(hdf_type); break; default: return (MI_ERROR); } handle->volume_class = volume_class; /* Create file in HDF5 with the given filename and H5F_ACC_TRUNC: Truncate file, if it already exists, erasing all data previously stored in the file. and create ID and ID access as default. */ file_id = hdf_create(filename, H5F_ACC_TRUNC, NULL); if (file_id < 0) { return (MI_ERROR); } handle->hdf_id = file_id; micreate_ident(ident_str, sizeof(ident_str)); miset_attribute(handle, MI_ROOT_PATH, "ident", MI_TYPE_STRING, strlen(ident_str), ident_str); miset_attribute(handle, MI_ROOT_PATH, "minc_version", MI_TYPE_STRING, strlen(VERSION), VERSION); _miset_volume_class(handle, handle->volume_class); /* Create a new property list for the volume */ hdf_plist = H5Pcreate(H5P_DATASET_CREATE); if (hdf_plist < 0) { return (MI_ERROR); } handle->plist_id = hdf_plist; /* Set fill value to guarantee valid data on incomplete datasets. */ if (volume_class != MI_CLASS_LABEL && volume_class != MI_CLASS_UNIFORM_RECORD) { size_t siz = H5Tget_size(handle->ftype_id); char *tmp = calloc(1, siz); H5Pset_fill_value(hdf_plist, handle->ftype_id, tmp); free(tmp); } /* See if chunking and/or compression should be enabled and if yes set the type of storage used to store the raw data for a dataset. */ if (create_props != NULL && (create_props->compression_type == MI_COMPRESS_ZLIB || create_props->edge_count != 0)) { /* Set the storage to CHUNKED */ stat = H5Pset_layout(hdf_plist, H5D_CHUNKED); if (stat < 0) { return (MI_ERROR); } /* Create an array, hdf_size, containing the size of each chunk */ for (i=0; i < number_of_dimensions; i++) { hdf_size[i] = create_props->edge_lengths[i]; /* If the size of each chunk is greater than the size of the corresponding dimension, set the chunk size to the dimension size */ if (hdf_size[i] > dimensions[i]->length) { hdf_size[i] = dimensions[i]->length; } } /* Sets the size of the chunks used to store a chunked layout dataset */ stat = H5Pset_chunk(hdf_plist, number_of_dimensions, hdf_size); if (stat < 0) { return (MI_ERROR); } /* Sets compression method and compression level */ stat = H5Pset_deflate(hdf_plist, create_props->zlib_level); if (stat < 0) { return (MI_ERROR); } } else { /* No COMPRESSION or CHUNKING is enabled */ stat = H5Pset_layout(hdf_plist, H5D_CONTIGUOUS); /* CONTIGUOUS data */ if (stat < 0) { return (MI_ERROR); } } /* See if Multi-res is set to a level above 0 and if yes create subgroups i.e., /minc-2.0/image/1/.. /minc-2.0/image/2/.. etc */ // must add some code to make sure that the res level is possible if (create_props != NULL && create_props->depth > 0) { for (i=0; i < create_props->depth ; i++) { if (minc_create_thumbnail(handle, i+1) < 0) { return (MI_ERROR); } } } /* Try creating DIMENSIONS GROUP i.e. /minc-2.0/dimensions */ grp_id = H5Gopen1(file_id, MI_FULLDIMENSIONS_PATH); if (grp_id < 0) { return (MI_ERROR); } /* Once the DIMENSIONS GROUP is opened, create each dimension. */ for (i=0; i < number_of_dimensions ; i++) { /* First create the dataspace required to create a dimension variable (dataset) */ if (dimensions[i]->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) { dim[0] = dimensions[i]->length; dataspace_id = H5Screate_simple(1, dim, NULL); } else { dataspace_id = H5Screate(H5S_SCALAR); } if (dataspace_id < 0) { return (MI_ERROR); } /* Create a dataset(dimension variable name) in DIMENSIONS GROUP */ dataset_id = H5Dcreate1(grp_id, dimensions[i]->name, H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT); /* Dimension variable for a regular dimension contains no meaningful data. Whereas, Dimension variable for an irregular dimension contains a vector with the lengths equal to the sampled points along the dimension. Also, create a variable named "-width" and write the dimension->widths. */ /* Check for irregular dimension and make sure offset values are provided for this dimension */ if (dimensions[i]->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) { if (dimensions[i]->offsets == NULL) { return (MI_ERROR); } else { /* If dimension is regularly sampled */ fspc_id = H5Dget_space(dataset_id); if (fspc_id < 0) { return (MI_ERROR); } /* Write the raw data from buffer (dimensions[i]->offsets) to the dataset. */ status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, dataspace_id, fspc_id, H5P_DEFAULT, dimensions[i]->offsets); if (status < 0) { return (MI_ERROR); } /* Write the raw data from buffer (dimensions[i]->offsets) to the dataset. */ size = strlen(dimensions[i]->name) + 6 + 1; name = malloc(size); strcpy(name, dimensions[i]->name); strcat(name, "-width"); /* Create dataset dimension_name-width */ dataset_width = H5Dcreate1(grp_id, name, H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT); /* Return an Id for the dataspace of the dataset dataset_width */ fspc_id = H5Dget_space(dataset_width); if (fspc_id < 0) { return (MI_ERROR); } /* Write the raw data from buffer (dimensions[i]->widths) to the dataset. */ status = H5Dwrite(dataset_width, H5T_NATIVE_DOUBLE, dataspace_id, fspc_id, H5P_DEFAULT, dimensions[i]->widths); if (status < 0) { return (MI_ERROR); } /* Create new attribute "length", with appropriate type (to hdf5) conversion. miset_attr_at_loc(..) is implemented at m2utils.c */ miset_attr_at_loc(dataset_width, "length", MI_TYPE_INT, 1, &dimensions[i]->length); /* Close the specified datatset */ H5Dclose(dataset_width); free(name); } } if (dimensions[i]->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) { name = "irregular"; } else { name = "regular__"; } /* Create attribute "spacing" and set its value to "regular__" or "irregular" */ miset_attr_at_loc(dataset_id, "spacing", MI_TYPE_STRING, strlen(name), name); switch (dimensions[i]->class) { case MI_DIMCLASS_SPATIAL: name = "spatial"; break; case MI_DIMCLASS_TIME: name = "time___"; break; case MI_DIMCLASS_SFREQUENCY: name = "sfreq__"; break; case MI_DIMCLASS_TFREQUENCY: name = "tfreq__"; break; case MI_DIMCLASS_USER: name = "user___"; break; case MI_DIMCLASS_RECORD: name = "record_"; break; case MI_DIMCLASS_ANY: default: /* These should not be seen in this context!!! */ return (MI_ERROR); } miset_attr_at_loc(dataset_id, "class", MI_TYPE_STRING, strlen(name), name); /* Create Dimension attribute "direction_cosines" */ miset_attr_at_loc(dataset_id, "direction_cosines", MI_TYPE_DOUBLE, 3, dimensions[i]->direction_cosines); /* Save dimension length */ miset_attr_at_loc(dataset_id, "length", MI_TYPE_INT, 1, &dimensions[i]->length); /* Save step value. */ miset_attr_at_loc(dataset_id, "step", MI_TYPE_DOUBLE, 1, &dimensions[i]->step); /* Save start value. */ miset_attr_at_loc(dataset_id, "start", MI_TYPE_DOUBLE, 1, &dimensions[i]->start); /* Save units. */ miset_attr_at_loc(dataset_id, "units", MI_TYPE_STRING, strlen(dimensions[i]->units), dimensions[i]->units); /* Save sample width. */ miset_attr_at_loc(dataset_id, "width", MI_TYPE_DOUBLE, 1, &dimensions[i]->width); /* Save comments. If user has not specified any comments, do not add this attribute */ if (dimensions[i]->comments != NULL) { miset_attr_at_loc(dataset_id, "comments", MI_TYPE_STRING, strlen(dimensions[i]->comments), dimensions[i]->comments); } /* Close the dataset with the specified Id */ H5Dclose(dataset_id); } //for (i=0; i < number_of_dimensions ; i++) /* Close the group with the specified Id */ H5Gclose(grp_id); /* Allocate space for all the dimension handles Note, each volume handle is associated with an array of dimension handles in the order that they were create (i.e, file order) */ handle->dim_handles = (midimhandle_t *)malloc(number_of_dimensions * sizeof(midimhandle_t)); if (handle->dim_handles == NULL) { return (MI_ERROR); } /* Once the space for all dimension handles is created fill the dimension handle array with the appropriate dimension handle. */ for (i = 0; i < number_of_dimensions; i++) { handle->dim_handles[i] = dimensions[i]; dimensions[i]->volume_handle = handle; } miset_volume_world_indices(handle); /* Verify the volume type. */ switch (volume_type) { case MI_TYPE_BYTE: case MI_TYPE_SHORT: case MI_TYPE_INT: case MI_TYPE_FLOAT: case MI_TYPE_DOUBLE: case MI_TYPE_STRING: case MI_TYPE_UBYTE: case MI_TYPE_USHORT: case MI_TYPE_UINT: case MI_TYPE_SCOMPLEX: case MI_TYPE_ICOMPLEX: case MI_TYPE_FCOMPLEX: case MI_TYPE_DCOMPLEX: case MI_TYPE_UNKNOWN: break; default: return (MI_ERROR); } handle->volume_type = volume_type; /* Set the initial value of the valid-range */ miinit_default_range(handle->volume_type, &handle->valid_max, &handle->valid_min); /* Get the voxel to world transform for the volume */ miget_voxel_to_world(handle, handle->v2w_transform); /* Calculate the inverse transform */ miinvert_transform(handle->v2w_transform, handle->w2v_transform); /* Allocated space for the volume properties */ props_handle = (mivolumeprops_t)malloc(sizeof(struct mivolprops)); /* Initialize volume properties with zero */ memset(props_handle, 0, sizeof (struct mivolprops)); /* If volume properties is specified by the user set all the properties of the volume handle */ if (create_props != NULL) { /* Set the enable_flag for multi-resolution */ props_handle->enable_flag = create_props->enable_flag; /* Set the depth of multi-resolution, i.e., how many levels of resolution is specified maximum is 16. */ props_handle->depth = create_props->depth; /* Set compression type, currently two values either no compression or zlib is applicable. */ switch (create_props->compression_type) { case MI_COMPRESS_NONE: props_handle->compression_type = MI_COMPRESS_NONE; break; case MI_COMPRESS_ZLIB: props_handle->compression_type = MI_COMPRESS_ZLIB; break; default: return (MI_ERROR); } /* Note that setting compression on (i.e., MI_COMPRESS_ZLIB) turns chunking on by default. Need to set the number of chunks (edge_count) */ props_handle->zlib_level = create_props->zlib_level; props_handle->edge_count = create_props->edge_count; /* Allocate space for an array which holds the size of each chunk and fill the array with the appropriiate chunk sizes. */ props_handle->edge_lengths = (int *)malloc(create_props->max_lengths*sizeof(int)); for (i=0;imax_lengths; i++) { props_handle->edge_lengths[i] = create_props->edge_lengths[i]; } props_handle->max_lengths = create_props->max_lengths; props_handle->record_length = create_props->record_length; /* Explicitly allocate storage for name */ if (create_props->record_name != NULL) { props_handle->record_name =malloc(strlen(create_props->record_name) + 1 ); strcpy(props_handle->record_name, create_props->record_name); } props_handle->template_flag = create_props->template_flag; } /* Set the handle to volume properties */ handle->create_props = props_handle; /* Return volume handle */ *volume = handle; return (MI_NOERROR); } /** Return the number of dimensions associated with this volume. \ingroup mi2Vol */ int miget_volume_dimension_count(mihandle_t volume, midimclass_t cls, midimattr_t attr, int *number_of_dimensions) { int i, count=0; /* Validate the parameters */ if (volume == NULL || number_of_dimensions == NULL) { return (MI_ERROR); } /* For each dimension check to make sure that dimension class and attribute match with the specified parameters and if yes increment the dimension count */ for (i=0; i< volume->number_of_dims; i++) { if ((cls == MI_DIMCLASS_ANY || volume->dim_handles[i]->class == cls) && (attr == MI_DIMATTR_ALL || volume->dim_handles[i]->attr == attr)) { count++; } } *number_of_dimensions = count; return (MI_NOERROR); } /** Returns the number of voxels in the volume. \ingroup mi2Vol */ int miget_volume_voxel_count(mihandle_t volume, int *number_of_voxels) { char path[MI2_MAX_PATH]; hid_t dset_id; hid_t fspc_id; /* Validate parameters */ if (volume == NULL || number_of_voxels == NULL) { return (MI_ERROR); } /* Quickest way to do this is with the dataspace identifier of the * volume. Use the volume's current resolution. */ sprintf(path, "/minc-2.0/image/%d/image", volume->selected_resolution); /* Open the dataset with the specified path */ dset_id = H5Dopen1(volume->hdf_id, path); if (dset_id < 0) { return (MI_ERROR); } /* Get an Id to the copy of the dataspace */ fspc_id = H5Dget_space(dset_id); if (fspc_id < 0) { return (MI_ERROR); } /* Determines the number of elements in the dataspace and cast the result to an integer. */ *number_of_voxels = (int) H5Sget_simple_extent_npoints(fspc_id); /* Close the dataspace */ H5Sclose(fspc_id); /* Close the dataset */ H5Dclose(dset_id); return (MI_NOERROR); } /* Get the number of dimensions in the file */ static int _miget_file_dimension_count(hid_t file_id) { hid_t dset_id; hid_t space_id; int result = -1; /* hdf5 macro can temporarily disable the automatic error printing */ H5E_BEGIN_TRY { dset_id = midescend_path(file_id, "/minc-2.0/image/0/image"); } H5E_END_TRY; if (dset_id >= 0) { /* Get an Id to the copy of the dataspace */ space_id = H5Dget_space(dset_id); if (space_id > 0) { /* Determine the dimensionality of the dataspace */ result = H5Sget_simple_extent_ndims(space_id); /* Close the dataspace */ H5Sclose(space_id); } /* Close the dataset */ H5Dclose(dset_id); } return (result); } /* Get dimension variable attributes for the given dimension name */ static int _miset_volume_class(mihandle_t volume, miclass_t volume_class) { const char *class_ptr; switch (volume_class) { case MI_CLASS_REAL: class_ptr = "real___"; break; case MI_CLASS_INT: class_ptr = "integer"; break; case MI_CLASS_LABEL: class_ptr = "label__"; break; case MI_CLASS_COMPLEX: class_ptr = "complex"; break; case MI_CLASS_UNIFORM_RECORD: class_ptr = "array__"; break; default: return (MI_ERROR); } miset_attribute(volume, MI_ROOT_PATH, "class", MI_TYPE_STRING, strlen(class_ptr), class_ptr); return (MI_NOERROR); } static int _miget_volume_class(mihandle_t volume, miclass_t *volume_class) { char class_buf[MI2_CHAR_LENGTH]; miget_attribute(volume, MI_ROOT_PATH, "class", MI_TYPE_STRING, MI2_CHAR_LENGTH, class_buf); if (!strcmp(class_buf, "label__")) { *volume_class = MI_CLASS_LABEL; } else if (!strcmp(class_buf, "integer")) { *volume_class = MI_CLASS_INT; } else if (!strcmp(class_buf, "complex")) { *volume_class = MI_CLASS_COMPLEX; } else if (!strcmp(class_buf, "array__")) { *volume_class = MI_CLASS_UNIFORM_RECORD; } else { *volume_class = MI_CLASS_REAL; } return (MI_NOERROR); } /* Get dimension variable attributes for the given dimension name */ static int _miget_file_dimension(mihandle_t volume, const char *dimname, midimhandle_t *hdim_ptr) { char path[MI2_CHAR_LENGTH]; char temp[MI2_CHAR_LENGTH]; midimhandle_t hdim; /* Create a path with the dimension name */ sprintf(path, "/minc-2.0/dimensions/%s", dimname); /* Allocate space for the dimension handle */ hdim = (midimhandle_t) malloc(sizeof (*hdim)); /* Initialize everything to zero */ memset(hdim, 0, sizeof (*hdim)); hdim->name = strdup(dimname); /* hdf5 macro can temporarily disable the automatic error printing */ H5E_BEGIN_TRY { int r; /* Get the attribute (spacing) from a minc file */ r = miget_attribute(volume, path, "spacing", MI_TYPE_STRING, MI2_CHAR_LENGTH, temp); if (!strcmp(temp, "irregular")) { hdim->attr |= MI_DIMATTR_NOT_REGULARLY_SAMPLED; } else { hdim->attr |= MI_DIMATTR_REGULARLY_SAMPLED; } /* Get the attribute (class) from a minc file */ r = miget_attribute(volume, path, "class", MI_TYPE_STRING, MI2_CHAR_LENGTH, temp); if (r < 0) { /* Get the default class. */ if (!strcmp(dimname, "time")) { hdim->class = MI_DIMCLASS_TIME; } else if (!strcmp(dimname, "vector_dimension")) { hdim->class = MI_DIMCLASS_RECORD; hdim->step = 0.0; } else { hdim->class = MI_DIMCLASS_SPATIAL; } } else { if (!strcmp(temp, "spatial")) { hdim->class = MI_DIMCLASS_SPATIAL; } else if (!strcmp(temp, "time___")) { hdim->class = MI_DIMCLASS_TIME; } else if (!strcmp(temp, "sfreq__")) { hdim->class = MI_DIMCLASS_SFREQUENCY; } else if (!strcmp(temp, "tfreq__")) { hdim->class = MI_DIMCLASS_TFREQUENCY; } else if (!strcmp(temp, "user___")) { hdim->class = MI_DIMCLASS_USER; } else if (!strcmp(temp, "record_")) { hdim->class = MI_DIMCLASS_RECORD; } else { /* TODO: error message?? */ } } /* Get the attribute (length) from a minc file */ r = miget_attribute(volume, path, "length", MI_TYPE_UINT, 1, &hdim->length); if (r < 0) { fprintf(stderr, "Can't get length\n"); } /* Get the attribute (start) from a minc file for NON vector_dimension only */ if (strcmp(dimname, "vector_dimension")) { r = miget_attribute(volume, path, "start", MI_TYPE_DOUBLE, 1, &hdim->start); if (r < 0) { hdim->start = 0.0; } /* Get the attribute (step) from a minc file */ r = miget_attribute(volume, path, "step", MI_TYPE_DOUBLE, 1, &hdim->step); if (r < 0) { hdim->step = 1.0; } } /* Get the attribute (direction_cosines) from a minc file */ r = miget_attribute(volume, path, "direction_cosines", MI_TYPE_DOUBLE, 3, hdim->direction_cosines); if (r < 0) { hdim->direction_cosines[MI2_X] = 0.0; hdim->direction_cosines[MI2_Y] = 0.0; hdim->direction_cosines[MI2_Z] = 0.0; if (!strcmp(dimname, MIxspace)) { hdim->direction_cosines[MI2_X] = 1.0; } else if (!strcmp(dimname, MIyspace)) { hdim->direction_cosines[MI2_Y] = 1.0; } else if (!strcmp(dimname, MIzspace)) { hdim->direction_cosines[MI2_Z] = 1.0; } } r = miget_attribute(volume, path, "units", MI_TYPE_STRING, MI2_CHAR_LENGTH, temp); if (r < 0) { hdim->units = strdup(""); } else { hdim->units = strdup(temp); } } H5E_END_TRY; /* Return the dimension handle */ *hdim_ptr = hdim; hdim->volume_handle = volume; return (MI_NOERROR); } /** Opens an existing MINC volume for read-only access if mode argument is MI2_OPEN_READ, or read-write access if mode argument is MI2_OPEN_RDWR. \ingroup mi2Vol */ int miopen_volume(const char *filename, int mode, mihandle_t *volume) { hid_t file_id; hid_t dset_id; hid_t space_id; mihandle_t handle; int hdf_mode; char dimorder[MI2_CHAR_LENGTH]; int i,r; char *p1, *p2; H5T_class_t class; size_t nbytes; int is_signed; /* Initialization. For the actual body of this function look at m2utils.c */ miinit(); /* Convert the specified mode to hdf mode */ if (mode == MI2_OPEN_READ) { hdf_mode = H5F_ACC_RDONLY; } else if (mode == MI2_OPEN_RDWR) { hdf_mode = H5F_ACC_RDWR; } else { return (MI_ERROR); } /* Open the hdf file using the given filename and mode */ file_id = hdf_open(filename, hdf_mode); if (file_id < 0) { return (MI_ERROR); } /* Allocate space for the volume handle */ handle = mialloc_volume_handle(); if (handle == NULL) { return (MI_ERROR); } /* Set some varibales associated with the volume handle */ handle->hdf_id = file_id; handle->mode = mode; /* Get the volume class. */ _miget_volume_class(handle, &handle->volume_class); /* GET THE DIMENSION COUNT */ handle->number_of_dims = _miget_file_dimension_count(file_id); /* READ EACH OF THE DIMENSIONS */ handle->dim_handles = (midimhandle_t *)malloc(handle->number_of_dims * sizeof(midimhandle_t)); /* Get the attribute (dimorder) from the image dataset */ r = miget_attribute(handle, "/minc-2.0/image/0/image", "dimorder", MI_TYPE_STRING, sizeof(dimorder), dimorder); if ( r < 0) { return (MI_ERROR); } p1 = dimorder; /* Break the ordered, comma-separated list of dimension names to get each individual dimension name */ for (i = 0; i < handle->number_of_dims; i++) { p2 = strchr(p1, ','); if (p2 != NULL) { *p2 = '\0'; } /* Get dimension variable attributes for each dimension */ _miget_file_dimension(handle, p1, &handle->dim_handles[i]); p1 = p2 + 1; } miset_volume_world_indices(handle); /* SEE IF SLICE SCALING IS ENABLED */ handle->has_slice_scaling = FALSE; /* hdf5 macro can temporarily disable the automatic error printing */ H5E_BEGIN_TRY { /* Open the dataset image-max at the specified path*/ dset_id = H5Dopen1(file_id, "/minc-2.0/image/0/image-max"); } H5E_END_TRY; if (dset_id >= 0) { /* Get the Id of the copy of the dataspace of the dataset */ space_id = H5Dget_space(dset_id); if (space_id >= 0) { /* If the dimensionality of the image-max variable is one or * greater, we consider this volume to have slice-scaling enabled. */ if (H5Sget_simple_extent_ndims(space_id) >= 1) { handle->has_slice_scaling = TRUE; } H5Sclose(space_id); /* Close the dataspace handle */ } H5Dclose(dset_id); /* Close the dataset handle */ } if (!handle->has_slice_scaling) { /* Read the minimum scalar of the given type at the specified path */ miget_scalar(handle->hdf_id, H5T_NATIVE_DOUBLE, "/minc-2.0/image/0/image-min", &handle->scale_min); /* Read the maximum scalar of the given type at the specified path */ miget_scalar(handle->hdf_id, H5T_NATIVE_DOUBLE, "/minc-2.0/image/0/image-max", &handle->scale_max); } /* Read the current voxel-to-world transform */ miget_voxel_to_world(handle, handle->v2w_transform); /* Calculate the inverse transform */ miinvert_transform(handle->v2w_transform, handle->w2v_transform); /* Open the image dataset */ handle->image_id = H5Dopen1(file_id, "/minc-2.0/image/0/image"); if (handle->image_id < 0) { return (MI_ERROR); } /* Get the Id for the copy of the datatype for the dataset */ handle->ftype_id = H5Dget_type(handle->image_id); if (handle->ftype_id < 0) { return (MI_ERROR); } switch (H5Tget_class(handle->ftype_id)) { case H5T_INTEGER: case H5T_FLOAT: handle->mtype_id = H5Tget_native_type(handle->ftype_id, H5T_DIR_ASCEND); break; case H5T_COMPOUND: handle->mtype_id = H5Tcreate(H5T_COMPOUND, H5Tget_size(handle->ftype_id)); for (i = 0; i < H5Tget_nmembers(handle->ftype_id); i++) { hid_t tmp_id = H5Tget_member_type(handle->ftype_id, i); size_t tmp_off = H5Tget_member_offset(handle->ftype_id, i); char *tmp_nm = H5Tget_member_name(handle->ftype_id, i); hid_t tmp2_id = H5Tget_native_type(tmp_id, H5T_DIR_ASCEND); H5Tinsert(handle->mtype_id, tmp_nm, tmp_off, tmp2_id); free(tmp_nm); H5Tclose(tmp_id); H5Tclose(tmp2_id); } break; case H5T_ENUM: handle->mtype_id = H5Tcopy(handle->ftype_id); miinit_enum(handle->ftype_id); miinit_enum(handle->mtype_id); /* Set native order ---> is not allowed after order is set */ //H5Tset_order(handle->mtype_id, H5Tget_order(H5T_NATIVE_INT)); break; default: return (MI_ERROR); } /* hdf5 macro can temporarily disable the automatic error printing */ H5E_BEGIN_TRY { /* Open both image-min and image-max datasets */ handle->imax_id = H5Dopen1(file_id, "/minc-2.0/image/0/image-max"); handle->imin_id = H5Dopen1(file_id, "/minc-2.0/image/0/image-min"); } H5E_END_TRY; /* Convert the type to a MINC type. */ /* Get the class Id for the datatype */ class = H5Tget_class(handle->ftype_id); /* Get the size of the datatype */ nbytes = H5Tget_size(handle->ftype_id); switch (class) { case H5T_INTEGER: case H5T_ENUM: /* label images */ is_signed = (H5Tget_sign(handle->ftype_id) == H5T_SGN_2); switch (nbytes) { case 1: handle->volume_type = (is_signed ? MI_TYPE_BYTE : MI_TYPE_UBYTE); break; case 2: handle->volume_type = (is_signed ? MI_TYPE_SHORT : MI_TYPE_USHORT); break; case 4: handle->volume_type = (is_signed ? MI_TYPE_INT : MI_TYPE_UINT); break; default: return (MI_ERROR); } break; case H5T_FLOAT: handle->volume_type = (nbytes == 4) ? MI_TYPE_FLOAT : MI_TYPE_DOUBLE; break; case H5T_STRING: handle->volume_type = MI_TYPE_STRING; break; case H5T_ARRAY: /* TODO: handle this case for uniform records (arrays)? */ break; case H5T_COMPOUND: /* TODO: handle this case for non-uniform records? */ break; default: return (MI_ERROR); } /* Read the current settings for valid-range */ miread_valid_range(handle, &handle->valid_max, &handle->valid_min); *volume = handle; return (MI_NOERROR); } /** Writes any changes associated with the volume to disk. \ingroup mi2Vol */ int miflush_volume(mihandle_t volume) { if ((volume->mode & MI2_OPEN_RDWR) != 0) { H5Fflush(volume->hdf_id, H5F_SCOPE_GLOBAL); misave_valid_range(volume); } return (MI_NOERROR); } /** Close an existing MINC volume. If the volume was newly created, * all changes will be written to disk. In all cases this function closes * the open volume and frees memory associated with the volume handle. * \ingroup mi2Vol */ int miclose_volume(mihandle_t volume) { if (volume == NULL) { return (MI_ERROR); } if (volume->is_dirty) { minc_update_thumbnails(volume); volume->is_dirty = FALSE; } miflush_volume(volume); if (volume->image_id > 0) { H5Dclose(volume->image_id); } if (volume->imax_id > 0) { H5Dclose(volume->imax_id); } if (volume->imin_id > 0) { H5Dclose(volume->imin_id); } if (volume->ftype_id > 0) { H5Tclose(volume->ftype_id); } if (volume->mtype_id > 0) { H5Tclose(volume->mtype_id); } if (volume->plist_id > 0) { H5Pclose(volume->plist_id); } //if (H5Fclose(volume->hdf_id) < 0) { if (hdf_close(volume->hdf_id) < 0) { return (MI_ERROR); } if (volume->dim_handles != NULL) { free(volume->dim_handles); } if (volume->dim_indices != NULL) { free(volume->dim_indices); } if (volume->create_props != NULL) { mifree_volume_props(volume->create_props); } free(volume); return (MI_NOERROR); } /* Internal functions */ static void miinit_default_range(mitype_t mitype, double *valid_max, double *valid_min) { switch (mitype) { case MI_TYPE_BYTE: *valid_min = CHAR_MIN; *valid_max = CHAR_MAX; break; case MI_TYPE_SHORT: *valid_min = SHRT_MIN; *valid_max = SHRT_MAX; break; case MI_TYPE_INT: *valid_min = INT_MIN; *valid_max = INT_MAX; break; case MI_TYPE_UBYTE: *valid_min = 0; *valid_max = UCHAR_MAX; break; case MI_TYPE_USHORT: *valid_min = 0; *valid_max = USHRT_MAX; break; case MI_TYPE_UINT: *valid_min = 0; *valid_max = UINT_MAX; break; case MI_TYPE_FLOAT: *valid_min = -FLT_MAX; *valid_max = FLT_MAX; break; case MI_TYPE_DOUBLE: *valid_min = -DBL_MAX; *valid_max = DBL_MAX; break; default: *valid_min = 0; *valid_max = 1; break; } } static void miread_valid_range(mihandle_t volume, double *valid_max, double *valid_min) { int r; double range[2]; H5E_BEGIN_TRY { r = miget_attribute(volume, "/minc-2.0/image/0/image", "valid_range", MI_TYPE_DOUBLE, 2, range); } H5E_END_TRY; if (r == MI_NOERROR) { if (range[0] < range[1]) { *valid_min = range[0]; *valid_max = range[1]; } else { *valid_min = range[1]; *valid_max = range[0]; } } else { /* Didn't find the attribute, so assign default values. */ miinit_default_range(volume->volume_type, valid_max, valid_min); } } /** \internal * This function saves the current valid range set for a MINC file. */ void misave_valid_range(mihandle_t volume) { double range[2]; range[0] = volume->valid_min; range[1] = volume->valid_max; miset_attribute(volume, "/minc-2.0/image/0/image", "valid_range", MI_TYPE_DOUBLE, 2, range); } minc-2.2.00/libsrc2/test/0000755000265600003100000000000012030114724012030 500000000000000minc-2.2.00/libsrc2/test/Makefile.am0000644000265600003100000000113312027132662014011 00000000000000INCLUDES = -I$(top_srcdir)/libsrc2 script_tests = \ testminctools.sh all-local: cd $(srcdir) && chmod +x $(script_tests) LDADD = ../../libminc2.la AM_CFLAGS = -DAPPARENTORDER ALL_TESTS = \ create-test-images \ create-test-images-2 \ datatype-test \ dimension-test \ full-test \ grpattr-test \ hyper-test \ hyper-test-2 \ label-test \ record-test \ slice-test \ valid-test \ volprops-test \ multires-test \ convert-test \ vector_dimension-test TESTS = \ $(ALL_TESTS) \ $(script_tests) EXTRA_DIST = $(script_tests) check_PROGRAMS = $(ALL_TESTS) CLEANFILES = *.mnc minc-2.2.00/libsrc2/test/Makefile.in0000644000265600003100000005700712030077514014033 00000000000000# Makefile.in generated by automake 1.10.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ TESTS = $(am__EXEEXT_1) $(script_tests) check_PROGRAMS = $(am__EXEEXT_1) subdir = libsrc2/test DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mni_REQUIRE_LIB.m4 \ $(top_srcdir)/m4/smr_WITH_BUILD_PATH.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__EXEEXT_1 = create-test-images$(EXEEXT) \ create-test-images-2$(EXEEXT) datatype-test$(EXEEXT) \ dimension-test$(EXEEXT) full-test$(EXEEXT) \ grpattr-test$(EXEEXT) hyper-test$(EXEEXT) \ hyper-test-2$(EXEEXT) label-test$(EXEEXT) record-test$(EXEEXT) \ slice-test$(EXEEXT) valid-test$(EXEEXT) volprops-test$(EXEEXT) \ multires-test$(EXEEXT) convert-test$(EXEEXT) \ vector_dimension-test$(EXEEXT) convert_test_SOURCES = convert-test.c convert_test_OBJECTS = convert-test.$(OBJEXT) convert_test_LDADD = $(LDADD) convert_test_DEPENDENCIES = ../../libminc2.la create_test_images_SOURCES = create-test-images.c create_test_images_OBJECTS = create-test-images.$(OBJEXT) create_test_images_LDADD = $(LDADD) create_test_images_DEPENDENCIES = ../../libminc2.la create_test_images_2_SOURCES = create-test-images-2.c create_test_images_2_OBJECTS = create-test-images-2.$(OBJEXT) create_test_images_2_LDADD = $(LDADD) create_test_images_2_DEPENDENCIES = ../../libminc2.la datatype_test_SOURCES = datatype-test.c datatype_test_OBJECTS = datatype-test.$(OBJEXT) datatype_test_LDADD = $(LDADD) datatype_test_DEPENDENCIES = ../../libminc2.la dimension_test_SOURCES = dimension-test.c dimension_test_OBJECTS = dimension-test.$(OBJEXT) dimension_test_LDADD = $(LDADD) dimension_test_DEPENDENCIES = ../../libminc2.la full_test_SOURCES = full-test.c full_test_OBJECTS = full-test.$(OBJEXT) full_test_LDADD = $(LDADD) full_test_DEPENDENCIES = ../../libminc2.la grpattr_test_SOURCES = grpattr-test.c grpattr_test_OBJECTS = grpattr-test.$(OBJEXT) grpattr_test_LDADD = $(LDADD) grpattr_test_DEPENDENCIES = ../../libminc2.la hyper_test_SOURCES = hyper-test.c hyper_test_OBJECTS = hyper-test.$(OBJEXT) hyper_test_LDADD = $(LDADD) hyper_test_DEPENDENCIES = ../../libminc2.la hyper_test_2_SOURCES = hyper-test-2.c hyper_test_2_OBJECTS = hyper-test-2.$(OBJEXT) hyper_test_2_LDADD = $(LDADD) hyper_test_2_DEPENDENCIES = ../../libminc2.la label_test_SOURCES = label-test.c label_test_OBJECTS = label-test.$(OBJEXT) label_test_LDADD = $(LDADD) label_test_DEPENDENCIES = ../../libminc2.la multires_test_SOURCES = multires-test.c multires_test_OBJECTS = multires-test.$(OBJEXT) multires_test_LDADD = $(LDADD) multires_test_DEPENDENCIES = ../../libminc2.la record_test_SOURCES = record-test.c record_test_OBJECTS = record-test.$(OBJEXT) record_test_LDADD = $(LDADD) record_test_DEPENDENCIES = ../../libminc2.la slice_test_SOURCES = slice-test.c slice_test_OBJECTS = slice-test.$(OBJEXT) slice_test_LDADD = $(LDADD) slice_test_DEPENDENCIES = ../../libminc2.la valid_test_SOURCES = valid-test.c valid_test_OBJECTS = valid-test.$(OBJEXT) valid_test_LDADD = $(LDADD) valid_test_DEPENDENCIES = ../../libminc2.la vector_dimension_test_SOURCES = vector_dimension-test.c vector_dimension_test_OBJECTS = vector_dimension-test.$(OBJEXT) vector_dimension_test_LDADD = $(LDADD) vector_dimension_test_DEPENDENCIES = ../../libminc2.la volprops_test_SOURCES = volprops-test.c volprops_test_OBJECTS = volprops-test.$(OBJEXT) volprops_test_LDADD = $(LDADD) volprops_test_DEPENDENCIES = ../../libminc2.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/ac_config_aux/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = convert-test.c create-test-images.c create-test-images-2.c \ datatype-test.c dimension-test.c full-test.c grpattr-test.c \ hyper-test.c hyper-test-2.c label-test.c multires-test.c \ record-test.c slice-test.c valid-test.c \ vector_dimension-test.c volprops-test.c DIST_SOURCES = convert-test.c create-test-images.c \ create-test-images-2.c datatype-test.c dimension-test.c \ full-test.c grpattr-test.c hyper-test.c hyper-test-2.c \ label-test.c multires-test.c record-test.c slice-test.c \ valid-test.c vector_dimension-test.c volprops-test.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POD2MAN = @POD2MAN@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_F77 = @ac_ct_F77@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir)/libsrc2 script_tests = \ testminctools.sh LDADD = ../../libminc2.la AM_CFLAGS = -DAPPARENTORDER ALL_TESTS = \ create-test-images \ create-test-images-2 \ datatype-test \ dimension-test \ full-test \ grpattr-test \ hyper-test \ hyper-test-2 \ label-test \ record-test \ slice-test \ valid-test \ volprops-test \ multires-test \ convert-test \ vector_dimension-test EXTRA_DIST = $(script_tests) CLEANFILES = *.mnc all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libsrc2/test/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu libsrc2/test/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done convert-test$(EXEEXT): $(convert_test_OBJECTS) $(convert_test_DEPENDENCIES) @rm -f convert-test$(EXEEXT) $(LINK) $(convert_test_OBJECTS) $(convert_test_LDADD) $(LIBS) create-test-images$(EXEEXT): $(create_test_images_OBJECTS) $(create_test_images_DEPENDENCIES) @rm -f create-test-images$(EXEEXT) $(LINK) $(create_test_images_OBJECTS) $(create_test_images_LDADD) $(LIBS) create-test-images-2$(EXEEXT): $(create_test_images_2_OBJECTS) $(create_test_images_2_DEPENDENCIES) @rm -f create-test-images-2$(EXEEXT) $(LINK) $(create_test_images_2_OBJECTS) $(create_test_images_2_LDADD) $(LIBS) datatype-test$(EXEEXT): $(datatype_test_OBJECTS) $(datatype_test_DEPENDENCIES) @rm -f datatype-test$(EXEEXT) $(LINK) $(datatype_test_OBJECTS) $(datatype_test_LDADD) $(LIBS) dimension-test$(EXEEXT): $(dimension_test_OBJECTS) $(dimension_test_DEPENDENCIES) @rm -f dimension-test$(EXEEXT) $(LINK) $(dimension_test_OBJECTS) $(dimension_test_LDADD) $(LIBS) full-test$(EXEEXT): $(full_test_OBJECTS) $(full_test_DEPENDENCIES) @rm -f full-test$(EXEEXT) $(LINK) $(full_test_OBJECTS) $(full_test_LDADD) $(LIBS) grpattr-test$(EXEEXT): $(grpattr_test_OBJECTS) $(grpattr_test_DEPENDENCIES) @rm -f grpattr-test$(EXEEXT) $(LINK) $(grpattr_test_OBJECTS) $(grpattr_test_LDADD) $(LIBS) hyper-test$(EXEEXT): $(hyper_test_OBJECTS) $(hyper_test_DEPENDENCIES) @rm -f hyper-test$(EXEEXT) $(LINK) $(hyper_test_OBJECTS) $(hyper_test_LDADD) $(LIBS) hyper-test-2$(EXEEXT): $(hyper_test_2_OBJECTS) $(hyper_test_2_DEPENDENCIES) @rm -f hyper-test-2$(EXEEXT) $(LINK) $(hyper_test_2_OBJECTS) $(hyper_test_2_LDADD) $(LIBS) label-test$(EXEEXT): $(label_test_OBJECTS) $(label_test_DEPENDENCIES) @rm -f label-test$(EXEEXT) $(LINK) $(label_test_OBJECTS) $(label_test_LDADD) $(LIBS) multires-test$(EXEEXT): $(multires_test_OBJECTS) $(multires_test_DEPENDENCIES) @rm -f multires-test$(EXEEXT) $(LINK) $(multires_test_OBJECTS) $(multires_test_LDADD) $(LIBS) record-test$(EXEEXT): $(record_test_OBJECTS) $(record_test_DEPENDENCIES) @rm -f record-test$(EXEEXT) $(LINK) $(record_test_OBJECTS) $(record_test_LDADD) $(LIBS) slice-test$(EXEEXT): $(slice_test_OBJECTS) $(slice_test_DEPENDENCIES) @rm -f slice-test$(EXEEXT) $(LINK) $(slice_test_OBJECTS) $(slice_test_LDADD) $(LIBS) valid-test$(EXEEXT): $(valid_test_OBJECTS) $(valid_test_DEPENDENCIES) @rm -f valid-test$(EXEEXT) $(LINK) $(valid_test_OBJECTS) $(valid_test_LDADD) $(LIBS) vector_dimension-test$(EXEEXT): $(vector_dimension_test_OBJECTS) $(vector_dimension_test_DEPENDENCIES) @rm -f vector_dimension-test$(EXEEXT) $(LINK) $(vector_dimension_test_OBJECTS) $(vector_dimension_test_LDADD) $(LIBS) volprops-test$(EXEEXT): $(volprops_test_OBJECTS) $(volprops_test_DEPENDENCIES) @rm -f volprops-test$(EXEEXT) $(LINK) $(volprops_test_OBJECTS) $(volprops_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/convert-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/create-test-images-2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/create-test-images.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dimension-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/full-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grpattr-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hyper-test-2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hyper-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/label-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multires-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/record-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slice-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/valid-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vector_dimension-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/volprops-test.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am all-local check check-TESTS check-am \ clean clean-checkPROGRAMS clean-generic clean-libtool ctags \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am all-local: cd $(srcdir) && chmod +x $(script_tests) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: minc-2.2.00/libsrc2/test/convert-test.c0000644000265600003100000001527212027132662014567 00000000000000#include #include #include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define NDIMS 3 #define CX 40 #define CY 40 #define CZ 40 /* "Close enough for government work" */ #define EPSILON 1e-13 #define NEARLY_EQUAL(x, y) (fabs(x - y) < EPSILON) #define VALID_MAX 100 #define VALID_MIN 0 #define REAL_MIN -2.0 #define REAL_MAX 2.0 int main(int argc, char **argv) { int result; double voxel[NDIMS]; double world[NDIMS]; double new_voxel[NDIMS]; unsigned long coords[NDIMS]; unsigned long count[NDIMS] = {1,1,1}; midimhandle_t hdims[NDIMS]; int i, j, k; int n; mihandle_t hvol; double v1, v2; double r1, r2, r3; double cosines[3]; result = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdims[0]); result = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdims[1]); result = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdims[2]); /* Set cosines, steps, and starts to reference values. */ cosines[0] = 0.999815712665963; cosines[1] = 0.019197414051189; cosines[2] = 0; miset_dimension_cosines(hdims[0], cosines); miset_dimension_start(hdims[0], -75.4957607345912); miset_dimension_separation(hdims[0], 1.0); cosines[0] = -0.019197414051189; cosines[1] = 0.999815712665963; cosines[2] = 0; miset_dimension_cosines(hdims[1], cosines); miset_dimension_start(hdims[1], 160.392861750822); miset_dimension_separation(hdims[1], -1.0); cosines[0] = 0; cosines[1] = 0; cosines[2] = 1; miset_dimension_cosines(hdims[2], cosines); miset_dimension_start(hdims[2], 121.91304); miset_dimension_separation(hdims[2], -1.0); result = micreate_volume("tst-convert.mnc", NDIMS, hdims, MI_TYPE_UINT, MI_CLASS_REAL, NULL, &hvol); if (result < 0) { TESTRPT("micreate_volume error", result); } result = micreate_volume_image(hvol); if (result < 0) { TESTRPT("micreate_volume_image error", result); } /* Valid values are from 0 to 100 */ miset_volume_valid_range(hvol, VALID_MAX, VALID_MIN); /* "real" values are -2.0 to 2.0 */ miset_volume_range(hvol, REAL_MAX, REAL_MIN); for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; voxel[0] = coords[0]; voxel[1] = coords[1]; voxel[2] = coords[2]; miconvert_voxel_to_world(hvol, voxel, world); miconvert_world_to_voxel(hvol, world, new_voxel); for (n = 0; n < 3; n++) { if (!NEARLY_EQUAL(voxel[n], new_voxel[n])) { fprintf(stderr, "%d %f %f\n", n, voxel[n], new_voxel[n]); TESTRPT("conversion error", 0); } } v1 = (VALID_MAX * (voxel[0] + voxel[1] + voxel[2]) / ((CX-1)+(CY-1)+(CZ-1))); result = miset_voxel_value_hyperslab(hvol, MI_TYPE_DOUBLE, coords, count, &v1); if (result < 0) { TESTRPT("miset_voxel_value_hyperslab error", result); } /* Get a voxel value. */ result = miget_voxel_value_hyperslab(hvol, MI_TYPE_DOUBLE, coords, count, &v1); if (result < 0) { TESTRPT("miget_voxel_value_hyperslab error", result); } /* Convert from voxel to real. */ result = miconvert_voxel_to_real(hvol, coords, 3, v1, &r1); if (result < 0) { TESTRPT("miconvert_voxel_to_real error", result); } /* Double check the conversion. */ r3 = (v1 - VALID_MIN) / (VALID_MAX - VALID_MIN); r3 = (r3 * (REAL_MAX - REAL_MIN)) + REAL_MIN; if (!NEARLY_EQUAL(r3, r1)) { TESTRPT("real value mismatch", 0); } /* Convert it back to voxel. */ result = miconvert_real_to_voxel(hvol, coords, 3, r1, &v2); if (result < 0) { TESTRPT("miconvert_real_to_voxel error", result); } /* Compare to the value read via the ICV */ result = miget_real_value(hvol, coords, 3, &r2); if (result < 0) { TESTRPT("miget_real_value error", result); } if (!NEARLY_EQUAL(v1, v2)) { fprintf(stderr, "v1 %f v2 %f\n", v1, v2); TESTRPT("Voxel value mismatch", 0); } if (!NEARLY_EQUAL(r1, r2)) { fprintf(stderr, "r1 %f r2 %f\n", r1, r2); TESTRPT("Real value mismatch", 0); } result = miget_voxel_value(hvol, coords, 3, &v1); if (result < 0) { TESTRPT("miget_voxel_value error", result); } if (!NEARLY_EQUAL(v1, v2)) { fprintf(stderr, "v1 %f v2 %f\n", v1, v2); TESTRPT("Voxel value mismatch", 0); } } } } world[MI2_X] = -80; world[MI2_Y] = 150; world[MI2_Z] = 120; result = miset_world_origin(hvol, world); if (result != MI_NOERROR) { TESTRPT("miset_world_origin error", result); } voxel[MI2_X] = voxel[MI2_Y] = voxel[MI2_Z] = 0; result = miconvert_voxel_to_world(hvol, voxel, world); if (result != MI_NOERROR) { TESTRPT("miconvert_voxel_to_world error", result); } if (!NEARLY_EQUAL(world[MI2_X], -80.0) || !NEARLY_EQUAL(world[MI2_Y], 150.0) || !NEARLY_EQUAL(world[MI2_Z], 120.0)) { fprintf(stderr, "%f %f %f\n", world[0], world[1], world[2]); TESTRPT("conversion error", 0); } if (error_cnt == 0) { printf("No errors\n"); } else { printf("%d error%s\n", error_cnt, error_cnt == 1 ? "" : "s"); } return (error_cnt); } minc-2.2.00/libsrc2/test/create-test-images.c0000644000265600003100000001332612027132662015613 00000000000000#include #include #include "minc2.h" /* This test will attempt to create a few different test images * which can be tested with minc2.0 */ #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) #define CZ 142 #define CY 245 #define CX 10 #define CU 5 #define NDIMS 3 int create_2D_image(void) { int r,i; midimhandle_t hdim[NDIMS-1]; mihandle_t hvol; short *buf = (short *)malloc(CX * CY * sizeof(short)); double *offsets = (double *)malloc(CX * sizeof(double)); double start_values[NDIMS-1]={-1.01, -2.02}; miboolean_t flag=0; long count[NDIMS-1]; long start[NDIMS-1]; r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_NOT_REGULARLY_SAMPLED, CX, &hdim[0]); r = micreate_dimension("yspace", MI_DIMCLASS_USER, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[1]); for(i=0; i < CX; i++) { offsets[i] = (i * i) + 0.1; } r = miset_dimension_offsets(hdim[0], CX, 0, offsets); r = miset_dimension_separation(hdim[1], 0.06); r = miset_dimension_starts(hdim, NDIMS-1, start_values); r = micreate_volume("2D_image.mnc", NDIMS-1 , hdim, MI_TYPE_SHORT, MI_CLASS_REAL, NULL, &hvol); /* set slice scaling flag to true */ r = miset_slice_scaling_flag(hvol, flag); r = micreate_volume_image(hvol); for (i = 0; i < CX*CY; i++) { buf[i] = (short) i * 0.1; } start[0] = start[1] = 0; count[0] = CX; count[1] = CY; r = miset_voxel_value_hyperslab(hvol, MI_TYPE_SHORT, start, count, buf); r = miclose_volume(hvol); } int create_3D_image(void) { int r; double start_values[NDIMS]={-6.96, -12.453, -9.48}; double separations[NDIMS]={0.09,0.09,0.09}; midimhandle_t hdim[NDIMS]; mihandle_t hvol; unsigned short *buf = ( unsigned short *) malloc(CX * CY * CZ * sizeof(unsigned short)); int i; long count[NDIMS]; long start[NDIMS]; miboolean_t flag=1; double min = -1.0; double max = 1.0; r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[0]); r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdim[1]); r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[2]); r = miset_dimension_starts(hdim, NDIMS, start_values); r = miset_dimension_separations(hdim, NDIMS, separations); r = micreate_volume("3D_image.mnc", NDIMS, hdim, MI_TYPE_USHORT, MI_CLASS_REAL, NULL, &hvol); /* set slice scaling flag to true */ r = miset_slice_scaling_flag(hvol, flag); r = micreate_volume_image(hvol); for (i = 0; i < CY*CX*CZ; i++) { buf[i] = (unsigned short) i * 0.001; } start[0] = start[1] = start[2] = 0; count[0] = CY; count[1] = CX; count[2] = CZ; r = miset_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, buf); /* Set random values to slice min and max for slice scaling*/ start[0] =start[1]=start[2]=0; for (i=0; i < CY; i++) { start[0] = i; min += 0.1; max += 0.1; r = miset_slice_range(hvol,start,NDIMS , max, min); } r = miclose_volume(hvol); } int create_4D_image(void) { int r; double start_values[NDIMS+1]={-6.96, -12.453, -9.48, 20.002}; double separations[NDIMS+1]={0.09,0.09,0.09, 1}; midimhandle_t hdim[NDIMS+1]; mihandle_t hvol; unsigned char *buf = (unsigned char *) malloc(CX * CU * CZ * CY * sizeof(unsigned char)); int i,j; long count[NDIMS+1]; long start[NDIMS+1]; miboolean_t flag=1; double min = -1.0; double max = 1.0; r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdim[0]); r = micreate_dimension("user", MI_DIMCLASS_USER, MI_DIMATTR_REGULARLY_SAMPLED, CU, &hdim[1]); r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[2]); r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[3]); r = miset_dimension_starts(hdim, NDIMS+1, start_values); r = miset_dimension_separations(hdim, NDIMS+1, separations); r = micreate_volume("4D_image.mnc", NDIMS+1, hdim, MI_TYPE_UBYTE, MI_CLASS_REAL, NULL, &hvol); /* set slice scaling flag to true */ r = miset_slice_scaling_flag(hvol, flag); r = micreate_volume_image(hvol); for (i = 0; i < CX*CU*CZ*CY; i++) { buf[i] = (unsigned char) i; } start[0] = start[1] = start[2] = start[3] = 0; count[0] = CX; count[1] = CU; count[2] = CZ; count[3] = CY; r = miset_voxel_value_hyperslab(hvol, MI_TYPE_UBYTE, start, count, buf); /* Set random values to slice min and max for slice scaling*/ start[0] =start[1]=start[2]=start[3]=0; for (i=0; i < CX; i++) { start[0] = i; for ( j=0; j < CU; j++) { start[1] = j; min += -0.1; max += 0.1; r = miset_slice_range(hvol,start,NDIMS+1 , max, min); } } r = miclose_volume(hvol); } int main(int argc, char **argv) { int r=0; printf("Creating 2D image with IRREGULAR sample dimension!! (2D_image.mnc)\n"); r +=create_2D_image(); printf("Creating 3D image with slice scaling!! (3D_image.mnc)\n"); r +=create_3D_image(); printf("Creating 4D image with slice scaling!! (4D_image.mnc)\n"); r +=create_4D_image(); if (r != 0) { fprintf(stderr, "%d error%s reported\n", r, (r == 1) ? "" : "s"); } else { fprintf(stderr, "\n No errors\n"); } return (r); } minc-2.2.00/libsrc2/test/create-test-images-2.c0000644000265600003100000001023012027132662015741 00000000000000#include #include #include "minc2.h" /* This test will attempt to create a few different test images * which can be tested with minc2.0 */ #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) #define CZ 142 #define CY 245 #define CX 120 #define NDIMS 3 int create_real_as_int_image(void) { int r; double start_values[NDIMS]={-6.96, -12.453, -9.48}; double separations[NDIMS]={0.09,0.09,0.09}; midimhandle_t hdim[NDIMS]; mihandle_t hvol; int *buf = ( int *) malloc(CX * CY * CZ * sizeof(int)); int i; long count[NDIMS]; long start[NDIMS]; miboolean_t flag=1; double min = -1.0; double max = 1.0; r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[0]); r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdim[1]); r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[2]); r = miset_dimension_starts(hdim, NDIMS, start_values); r = miset_dimension_separations(hdim, NDIMS, separations); r = micreate_volume("real_as_int_image.mnc", NDIMS, hdim, MI_TYPE_INT, MI_CLASS_REAL, NULL, &hvol); /* set slice scaling flag to true */ r = miset_slice_scaling_flag(hvol, flag); r = micreate_volume_image(hvol); for (i = 0; i < CY*CX*CZ; i++) { buf[i] = (int) i * 0.001; } start[0] = start[1] = start[2] = 0; count[0] = CY; count[1] = CX; count[2] = CZ; r = miset_voxel_value_hyperslab(hvol, MI_TYPE_INT, start, count, buf); /* Set random values to slice min and max for slice scaling*/ start[0] =start[1]=start[2]=0; for (i=0; i < CY; i++) { start[0] = i; min += -0.1; max += 0.1; r = miset_slice_range(hvol,start,NDIMS , max, min); } r = miclose_volume(hvol); } int create_real_as_float_image(void) { int r; double start_values[NDIMS]={-6.96, -12.453, -9.48}; double separations[NDIMS]={0.09,0.09,0.09}; midimhandle_t hdim[NDIMS]; mihandle_t hvol; float *buf = (float *) malloc(CX * CY * CZ * sizeof(float)); int i; long count[NDIMS]; long start[NDIMS]; miboolean_t flag=1; double min = -1.0; double max = 1.0; r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[0]); r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdim[1]); r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[2]); r = miset_dimension_starts(hdim, NDIMS, start_values); r = miset_dimension_separations(hdim, NDIMS, separations); r = micreate_volume("real_as_float_image.mnc", NDIMS, hdim, MI_TYPE_FLOAT, MI_CLASS_REAL, NULL, &hvol); /* set slice scaling flag to true */ r = miset_slice_scaling_flag(hvol, flag); r = micreate_volume_image(hvol); for (i = 0; i < CY*CX*CZ; i++) { buf[i] = i * 0.001; } start[0] = start[1] = start[2] = 0; count[0] = CY; count[1] = CX; count[2] = CZ; r = miset_voxel_value_hyperslab(hvol, MI_TYPE_FLOAT, start, count, buf); /* Set random values to slice min and max for slice scaling*/ start[0] =start[1]=start[2]=0; for (i=0; i < CY; i++) { start[0] = i; min += -0.1; max += 0.1; r = miset_slice_range(hvol,start,NDIMS , max, min); } r = miclose_volume(hvol); } int main(int argc, char **argv) { int r = 0; printf("Creating 3D image REAL stored as INT w/ slice scaling!! (real_as_int_image.mnc)\n"); r +=create_real_as_int_image(); printf("Creating 3D image REAL stored as FLOAT w/ slice scaling!! (real_as_float_image.mnc)\n"); r +=create_real_as_float_image(); if (r != 0) { fprintf(stderr, "%d error%s reported\n", r, (r == 1) ? "" : "s"); } else { fprintf(stderr, "\n No errors\n"); } return (r); } minc-2.2.00/libsrc2/test/datatype-test.c0000644000265600003100000000170712030103003014675 00000000000000#include #include #include "minc2.h" int main(int argc, char **argv) { miclass_t myclass; mitype_t mytype; misize_t mysize; char *myname; mihandle_t volume; /* Turn off automatic error reporting. */ H5Eset_auto2(H5E_DEFAULT, NULL, NULL); /* Check each file. */ while (--argc > 0) { ++argv; if (micreate_volume(*argv, 0, NULL, 0, 0, NULL, &volume) < 0) { fprintf(stderr, "Error opening %s\n", *argv); } else { int i; /* Repeat many times to expose resource leakage problems, etc. */ for (i = 0; i < 25000; i++) { miget_data_type(volume, &mytype); miget_data_type_size(volume, &mysize); miget_data_class(volume, &myclass); miget_space_name(volume, &myname); mifree_name(myname); } miclose_volume(volume); printf("file: %s type %d size %ld class %d name %s\n", *argv, mytype, mysize, myclass, myname); } } return (0); } minc-2.2.00/libsrc2/test/dimension-test.c0000644000265600003100000001774312027132662015101 00000000000000#include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define CX 10 #define CY 10 #define CZ 6 #define CT 8 #define NDIMS 4 #define XSTART (-24) #define XSTEP (1) #define YSTART (-26) #define YSTEP (2) #define ZSTART (22) #define ZSTEP (-1.5) int check_dims(mihandle_t vol, midimhandle_t dim[]) { int i; int r; int n; mihandle_t vol_tmp; midimhandle_t dim_tmp[NDIMS]; double offsets[100]; for (i = 0; i < CT; i++) { double tmp = -1; r = miget_dimension_offsets(dim[0], 1, i, &tmp); if (r < 0) { TESTRPT("failed", r); } if ((i * i) + 100.0 != tmp) { TESTRPT("bad value", i); } } r = miget_dimension_offsets(dim[1], CX, 0, offsets); if (r < 0) { TESTRPT("failed", r); } for (i = 0; i < CX; i++) { if (offsets[i] != XSTART + (i * XSTEP)) { TESTRPT("bad value", i); } } r = miget_dimension_offsets(dim[2], CY, 0, offsets); if (r < 0) { TESTRPT("failed", r); } for (i = 0; i < CY; i++) { if (offsets[i] != YSTART + (i * YSTEP)) { TESTRPT("bad value", i); } } r = miget_dimension_offsets(dim[3], CZ, 0, offsets); if (r < 0) { TESTRPT("failed", r); } for (i = 0; i < CZ; i++) { if (offsets[i] != ZSTART + (i * ZSTEP)) { TESTRPT("bad value", i); } } r = miget_volume_dimension_count(vol, MI_DIMCLASS_SPATIAL, MI_DIMATTR_ALL, &n); if (r < 0) { TESTRPT("failed", r); } if (n != NDIMS-1) { TESTRPT("wrong number of spatial dimensions", n); } r = miget_volume_dimension_count(vol, MI_DIMCLASS_ANY, MI_DIMATTR_ALL, &n); if (r < 0) { TESTRPT("failed", r); } if (n != NDIMS) { TESTRPT("wrong number of dimensions", n); } r = miget_volume_dimension_count(vol, MI_DIMCLASS_TIME, MI_DIMATTR_ALL, &n); if (r < 0) { TESTRPT("failed", r); } if (n != 1) { TESTRPT("wrong number of time dimensions", n); } for (i = 0; i < NDIMS; i++) { miboolean_t flag_value; r = miget_dimension_sampling_flag(dim[i], &flag_value); if (r < 0) { TESTRPT("error getting sampling flag", r); } else if (flag_value != (i == 0)) { TESTRPT("wrong value for sampling flag", i); } } r = miget_volume_dimensions(vol, MI_DIMCLASS_ANY, MI_DIMATTR_ALL, MI_DIMORDER_FILE, NDIMS, dim_tmp); if (r < 0) { TESTRPT("failed to get dimensions", r); } for (i = 0; i < NDIMS; i++) { vol_tmp = NULL; r = miget_volume_from_dimension(dim_tmp[i], &vol_tmp); if (r < 0) { TESTRPT("failed to get volume from dimension", r); } else if (vol_tmp != vol) { TESTRPT("wrong volume returned", i); } } return (error_cnt); } int main(int argc, char **argv) { mihandle_t vol; int r; midimhandle_t dim[NDIMS]; int n; unsigned long coords[NDIMS]; unsigned long count[NDIMS]; int i,j,k; double offset; unsigned int voxel; /* Write data one voxel at a time. */ for (i = 0; i < NDIMS; i++) { count[i] = 1; } r = micreate_dimension("time", MI_DIMCLASS_TIME, MI_DIMATTR_NOT_REGULARLY_SAMPLED, CT, &dim[0]); if (r < 0) { TESTRPT("failed", r); } for (i = 0; i < CT; i++) { offset = (i * i) + 100.0; r = miset_dimension_offsets(dim[0], 1, i, &offset); if (r < 0) { TESTRPT("failed", r); } } r = micreate_dimension("xspace",MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &dim[1]); if (r < 0) { TESTRPT("failed", r); } r = miset_dimension_start(dim[1], XSTART); if (r < 0) { TESTRPT("failed", r); } r = miset_dimension_separation(dim[1], XSTEP); if (r < 0) { TESTRPT("failed", r); } r = micreate_dimension("yspace",MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &dim[2]); if (r < 0) { TESTRPT("failed", r); } r = miset_dimension_start(dim[2], YSTART); if (r < 0) { TESTRPT("failed", r); } r = miset_dimension_separation(dim[2], YSTEP); if (r < 0) { TESTRPT("failed", r); } r = micreate_dimension("zspace",MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &dim[3]); if (r < 0) { TESTRPT("failed", r); } r = miset_dimension_start(dim[3], ZSTART); if (r < 0) { TESTRPT("failed", r); } r = miset_dimension_separation(dim[3], ZSTEP); if (r < 0) { TESTRPT("failed", r); } r = micreate_volume("tst-dim.mnc", NDIMS, dim, MI_TYPE_UINT, MI_CLASS_REAL, NULL, &vol); if (r < 0) { TESTRPT("failed", r); } r = micreate_volume_image(vol); if (r < 0) { TESTRPT("failed", r); } check_dims(vol, dim); for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { coords[0] = 0; coords[1] = i; coords[2] = j; coords[3] = k; voxel = (i*10000)+(j*100)+k; r = miset_voxel_value_hyperslab(vol, MI_TYPE_UINT, coords, count, &voxel); if (r < 0) { TESTRPT("Error writing voxel", r); } } } } r = miclose_volume(vol); if (r < 0) { TESTRPT("failed", r); } /***** 03-Aug-2004: Added two tests for bugs reported by Leila */ r = miopen_volume("tst-dim.mnc", MI2_OPEN_RDWR, &vol); if (r < 0) { TESTRPT("failed", r); } r = miget_volume_dimension_count(vol, MI_DIMCLASS_ANY, MI_DIMATTR_REGULARLY_SAMPLED, &n); if (r < 0) { TESTRPT("failed", r); } if (n != NDIMS - 1) { TESTRPT("wrong result", n); } r = miget_volume_dimension_count(vol, MI_DIMCLASS_ANY, MI_DIMATTR_NOT_REGULARLY_SAMPLED, &n); if (r < 0) { TESTRPT("failed", r); } if (n != 1) { TESTRPT("wrong result", n); } r = miclose_volume(vol); if (r < 0) { TESTRPT("failed", r); } /* Test #2 - verify that we don't print anything scary if a user * closes a volume prematurely. */ r = micreate_dimension("xspace",MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &dim[0]); if (r < 0) { TESTRPT("failed", r); } r = micreate_dimension("yspace",MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &dim[1]); if (r < 0) { TESTRPT("failed", r); } r = micreate_dimension("zspace",MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &dim[2]); if (r < 0) { TESTRPT("failed", r); } r = micreate_volume("tst-vol.mnc", 3, dim, MI_TYPE_SHORT, MI_CLASS_LABEL, NULL, &vol); if (r < 0) { TESTRPT("failed", r); } r = miclose_volume(vol); if (r < 0) { TESTRPT("failed", r); } /** End of tests added 03-Aug-2004 **/ if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/full-test.c0000644000265600003100000001603012027132662014042 00000000000000/* A test program to evaluate some of the MINC2 API's and features. */ #include #include "minc2.h" #define ND 3 #define CX 100 #define CY 100 #define CZ 100 int test1(int do_real) { int i, j, k; int r; mivolumeprops_t hprops; midimhandle_t hdim[ND]; mihandle_t hvol; double offsets[CX]; unsigned long coords[ND]; for (i = 0; i < CX; i++) { offsets[i] = (double) i * (double) i; } r = minew_volume_props(&hprops); if (r != 0) { fprintf(stderr, "unexpected error\n"); return (1); } r = miset_props_compression_type(hprops, MI_COMPRESS_ZLIB); if (r != 0) { fprintf(stderr, "unexpected error\n"); return (1); } r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_NOT_REGULARLY_SAMPLED, CX, &hdim[0]); if (r != 0) { fprintf(stderr, "unexpected error\n"); return (1); } r = miset_dimension_offsets(hdim[0], 100, 0, offsets); if (r != 0) { fprintf(stderr, "unexpected error\n"); return (1); } r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[1]); if (r < 0) { return (1); } r = miset_dimension_start(hdim[1], -10.0); if (r < 0) { return (1); } r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[2]); if (r < 0) { return (1); } r = miset_dimension_start(hdim[2], -20.0); if (r != 0) { fprintf(stderr, "error setting dimension start\n"); return (1); } r = miset_dimension_separation(hdim[2], 2.0); if (r != 0) { fprintf(stderr, "error setting dimension separation\n"); return (1); } r = micreate_volume("fulltest.mnc", 3, hdim, MI_TYPE_SHORT, MI_CLASS_REAL, hprops, &hvol); if (r != 0) { fprintf(stderr, "error creating volume\n"); return (1); } r = micreate_volume_image(hvol); if (r != 0) { fprintf(stderr, "error creating volume image\n"); return (1); } r = miset_volume_valid_range(hvol, 1000, -1000); if (r != 0) { fprintf(stderr, "error setting valid range\n"); return (1); } r = miset_volume_range(hvol, 5, -5); if (r < 0) { fprintf(stderr, "error setting volume range\n"); return (1); } for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; if (do_real) { r = miset_real_value(hvol, coords, ND, 1.0); if (r < 0) { return (1); } } else { r = miset_voxel_value(hvol, coords, ND, 200.0); if (r < 0) { return (1); } } } } } r = mifree_volume_props(hprops); if (r < 0) { return (1); } r = miclose_volume(hvol); if (r < 0) { return (1); } return (0); } #define CCX 20 #define CCY 20 #define CCZ 20 int test2() { midimhandle_t hdim[ND]; mihandle_t hvol; int r; int i,j,k; unsigned long coords[ND]; unsigned long lengths[ND]; mifcomplex_t fcmpl; r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CCX, &hdim[2]); if (r != 0) { return (1); } r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CCY, &hdim[1]); if (r < 0) { return (1); } r = miset_dimension_start(hdim[1], -10.0); if (r < 0) { return (1); } r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CCZ, &hdim[0]); if (r < 0) { return (1); } r = miset_dimension_start(hdim[2], -20.0); if (r < 0) { fprintf(stderr, "error setting dimension start\n"); return (1); } r = miset_dimension_separation(hdim[2], 2.0); if (r < 0) { fprintf(stderr, "error setting dimension separation\n"); return (1); } r = micreate_volume("cmpltest.mnc", 3, hdim, MI_TYPE_FCOMPLEX, MI_CLASS_COMPLEX, NULL, &hvol); if (r != 0) { fprintf(stderr, "error creating volume\n"); return (1); } r = miset_volume_valid_range(hvol, 1919.0, 0.0); r = micreate_volume_image(hvol); if (r != 0) { fprintf(stderr, "error creating volume image\n"); return (1); } lengths[0] = lengths[1] = lengths[2] = 1; for (i = 0; i < CCX; i++) { for (j = 0; j < CCY; j++) { for (k = 0; k < CCZ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; fcmpl.real = (i * 100) + j; fcmpl.imag = k; r = miset_voxel_value_hyperslab(hvol, MI_TYPE_FCOMPLEX, coords, lengths, &fcmpl); if (r < 0) { fprintf(stderr, "error writing complex voxel\n"); return (1); } } } } for (i = 0; i < CCX; i++) { for (j = 0; j < CCY; j++) { for (k = 0; k < CCZ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; r = miget_voxel_value_hyperslab(hvol, MI_TYPE_FCOMPLEX, coords, lengths, &fcmpl); if (r < 0) { fprintf(stderr, "error writing complex voxel\n"); return (1); } if (fcmpl.real != (i * 100) + j || fcmpl.imag != k) { fprintf(stderr, "value mismatch for complex voxel\n"); return (1); } } } } r = miclose_volume(hvol); if (r < 0) { return (1); } return (0); } int main(int argc, char **argv) { int errors; int do_real = 0; while (--argc > 0) { char *argp = *++argv; if (*argp == '-') { argp++; switch (*argp) { case 'r': do_real = 1; break; } } } errors = 0; errors += test1(do_real); errors += test2(); if (errors == 0) { printf("No errors\n"); } else { printf("%d error%s found\n", errors, (errors == 1) ? "" : "s"); } return (errors); } minc-2.2.00/libsrc2/test/grpattr-test.c0000644000265600003100000001646112030104200014550 00000000000000#include #include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) #define TESTARRAYSIZE 11 static int error_cnt = 0; int main(int argc, char **argv) { mihandle_t hvol; mihandle_t hvol1; int r; mitype_t data_type; int length; static double tstarr[TESTARRAYSIZE] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10, 11.11 }; double dblarr[TESTARRAYSIZE]; float fltarr[TESTARRAYSIZE]; int intarr[TESTARRAYSIZE]; char valstr[128]; float val1=12.5; float val2=34.5; milisthandle_t hlist, h1list; char pathbuf[256]; char namebuf[256]; char pathbuf1[256]; int count=0; r = micreate_volume("tst-grpa.mnc", 0, NULL, MI_TYPE_UINT, MI_CLASS_INT, NULL, &hvol); if (r < 0) { TESTRPT("Unable to create test file", r); return (-1); } r = micreate_volume("tst-grpb.mnc", 0, NULL, MI_TYPE_UINT, MI_CLASS_INT, NULL, &hvol1); if (r < 0) { TESTRPT("Unable to create test file", r); return (-1); } r = micreate_group(hvol, "/", "test1"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/", "test2"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/", "test3"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/", "test4"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/test2", "stuff2"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/test1", "stuff"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/test1", "otherstuff"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/test1", "theotherstuff"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/test1/theotherstuff", "thisstuff"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/test1/stuff", "hello"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = micreate_group(hvol, "/test1/stuff", "helloleila"); if (r < 0) { TESTRPT("micreate_group failed", r); } r = miset_attr_values(hvol, MI_TYPE_STRING, "/test1/stuff/hello", "animal", 8, "fruitbat"); if (r < 0) { TESTRPT("miset_attr_values failed", r); } r = miset_attr_values(hvol, MI_TYPE_STRING, "/test1/stuff", "objtype", 10, "automobile"); if (r < 0) { TESTRPT("miset_attr_values failed", r); } r = miset_attr_values(hvol, MI_TYPE_STRING, "/test3", "objtype", 10, "automobile"); if (r < 0) { TESTRPT("miset_attr_values failed", r); } r = miset_attr_values(hvol, MI_TYPE_STRING, "/test1/stuff", "objname", 10, "automobile"); if (r < 0) { TESTRPT("miset_attr_values failed", r); } r = miset_attr_values(hvol, MI_TYPE_DOUBLE, "/test2", "maxvals", TESTARRAYSIZE, tstarr); if (r < 0) { TESTRPT("miset_attr_values failed", r); } r = miget_attr_type(hvol, "/test1/stuff/hello", "animal", &data_type); if (r < 0) { TESTRPT("miget_attr_type failed", r); } r = miget_attr_length(hvol, "/test1/stuff/hello", "animal", &length); if (r < 0) { TESTRPT("miget_attr_length failed", r); } if (data_type != MI_TYPE_STRING) { TESTRPT("miget_attr_type failed", data_type); } if (length != 8) { TESTRPT("miget_attr_length failed", length); } r = midelete_group(hvol, "/test1/stuff", "goodbye"); if (r >= 0) { TESTRPT("midelete_group failed", r); } r = midelete_group(hvol, "/test1/stuff", "hello"); /* This should succeed. */ if (r < 0) { TESTRPT("midelete_group failed", r); } r = miget_attr_length(hvol, "/test1/stuff/hello", "animal", &length); /* This should fail since we deleted the group. */ if (r >= 0) { TESTRPT("miget_attr_length failed", r); } r = miget_attr_values(hvol, MI_TYPE_DOUBLE, "/test2", "maxvals", TESTARRAYSIZE, dblarr); if (r < 0) { TESTRPT("miget_attr_values failed", r); } for (r = 0; r < TESTARRAYSIZE; r++) { if (dblarr[r] != tstarr[r]) { TESTRPT("miget_attr_values mismatch", r); } } /* Get the values again in float rather than double format. */ r = miget_attr_values(hvol, MI_TYPE_FLOAT, "/test2", "maxvals", TESTARRAYSIZE, fltarr); if (r < 0) { TESTRPT("miget_attr_values failed", r); } for (r = 0; r < TESTARRAYSIZE; r++) { if (fltarr[r] != (float) tstarr[r]) { TESTRPT("miget_attr_values mismatch", r); fprintf(stderr, "fltarr[%d] = %f, tstarr[%d] = %f\n", r, fltarr[r], r, tstarr[r]); } } /* Get the values again in int rather than double format. */ r = miget_attr_values(hvol, MI_TYPE_INT, "/test2", "maxvals", TESTARRAYSIZE, intarr); if (r < 0) { TESTRPT("miget_attr_values failed", r); } for (r = 0; r < TESTARRAYSIZE; r++) { if (intarr[r] != (int) tstarr[r]) { TESTRPT("miget_attr_values mismatch", r); fprintf(stderr, "intarr[%d] = %d, tstarr[%d] = %d\n", r, intarr[r], r, (int) tstarr[r]); } } r = miget_attr_values(hvol, MI_TYPE_STRING, "/test1/stuff", "objtype", 128, valstr); if (r < 0) { TESTRPT("miget_attr_values failed", r); } if (strcmp(valstr, "automobile") != 0) { TESTRPT("miget_attr_values failed", 0); } r = miset_attr_values(hvol, MI_TYPE_STRING, "/test1/stuff", "objtype", 8, "bicycle"); if (r < 0) { TESTRPT("miset_attr_values failed on rewrite", r); } r = miget_attr_values(hvol, MI_TYPE_STRING, "/test1/stuff", "objtype", 128, valstr); if (r < 0) { TESTRPT("miget_attr_values failed", r); } if (strcmp(valstr, "bicycle") != 0) { TESTRPT("miget_attr_values failed", 0); } r = miset_attr_values(hvol, MI_TYPE_FLOAT, "/OPT", "zoom",1, &val1); if (r < 0) { TESTRPT("micreate_group failed", r); } r = miset_attr_values(hvol, MI_TYPE_FLOAT, "/OPT", "binning",1, &val2); r = miset_attr_values(hvol, MI_TYPE_FLOAT, "/OPT", "gain",1, &val1); if (r < 0) { TESTRPT("micreate_group failed", r); } r = milist_start(hvol, "/", 1, &hlist); if (r == MI_NOERROR) { count++; while (milist_attr_next(hvol, hlist, pathbuf, sizeof(pathbuf), namebuf, sizeof(namebuf)) == MI_NOERROR) { printf(" %s %s\n", pathbuf, namebuf); } } milist_finish(hlist); printf("copy all attributes in the provided path in the new volume\n"); r = micopy_attr(hvol,"/OPT",hvol1); printf("***************** \n"); r = milist_start(hvol, "/", 1, &h1list); if (r == MI_NOERROR) { while( milist_grp_next(h1list, pathbuf1, sizeof(pathbuf1)) == MI_NOERROR) { printf("%s \n", pathbuf1); } } milist_finish(h1list); miclose_volume(hvol); miclose_volume(hvol1); if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/hyper-test.c0000644000265600003100000003312312027132662014231 00000000000000#include #include #include #include "minc2.h" #include "config.h" #define NDIMS 3 #define CX 11 #define CY 12 #define CZ 9 #define TESTRPT(msg, val) (error_cnt++, printf(\ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define XP 101 #define YP 17 #define ZP 1 #define VALID_MAX (((CX-1)*XP)+((CY-1)*YP)+((CZ-1)*ZP)) #define VALID_MIN (0.0) #define REAL_MAX (1.0) #define REAL_MIN (-1.0) #define NORM_MAX (1.0) #define NORM_MIN (-1.0) int main(int argc, char **argv) { mihandle_t hvol; int result; unsigned long start[NDIMS]; unsigned long count[NDIMS]; double dtemp[CX][CY][CZ]; unsigned short stmp2[CX][CY][CZ]; unsigned short stemp[CZ][CX][CY]; unsigned char btemp[CZ][CX][CY]; int i,j,k; midimhandle_t hdims[NDIMS]; char *dimnames[] = {"zspace", "xspace", "yspace"}; result = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdims[0]); result = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdims[1]); result = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdims[2]); result = micreate_volume("tst-hyper.mnc", NDIMS, hdims, MI_TYPE_UINT, MI_CLASS_REAL, NULL, &hvol); if (result < 0) { TESTRPT("Unable to create test volume", result); } result = miget_volume_dimensions(hvol, MI_DIMCLASS_ANY, MI_DIMATTR_ALL, MI_DIMORDER_FILE, NDIMS, hdims); if (result < 0) { TESTRPT("Unable to get volume dimensions", result); } micreate_volume_image(hvol); for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { stmp2[i][j][k] = (i*XP)+(j*YP)+(k*ZP); } } } result = miset_volume_valid_range(hvol, VALID_MAX, VALID_MIN); if (result < 0) { TESTRPT("error setting valid range", result); } result = miset_volume_range(hvol, REAL_MAX, REAL_MIN); if (result < 0) { TESTRPT("error setting real range", result); } start[0] = start[1] = start[2] = 0; count[0] = CX; count[1] = CY; count[2] = CZ; result = miset_voxel_value_hyperslab(hvol, MI_TYPE_SHORT, start, count, stmp2); if (result < 0) { TESTRPT("unable to set hyperslab", result); } start[0] = start[1] = start[2] = 0; count[0] = CX; count[1] = CY; count[2] = CZ; result = miget_real_value_hyperslab(hvol, MI_TYPE_DOUBLE, start, count, dtemp); printf("miget_real_value_hyperslab()\n"); if (result < 0) { TESTRPT("Unable to read real value hyperslab", result); } else { for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { double r = stmp2[i][j][k]; /* Use fixed known values for valid range, etc. */ r -= VALID_MIN; r /= (VALID_MAX - VALID_MIN); r *= (REAL_MAX - REAL_MIN); r += REAL_MIN; /* Have to do approximate comparison, since conversion may * not be exact. */ if (fabs(r - dtemp[i][j][k]) > 1.0e-15) { TESTRPT("Value error!", 0); break; } } } } } printf("miget_voxel_value_hyperslab, default dimensions\n"); memset(stmp2, 0, sizeof(short)*CX*CY*CZ); /* Clear the array. */ result = miget_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stmp2); if (result < 0) { TESTRPT("Unable to get raw hyperslab", result); } else { /* Verify all of the values. */ for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { if (stmp2[i][j][k] != (i*XP)+(j*YP)+(k*ZP)) { TESTRPT("Value error", 0); break; } } } } } result = miset_apparent_dimension_order_by_name(hvol, NDIMS, dimnames); if (result < 0) { TESTRPT("unable to set dimension order", result); } printf("miget_voxel_value_hyperslab(), swapped dimensions\n"); start[0] = start[1] = start[2] = 0; count[0] = CZ; count[1] = CX; count[2] = CY; result = miget_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stemp); if (result < 0) { TESTRPT("Error reading swapped hyperslab", result); } else { for (i = 0; i < CZ; i++) { for (j = 0; j < CX; j++) { for (k = 0; k < CY; k++) { if (stemp[i][j][k] != (j*XP)+(k*YP)+(i*ZP)) { printf("%d != %d: ", stemp[i][j][k], (j*XP)+(k*YP)+(i*ZP)); TESTRPT("Value error", 0); break; } } } } } /******************************************************************** * Read and validate the entire dataset. * This is done with: * - Axes in (z,y,x) order * - Z axis reversed */ printf("miget_voxel_hyperslab, reversed Z axis\n"); result = miset_dimension_apparent_voxel_order(hdims[2], MI_COUNTER_FILE_ORDER); if (result < 0) { TESTRPT("unable to set voxel order", result); } start[0] = start[1] = start[2] = 0; count[0] = CZ; count[1] = CX; count[2] = CY; result = miget_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stemp); if (result < 0) { TESTRPT("Error reading swapped hyperslab", result); } else { for (i = 0; i < CZ; i++) { for (j = 0; j < CX; j++) { for (k = 0; k < CY; k++) { short t = (j*XP)+(k*YP)+(((CZ-1)-i)*ZP); if (stemp[i][j][k] != t) { printf("%d != %d: ", stemp[i][j][k], t); TESTRPT("Value error", 0); break; } } } } } /******************************************************************** * Attempt to get a series of 3x2x2 matrices from the file. * This is done with: * - Axes in (z,x,y) order * - Z axis reversed */ printf("Read 3x2x2 matrices of voxel values:\n"); count[0] = 3; count[1] = 2; count[2] = 2; for (i = 0; (i + 3) < CZ; i += 3) { for (j = 0; (j + 2) < CX; j += 2) { for (k = 0; (k + 2) < CY; k += 2) { short stmp3[3][2][2]; start[0] = i; start[1] = j; start[2] = k; result = miget_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stmp3); if (result < 0) { TESTRPT("Error reading swapped hyperslab", result); } else { int q,r,s; for (q = 0; q < 3; q++) { for (r = 0; r < 2; r++) { for (s = 0; s < 2; s++) { int x,y,z; short t; x = r + j; y = s + k; z = q + i; t = (x*XP)+(y*YP)+(((CZ-1)-z)*ZP); if (stmp3[q][r][s] != t) { printf("%d != %d: ", stmp3[q][r][s], t); TESTRPT("Value error", 0); break; } } } } } } } } /********************************************************************* * Read the entire dataset, normalized. * * This is done with the axes in (z,y,x) order, but with the Z axis * restored to normal (file) order. */ printf("miget_hyperslab_normalized()\n"); result = miset_dimension_apparent_voxel_order(hdims[2], MI_FILE_ORDER); if (result < 0) { TESTRPT("unable to set voxel order", result); } start[0] = start[1] = start[2] = 0; count[0] = CZ; count[1] = CX; count[2] = CY; result = miget_hyperslab_normalized(hvol, MI_TYPE_UBYTE, start, count, NORM_MIN, NORM_MAX, btemp); if (result < 0) { TESTRPT("Can't read normalized hyperslab", result); } else { for (i = 0; i < CZ; i++) { for (j = 0; j < CX; j++) { for (k = 0; k < CY; k++) { double r = stmp2[j][k][i]; /* Calculate what the normalized value ought to be * in this case. Use fixed known values for valid * range, etc. */ r -= VALID_MIN; r /= (VALID_MAX - VALID_MIN); r *= (REAL_MAX - REAL_MIN); r += REAL_MIN; /* r now contains the alleged "real" value for this * voxel. Now we have to map it to 0-255 for the * unsigned byte type. */ if (r > NORM_MAX) { r = 255; } else if (r < NORM_MIN) { r = 0; } else { r = ((r - REAL_MIN) / (REAL_MAX - REAL_MIN)) * 255; } if (btemp[i][j][k] != (unsigned char)rint(r)) { TESTRPT("Value error!", 0); break; } } } } } /******************************************************************** * Now read, modify, write, and repeat, performing an exclusive OR * operation on each voxel value. * Axes are still in (z,y,x) order. */ printf("read and write entire hyperslab:\n"); result = miget_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stemp); if (result < 0) { TESTRPT("Can't read hyperslab", result); } else { for (i = 0; i < CZ; i++) { for (j = 0; j < CX; j++) { for (k = 0; k < CY; k++) { short t = stemp[i][j][k]; if (t != (j*XP)+(k*YP)+(i*ZP)) { printf("%d != %d: ", t, (j*XP)+(k*YP)+(i*ZP)); TESTRPT("Value error!", 0); } stemp[i][j][k] ^= 0x5555; } } } } result = miset_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stemp); /* stemp has now been modified by the operation! */ result = miget_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stemp); if (result < 0) { TESTRPT("oops", result); } else { for (i = 0; i < CZ; i++) { for (j = 0; j < CX; j++) { for (k = 0; k < CY; k++) { short t = stemp[i][j][k] ^ 0x5555; if (t != (j*XP)+(k*YP)+(i*ZP)) { printf("%d != %d: ", t, (j*XP)+(k*YP)+(i*ZP)); TESTRPT("Value error!", 0); } stemp[i][j][k] = t; } } } } result = miset_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stemp); if (result < 0) { TESTRPT("miset_voxel_value_hyperslab failed\n", result); } /* This call should have the effect of resetting the dimension order * to the "raw" file order. */ miset_apparent_dimension_order_by_name(hvol, 0, NULL); /* Verify this. */ printf("Read and verify hyperslab in original dimension order:\n"); start[0] = start[1] = start[2]; count[0] = CX; count[1] = CY; count[2] = CZ; result = miget_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, stmp2); if (result < 0) { TESTRPT("Unable to read real value hyperslab", result); } else { for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { short t = stmp2[i][j][k]; if (t != (i*XP)+(j*YP)+(k*ZP)) { printf("%d != %d: ", t, (i*XP)+(j*YP)+(k*ZP)); TESTRPT("Value error!", 0); break; } } } } } miclose_volume(hvol); if (error_cnt == 0) { printf("No errors\n"); } else { printf("**** %d error%s\n", error_cnt, (error_cnt == 1) ? "" : "s"); } return (error_cnt); } minc-2.2.00/libsrc2/test/hyper-test-2.c0000644000265600003100000001430112027132662014365 00000000000000#include #include #include "minc2.h" /* Courtesy of Dr Jason Lerch * A test of the dimensions ordering/hyperslab functions in minc2. The * basic flow is the following: * open an existing minc volume * set the apparent dimension order to be different from the file order * get the volume dimensions * load the entire image into a buffer using the hyperslab function * compare with single voxel value returned from single voxel functions. */ #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define CZ 142 #define CY 245 #define CX 210 #define NDIMS 3 void create_test_file(void) { int r; double start_values[3]={-6.96, -12.453, -9.48}; double separations[3]={0.09,0.09,0.09}; midimhandle_t hdim[NDIMS]; mihandle_t hvol; unsigned short *buf = ( unsigned short *) malloc(CX * CY * CZ * sizeof(unsigned short)); int i; long count[NDIMS]; long start[NDIMS]; miboolean_t flag=1; double min = -1.0; double max = 1.0; r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[0]); r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[1]); r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdim[2]); r = miset_dimension_starts(hdim, NDIMS, start_values); r = miset_dimension_separations(hdim, NDIMS, separations); r = micreate_volume("hyperslab-test2.mnc", NDIMS, hdim, MI_TYPE_USHORT, MI_CLASS_REAL, NULL, &hvol); /* set slice scaling flag to true */ r = miset_slice_scaling_flag(hvol, flag); r = micreate_volume_image(hvol); for (i = 0; i < CZ*CY*CX; i++) { buf[i] = (unsigned short) i * 0.01; } start[0] = start[1] = start[2] = 0; count[0] = CZ; count[1] = CY; count[2] = CX; r = miset_voxel_value_hyperslab(hvol, MI_TYPE_USHORT, start, count, buf); /* Set random values to slice min and max for slice scaling*/ start[0] =start[1]=start[2]=0; for (i=0; i < CZ; i++) { start[0] = i; min += 0.1; max += 0.1; r = miset_slice_range(hvol,start, 3, max, min); } r = miclose_volume(hvol); } int main(int argc, char **argv) { mihandle_t vol; midimhandle_t dim[NDIMS]; unsigned int sizes[NDIMS]; unsigned long start[NDIMS]; unsigned long count[NDIMS]; unsigned long howfar[NDIMS]; unsigned long location[NDIMS]; double *buffer,value; int r = 0; static char *dimorder[] = {"xspace", "yspace", "zspace"}; printf("Creating image with slice scaling!! \n"); create_test_file(); printf("Opening hyperslab-test2.mnc! \n"); r = miopen_volume("hyperslab-test2.mnc", MI2_OPEN_READ, &vol); if (r < 0) { TESTRPT("failed to open image", r); } #ifdef APPARENTORDER /* set the apparent dimension order to be xyz */ r = miset_apparent_dimension_order_by_name(vol, 3, dimorder); /* get the apparent dimensions and their sizes */ r = miget_volume_dimensions( vol, MI_DIMCLASS_SPATIAL, MI_DIMATTR_ALL, MI_DIMORDER_APPARENT, 3, dim); r = miget_dimension_sizes( dim, 3, sizes ); #else /* get the apparent dimensions and their sizes */ r = miget_volume_dimensions( vol, MI_DIMCLASS_SPATIAL, MI_DIMATTR_ALL, MI_DIMORDER_FILE, 3, dim); r = miget_dimension_sizes( dim, 3, sizes ); #endif if (r == MI_NOERROR) { printf("Sizes: %d, %d, %d\n", sizes[0], sizes[1], sizes[2]); } else { fprintf(stderr, "Error getting dimension sizes\n"); } /* try to play with hyperslab functions!! */ start[0] = 4; start[1] = 3; start[2] = 5; howfar[0] = 120; howfar[1] = 180; howfar[2] = 110; count[0] = howfar[0] - start[0]; count[1] = howfar[1] - start[1]; count[2] = howfar[2] - start[2]; /* Alocate memory for the hyperslab*/ buffer = (double *)malloc(count[0] * count[1] * count[2] * sizeof(double)); if (buffer == NULL) { fprintf(stderr, "Error allocation memory.\n"); exit(-1); } /* Get real value hyperslab*/ printf("\n"); printf("Getting a real value hyperslab \n"); printf("Starting at %d, %d, %d \n", start[0], start[1], start[2]); printf("Extending to %d, %d, %d \n", howfar[0], howfar[1], howfar[2]); printf("\n"); if (miget_real_value_hyperslab(vol,MI_TYPE_DOUBLE, start, count, buffer) < 0) { fprintf(stderr, "Could not get hyperslab.\n"); exit(-1); } /* set an arbitrary location to print values from */ location[0] = 70; location[1] = 100; location[2] = 104; printf("Test arbitrary location %d, %d, %d \n", location[0], location[1], location[2]); miget_real_value(vol, location, 3, &value); printf("Test from hyperslab: %f \n", *( buffer + (location[0] - start[0])*count[1]*count[2] + (location[1]- start[1]) * count[2] + (location[2]- start[2]))); printf("Test from voxel scaled: %f\n", value); miget_voxel_value(vol, location, 3, &value); printf("Test voxel value itself: %f\n", value); printf("\n"); printf("HMMMMMMMMMM! let's try something else \n"); printf("\n"); /* set another arbitrary location to print values from */ location[0] = 104; location[1] = 100; location[2] = 70; printf("Test arbitrary location %d, %d, %d \n", location[0], location[1], location[2]); miget_real_value(vol, location, 3, &value); printf("Test from hyperslab: %f \n", *( buffer + (location[0] - start[0])*count[1]*count[2] + (location[1]- start[1]) * count[2] + (location[2]- start[2]))); printf("Test from voxel scaled: %f\n", value); miget_voxel_value(vol, location, 3, &value); printf("Test voxel value itself: %f\n", value); /* close volume*/ miclose_volume(vol); if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "\n No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/label-test.c0000644000265600003100000001261512027132662014164 00000000000000#include #include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define CX 3 #define CY 4 #define CZ 2 #define NDIMS 3 int create_label_image(void) { mihandle_t hvol; char *name; int result; int value; midimhandle_t hdim[3]; unsigned long coords[3]; int i,j,k; int counter=0; result = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, 10, &hdim[0]); result = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, 10, &hdim[1]); result = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, 6, &hdim[2]); result = micreate_volume("tst-label.mnc", 3, hdim, MI_TYPE_UINT, MI_CLASS_LABEL, NULL, &hvol); if (result < 0) { fprintf(stderr, "Unable to create test file %x\n", result); return (-1); } result = miget_number_of_defined_labels(hvol,&value); if (result != MI_NOERROR) { TESTRPT("Invalid return from miget_label_name", result); } else { printf(" %d \n", value); } /* Now test some stuff... */ midefine_label(hvol, 0, "Black"); midefine_label(hvol, 0xffffff, "White"); midefine_label(hvol, 0x808080, "Grey"); midefine_label(hvol, 0xff0000, "Red"); midefine_label(hvol, 0x00ff00, "Blue"); midefine_label(hvol, 0x0000ff, "Green"); result = miget_number_of_defined_labels(hvol,&value); if (result != MI_NOERROR) { TESTRPT("Invalid return from miget_label_name", result); } else { printf(" %d \n", value); } result = miget_label_name(hvol, 0, &name); if (result != MI_NOERROR) { TESTRPT("Invalid return from miget_label_name", result); } if (strcmp(name, "Black") != 0) { TESTRPT("Unexpected label for value 0", 0); } mifree_name(name); result = miget_label_name(hvol, 0x00ff00, &name); if (result != MI_NOERROR) { TESTRPT("Invalid return from miget_label_name", result); } if (strcmp(name, "Blue") != 0) { TESTRPT("Unexpected label for value 0", 0); } mifree_name(name); result = miget_label_name(hvol, 1, &name); if (result != MI_ERROR) { TESTRPT("Invalid return from miget_label_name", result); } result = miget_label_value(hvol, "White", &value); if (result != MI_NOERROR) { TESTRPT("Invalid return from miget_label_value", result); } if (value != 0xffffff) { TESTRPT("Unexpected value for label 'White'", 0); } result = miget_label_value(hvol, "Mauve", &value); if (result != MI_ERROR) { TESTRPT("Invalid return from miget_label_value", result); } micreate_volume_image(hvol); for (i=0; i < CX; i++) { for (j=0; j < CY ; j++) { for (k=0; k < CZ ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; if (counter == 1) { miset_voxel_value(hvol,coords, 3, 0xffffff); } else if ( counter ==2) { miset_voxel_value(hvol,coords, 3, 0x808080); } else if ( counter ==3) { miset_voxel_value(hvol,coords, 3, 0xff0000); } else if ( counter ==4) { miset_voxel_value(hvol,coords, 3, 0x00ff00); } else if (counter ==5) { miset_voxel_value(hvol,coords, 3,0x0000ff ); } else { miset_voxel_value(hvol,coords, 3, 0); } counter++; if (counter >=6) { counter =0; } } } } miclose_volume(hvol); return 0; } int main(int argc, char **argv) { int i,j,k; mihandle_t vol; midimhandle_t hdims[NDIMS], cp_hdims[NDIMS]; unsigned long coords[NDIMS]; unsigned long count[NDIMS]; int value; int counter = 0; int id; int *buf = (int *)malloc(CX * CY * CZ * sizeof(int)); printf("Creating label image !! \n"); error_cnt += create_label_image(); error_cnt += miopen_volume("tst-label.mnc", MI2_OPEN_READ, &vol); miget_number_of_defined_labels(vol,&value); printf("Number of defined labels %d \n", value); miget_label_value(vol, "White", &value); coords[0] = coords[1] = coords[2] = 0; count[0] = CX; count[1] = CY; count[2] = CZ; error_cnt += miget_voxel_value_hyperslab(vol,MI_TYPE_INT, coords, count,buf); printf("Print label file with file order x,y,z \n"); for (i=0; i < CX; i++) { for (j=0; j < CY; j++) { for (k=0; k < CZ; k++) { id = i * CY * CZ + j * CZ + k; printf("%8x ", buf[id]); counter++; if (counter == 6) { counter = 0; printf(" \n"); } } } } miget_volume_dimensions(vol, MI_DIMCLASS_ANY, MI_DIMATTR_REGULARLY_SAMPLED, MI_DIMORDER_FILE, NDIMS, hdims); cp_hdims[0] = hdims[2]; cp_hdims[1] = hdims[1]; cp_hdims[2] = hdims[0]; miset_apparent_dimension_order(vol, NDIMS, cp_hdims); coords[0] = coords[1] = coords[2] = 0; count[0] = CZ; count[1] = CY; count[2] = CX; error_cnt += miget_voxel_value_hyperslab(vol,MI_TYPE_UINT, coords, count,buf); printf("Print label file with apparent order z,y,x \n"); counter = 0; for (i=0; i < CZ; i++) { for (j=0; j < CY; j++) { for (k=0; k < CX; k++) { id = i * CY * CX + j * CX + k; printf("%8x ", buf[id]); counter++; if (counter == 6) { counter = 0; printf(" \n"); } } } } error_cnt += miclose_volume(vol); if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/multires-test.c0000644000265600003100000001023412027132662014744 00000000000000#include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define CX 60 #define CY 55 #define CZ 50 #define NDIMS 3 int main(int argc, char **argv) { mihandle_t vol; int r; midimhandle_t dim[NDIMS]; mivolumeprops_t props; int n; unsigned long coords[NDIMS]; unsigned long count[NDIMS]; int i,j,k; unsigned int voxel; printf("Creating volume...\n"); /* Write data one voxel at a time. */ for (i = 0; i < NDIMS; i++) { count[i] = 1; } r = minew_volume_props(&props); r = miset_props_compression_type(props, MI_COMPRESS_ZLIB); r = miset_props_zlib_compression(props, 3); r = miset_props_multi_resolution(props, 1, 3); if (r < 0) { TESTRPT("failed", r); } r = micreate_dimension("xspace",MI_DIMCLASS_SPATIAL,MI_DIMATTR_REGULARLY_SAMPLED, CX,&dim[0]); if (r < 0) { TESTRPT("failed", r); } r = micreate_dimension("yspace",MI_DIMCLASS_SPATIAL,MI_DIMATTR_REGULARLY_SAMPLED, CY, &dim[1]); if (r < 0) { TESTRPT("failed", r); } r = micreate_dimension("zspace",MI_DIMCLASS_SPATIAL,MI_DIMATTR_REGULARLY_SAMPLED, CZ,&dim[2]); if (r < 0) { TESTRPT("failed", r); } r = micreate_volume("tst-multi.mnc", NDIMS, dim, MI_TYPE_UINT, MI_CLASS_REAL,props,&vol); if (r < 0) { TESTRPT("failed", r); } r = miset_volume_valid_range(vol, CX*10000.0 + CY*100 + CZ, 0.0); r = micreate_volume_image(vol); if (r < 0) { TESTRPT("failed", r); } r = miget_volume_dimension_count(vol, MI_DIMCLASS_SPATIAL, MI_DIMATTR_ALL, &n); if (r < 0) { TESTRPT("failed", r); } printf("Writing data...\n"); for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; voxel = i*10000 + j*100 + k; r = miset_voxel_value_hyperslab(vol, MI_TYPE_UINT, coords, count, &voxel); if (r < 0) { TESTRPT("Error writing voxel", r); } } } } printf("Selecting half-size image\n"); r = miselect_resolution(vol, 1); if (r < 0) { TESTRPT("miselect_resolution failed", r); } /* OK, now try to read the lower-resolution hyperslab */ coords[0] = 0; coords[1] = 0; coords[2] = 0; count[0] = CX/2; count[1] = CY/2; count[2] = CZ/2; { unsigned int buffer[CX/2][CY/2][CZ/2]; r = miget_voxel_value_hyperslab(vol, MI_TYPE_UINT, coords, count, buffer); if (r < 0) { TESTRPT("failed", r); } } printf("Selecting quarter-size image\n"); r = miselect_resolution(vol, 2); if (r < 0) { TESTRPT("miselect_resolution failed", r); } /* OK, now try to read the lower-resolution hyperslab */ coords[0] = 0; coords[1] = 0; coords[2] = 0; count[0] = CX/4; count[1] = CY/4; count[2] = CZ/4; { unsigned int buffer[CX/4][CY/4][CZ/4]; r = miget_voxel_value_hyperslab(vol, MI_TYPE_UINT, coords, count, buffer); if (r < 0) { TESTRPT("failed", r); } } printf("Return to full resolution.\n"); r = miselect_resolution(vol, 0); /* Back to full resolution */ if (r < 0) { TESTRPT("miselect_resolution failed", r); } printf("Flush any remaining thumbnails.\n"); r = miflush_from_resolution(vol, 3); if (r < 0) { TESTRPT("failed", r); } r = miclose_volume(vol); if (r < 0) { TESTRPT("failed", r); } if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/record-test.c0000644000265600003100000000704412027132662014363 00000000000000#include #include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define CX 10 #define CY 10 #define CZ 6 #define NDIMS 3 int main(int argc, char **argv) { mihandle_t hvol; char *name; int result; midimhandle_t hdim[NDIMS]; unsigned long coords[NDIMS]; unsigned long count[NDIMS]; int i,j,k; struct test { int r; int g; int b; } voxel; /* Write data one voxel at a time. */ for (i = 0; i < NDIMS; i++) { count[i] = 1; } result = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdim[0]); result = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[1]); result = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[2]); result = micreate_volume("tst-rec.mnc", NDIMS, hdim, MI_TYPE_UINT, MI_CLASS_UNIFORM_RECORD, NULL, &hvol); if (result < 0) { TESTRPT("Unable to create test file", result); } result = miset_record_field_name(hvol, 0, "Red"); if (result < 0) { TESTRPT("miset_record_field_name", result); } miset_record_field_name(hvol, 1, "Green"); miset_record_field_name(hvol, 2, "Blue"); miget_record_field_name(hvol, 1, &name); if (strcmp(name, "Green") != 0) { TESTRPT("Unexpected label for value 1", 0); } mifree_name(name); miget_record_field_name(hvol, 0, &name); if (strcmp(name, "Red") != 0) { TESTRPT("Unexpected label for value 0", 0); } mifree_name(name); miget_record_field_name(hvol, 2, &name); if (strcmp(name, "Blue") != 0) { TESTRPT("Unexpected label for value 2", 0); } mifree_name(name); result = micreate_volume_image(hvol); if (result < 0) { TESTRPT("micreate_volume_image failed", result); } for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; voxel.r = i; voxel.g = j; voxel.b = k; result = miset_voxel_value_hyperslab(hvol, MI_TYPE_UNKNOWN, coords, count, &voxel); if (result < 0) { TESTRPT("Error writing voxel", result); } } } } for (i = 0; i < CX; i++) { for (j = 0; j < CY; j++) { for (k = 0; k < CZ; k++) { coords[0] = i; coords[1] = j; coords[2] = k; result = miget_voxel_value_hyperslab(hvol, MI_TYPE_UNKNOWN, coords, count, &voxel); if (result < 0) { TESTRPT("Error reading voxel", result); } if (voxel.r != i || voxel.g != j || voxel.b != k) { TESTRPT("Data mismatch", 0); } } } } miclose_volume(hvol); if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/slice-test.c0000644000265600003100000000144612027132662014204 00000000000000#include #include #include "minc2.h" int main(int argc, char **argv) { mihandle_t hvol; int r; unsigned long coords[3]; double min, max; int i; while (--argc > 0) { r = miopen_volume(*++argv, MI2_OPEN_READ, &hvol); if (r < 0) { fprintf(stderr, "can't open %s, error %d\n", *argv, r); } else { for (i = 0; i < 10; i++) { coords[0] = i; coords[1] = rand(); coords[2] = rand(); r = miget_slice_min(hvol, coords, 3, &min); if (r < 0) { fprintf(stderr, "error %d getting slice minimum\n", r); } r = miget_slice_max(hvol, coords, 3, &max); if (r < 0) { fprintf(stderr, "error %d getting slice maximum\n", r); } printf("%d. min %f max %f\n", i, min, max); } miclose_volume(hvol); } } return (0); } minc-2.2.00/libsrc2/test/valid-test.c0000644000265600003100000000357312027132662014207 00000000000000#include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; int main(int argc, char **argv) { mihandle_t hvol; int r; double min, max; double orig_min, orig_max; while (--argc > 0) { r = miopen_volume(*++argv, MI2_OPEN_RDWR, &hvol); if (r < 0) { TESTRPT("can't open input", r); continue; } r = miget_volume_valid_min(hvol, &min); if (r < 0) { TESTRPT("error getting valid minimum", r); } r = miget_volume_valid_max(hvol, &max); if (r < 0) { TESTRPT("error getting valid maximum", r); } r = miget_volume_valid_range(hvol, &max, &min); if (r < 0) { TESTRPT("error getting valid range", r); } printf("min %f max %f\n", min, max); if (min > max) { TESTRPT("error - min exceeds max!", 0); } orig_min = min; orig_max = max; /* Try some arbitrary manipulations */ max = orig_max + 100; min = orig_min - 100; r = miset_volume_valid_range(hvol, max, min); if (r < 0) { TESTRPT("error setting new volume range", 0); } r = miget_volume_valid_min(hvol, &min); if (r != 0 || min != orig_min - 100) { TESTRPT("error changing volume minimum", 0); } r = miget_volume_valid_max(hvol, &max); if (max != orig_max + 100) { TESTRPT("error changing volume maximum", 0); } r = miset_volume_valid_range(hvol, orig_max, orig_min); if (r < 0) { TESTRPT("error restoring volume range", r); } miclose_volume(hvol); } return (error_cnt); } minc-2.2.00/libsrc2/test/vector_dimension-test.c0000644000265600003100000001146312027132662016454 00000000000000#include #include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; #define CZ 41 #define CY 410 #define CX 530 #define NDIMS 4 void create_test_file(void) { int r; midimhandle_t hdim[NDIMS]; mihandle_t hvol; unsigned char *buf = malloc(CZ*CX*CY*3); int i; long count[NDIMS]; long start[NDIMS]; r = micreate_dimension("zspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CZ, &hdim[0]); r = micreate_dimension("yspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CY, &hdim[1]); r = micreate_dimension("xspace", MI_DIMCLASS_SPATIAL, MI_DIMATTR_REGULARLY_SAMPLED, CX, &hdim[2]); r = micreate_dimension("vector_dimension", MI_DIMCLASS_RECORD, MI_DIMATTR_REGULARLY_SAMPLED, 3, &hdim[3]); micreate_volume("example_vector2.mnc", NDIMS, hdim, MI_TYPE_BYTE, MI_CLASS_INT, NULL, &hvol); micreate_volume_image(hvol); for (i = 0; i < CZ*CY*CX*3; i++) { buf[i] = (unsigned char) i; } start[0] = start[1] = start[2] = start[3] = 0; count[0] = CZ; count[1] = CY; count[2] = CX; count[3] = 3; miset_voxel_value_hyperslab(hvol, MI_TYPE_BYTE, start, count, buf); miclose_volume(hvol); } int main(int argc, char **argv) { mihandle_t vol; int r = 0; midimhandle_t dim[NDIMS]; unsigned int lengths[NDIMS]; midimhandle_t copy_dim[NDIMS]; unsigned long coords[NDIMS]; unsigned long count[NDIMS]; int i,j; unsigned char * Atmp; midimclass_t dimension_class; int ndims; Atmp = ( unsigned char *) malloc(CX * CY * CZ * sizeof(unsigned char)); create_test_file(); printf(" \n"); printf("Opening vector-dimension file!\n"); printf(" \n"); r = miopen_volume("example_vector2.mnc", MI2_OPEN_READ, &vol); if (r < 0) { TESTRPT("failed to open vector_dimension volume", r); } r = miget_volume_dimension_count(vol, MI_DIMCLASS_ANY, MI_DIMATTR_REGULARLY_SAMPLED, &ndims); if (r < 0) { TESTRPT("failed to get number of dimensions", r); } printf("Total number of dimensions : %d \n", ndims); r = miget_volume_dimensions(vol, MI_DIMCLASS_ANY, MI_DIMATTR_REGULARLY_SAMPLED, MI_DIMORDER_FILE, NDIMS, dim); if (r < 0) { TESTRPT("Could not get dimension handles from volume", r); } r = miget_dimension_sizes(dim, NDIMS, lengths); if (r < 0) { TESTRPT(" more trouble", r); } printf( "Dimension Size in file order : "); for(i=0; i < NDIMS; i++) { printf( " %d ", lengths[i]); } printf(" \n"); for( i=0; i < NDIMS; i++) { r = miget_dimension_class(dim[i],&dimension_class); if (r < 0) { TESTRPT("failed to get dimension class", r); } if (dimension_class == MI_DIMCLASS_RECORD) { printf("Dim class RECORD present check dim name for *vector_dimension*\n"); } } printf("Let's get the first 10 data values of each vector component (file order) \n"); coords[0]=coords[1]=coords[2]=0; count[0]=CZ; count[1]=CY; count[2]=CX; count[3]=1; printf(" FILE ORDER --> zspace, yspace, xspace, vector_dimension \n"); for (i=0; i < 3; i++) { printf("Vector Componenet %d \n", i+1); coords[3]=i; r = miget_voxel_value_hyperslab(vol, MI_TYPE_UBYTE, coords, count,Atmp); if (r < 0) { TESTRPT("Failed to operate hyperslab function", r); } for (j=0; j < 10; j++) { printf( " %u ", Atmp[j]); } printf(" \n"); } printf("APPARENT ORDER --> vector_dimension, zspace, yspace, xspace\n"); // Set the apparent dimension order copy_dim[0] = dim[3]; copy_dim[1] = dim[0]; copy_dim[2] = dim[1]; copy_dim[3] = dim[2]; r = miset_apparent_dimension_order(vol, NDIMS, copy_dim); if (r < 0) { TESTRPT("failed to set apparent order", r); } coords[1]=coords[2]=coords[3]=0; count[0]=1; //must always be one count[1]=CZ; count[2]=CY; count[3]=CZ; printf("APPARENT ORDER SET \n"); for (i=0; i < 3; i++) { printf("Vector Componenet %d \n", i+1); coords[0]=i; r = miget_voxel_value_hyperslab(vol, MI_TYPE_UBYTE, coords, count,Atmp); if (r < 0) { TESTRPT("Failed to operate hyperslab function", r); } for (j=0; j < 10; j++) { printf( " %u ", Atmp[j]); } printf(" \n"); } if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/volprops-test.c0000644000265600003100000000457412027132662014776 00000000000000#include #include "minc2.h" #define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ "Error reported on line #%d, %s: %d\n", \ __LINE__, msg, val)) static int error_cnt = 0; int main(int argc, char **argv) { mihandle_t vol; mivolumeprops_t props; int r; micompression_t compression_type; miboolean_t enable_flag; int zlib_level; int depth; int edge_lengths[MI2_MAX_VAR_DIMS]; int edge_count; int i; r = minew_volume_props(&props); if (r < 0) { TESTRPT("failed", r); } r = miset_props_multi_resolution(props, 1 , 2); if (r < 0) { TESTRPT("failed", r); } r = miget_props_multi_resolution(props, &enable_flag, &depth); if (r < 0) { TESTRPT("failed", r); } else { printf("Multiresolution enabled: %d depth: %d \n", enable_flag, depth); } r = miset_props_compression_type(props, MI_COMPRESS_NONE); if (r < 0) { TESTRPT("failed", r); } else { printf("Set compression type to %d\n", MI_COMPRESS_NONE); } r = miget_props_compression_type(props,&compression_type); if (r < 0 || compression_type != MI_COMPRESS_NONE) { TESTRPT("failed", r); } else { printf("Got compression type %d \n", compression_type); } r = miset_props_zlib_compression(props,4); if (r < 0) { TESTRPT("failed", r); } else { printf("Set zlib level to %d\n", 4); } r = miget_props_zlib_compression(props,&zlib_level); if (r < 0 || zlib_level != 4) { TESTRPT("failed", r); } else { printf("Got zlib level %d \n", zlib_level); } mifree_volume_props(props); while (--argc > 0) { r = miopen_volume(*++argv, MI2_OPEN_RDWR, &vol); if (r < 0) { TESTRPT("failed", r); } r = miget_volume_props(vol, &props); if (r < 0) { TESTRPT("failed", r); } r = miget_props_blocking(props, &edge_count, edge_lengths, MI2_MAX_VAR_DIMS); if (r < 0) { TESTRPT("failed", r); } printf("edge_count %d\n", edge_count); for (i = 0; i < edge_count; i++) { printf(" %d", edge_lengths[i]); } printf("\n"); mifree_volume_props(props); miclose_volume(vol); } if (error_cnt != 0) { fprintf(stderr, "%d error%s reported\n", error_cnt, (error_cnt == 1) ? "" : "s"); } else { fprintf(stderr, "No errors\n"); } return (error_cnt); } minc-2.2.00/libsrc2/test/testminctools.sh0000755000265600003100000000153712027132662015233 00000000000000#! /bin/sh # # Test minc tools on minc2 file. set -e ../../mincconvert ../../volume_io/Testing/t3_grid_0.mnc t3_grid_0_2.mnc -2 -clobber && echo "Converted file to MINC2.0 format." || exit 1 ../../mincinfo -minc_version -image_info t3_grid_0_2.mnc ../../mincmath -const 1 -mult t3_grid_0_2.mnc t32.mnc -clobber || exit 1 echo "Statistics on image" ../../mincstats -mean -std t32.mnc || exit 1 echo "Adding const 2 to all three channels." ../../mincmath -const 2 -add t32.mnc t32_added.mnc -clobber || exit 1 echo "Statistics on image with added constant" ../../mincstats -mean -std t32_added.mnc || exit 1 echo "Resampling file with t1.xfm transform" ../../mincresample -transform ../../volume_io/Testing/t1.xfm -tfm_input_sampling t32_added.mnc t32_transformed.mnc -clobber || exit 1 echo "Transformed file" ../../mincinfo t32_transformed.mnc exit 0 minc-2.2.00/m4/0000755000265600003100000000000012030114720010025 500000000000000minc-2.2.00/m4/libtool.m40000644000265600003100000077464712027132662011717 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 56 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl _LT_PROG_ECHO_BACKSLASH case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\[$]0 --fallback-echo"')dnl " lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` ;; esac _LT_OUTPUT_LIBTOOL_INIT ]) # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) cat >"$CONFIG_LT" <<_LTEOF #! $SHELL # Generated by $as_me. # Run this file to recreate a libtool stub with the current configuration. lt_cl_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2008 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. if test "$no_create" != yes; then lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) fi ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_XSI_SHELLFNS sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES # -------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(whole_archive_flag_spec, $1)='' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX # ----------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl AC_LINK_IFELSE(AC_LANG_PROGRAM,[ lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) $1 AC_DIVERT_POP ])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. m4_defun([_LT_PROG_ECHO_BACKSLASH], [_LT_SHELL_INIT([ # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac ECHO=${lt_ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF [$]* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(lt_ECHO) ]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that does not interpret backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [AC_CHECK_TOOL(AR, ar, false) test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1]) AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line __oline__ "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method == "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC*) # IBM XL 8.0 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' ;; linux* | k*bsd*-gnu) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE(int foo(void) {}, _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' ) LDFLAGS="$save_LDFLAGS" else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then _LT_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], [[If ld is used when linking, flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [fix_srcfile_path], [1], [Fix the shell variable $srcfile for the compiler]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_PROG_CXX # ------------ # Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ # compiler, we have our own version here. m4_defun([_LT_PROG_CXX], [ pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) AC_PROG_CXX if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_CXX dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_CXX], []) # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [AC_REQUIRE([_LT_PROG_CXX])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 will use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; xl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=echo else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ]) dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_PROG_F77 # ------------ # Since AC_PROG_F77 is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_F77], [ pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) AC_PROG_F77 if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_F77 dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_F77], []) # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_REQUIRE([_LT_PROG_F77])dnl AC_LANG_PUSH(Fortran 77) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${F77-"f77"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_PROG_FC # ----------- # Since AC_PROG_FC is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_FC], [ pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) AC_PROG_FC if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_FC dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_FC], []) # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_REQUIRE([_LT_PROG_FC])dnl AC_LANG_PUSH(Fortran) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${FC-"f95"} compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC="$lt_save_CC" ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC= CC=${RC-"windres"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC="$lt_save_CC" ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_XSI_SHELLFNS # --------------------- # Bourne and XSI compatible variants of some useful shell functions. m4_defun([_LT_PROG_XSI_SHELLFNS], [case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $[*] )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } dnl func_dirname_and_basename dnl A portable version of this function is already defined in general.m4sh dnl so there is no need for it here. # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[[^=]]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$[@]"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]+=\$[2]" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]=\$$[1]\$[2]" } _LT_EOF ;; esac ]) minc-2.2.00/m4/ltoptions.m40000644000265600003100000002724212027132662012264 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [0], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) minc-2.2.00/m4/ltsugar.m40000644000265600003100000001042412027132662011704 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) minc-2.2.00/m4/ltversion.m40000644000265600003100000000127712027132662012256 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # Generated from ltversion.in. # serial 3017 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.2.6b]) m4_define([LT_PACKAGE_REVISION], [1.3017]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.2.6b' macro_revision='1.3017' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) minc-2.2.00/m4/lt~obsolete.m40000644000265600003100000001311312027132662012573 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 4 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) minc-2.2.00/m4/mni_REQUIRE_LIB.m40000644000265600003100000000070612027132662012672 00000000000000dnl @synopsis mni_REQUIRE_LIB(LIBRARY,INCLUDES,BODY) dnl dnl @version $Id: mni_REQUIRE_LIB.m4,v 1.2 2009-11-26 04:37:29 vfonov Exp $ dnl @author Steve M. Robbins AC_DEFUN([mni_REQUIRE_LIB], [ AC_MSG_CHECKING([for library $1]) LIBS="-l$1 $LIBS" AC_TRY_LINK([$2],[$3],[mni_result=yes],[mni_result=no]) AC_MSG_RESULT([$mni_result]) if test "$mni_result" = "no"; then AC_MSG_ERROR([cannot find required library $1]) fi ]) minc-2.2.00/m4/smr_WITH_BUILD_PATH.m40000644000265600003100000000202612027132662013411 00000000000000dnl @synopsis smr_WITH_BUILD_PATH dnl dnl This macro adds a "--with-build-path" option to the configure script. dnl This configure option provides a convenient way to add "-I" options dnl to CPPFLAGS and "-L" options to LDFLAGS, at configure time. dnl dnl Invoking "./configure --with-build-path=DIR" results in dnl "-I DIR/include" being added to CPPFLAGS if DIR/include exists, dnl and "-L DIR/lib" being added to LDFLAGS if DIR/lib exists. dnl dnl Separate multiple directories using colons; e.g. dnl "--with-build-path=DIR1:DIR2:DIR3". dnl dnl @version $Id: smr_WITH_BUILD_PATH.m4,v 1.4 2009-11-26 04:37:30 vfonov Exp $ dnl @author Steve M. Robbins AC_DEFUN([smr_WITH_BUILD_PATH], [ AC_ARG_WITH([build-path], [ --with-build-path=DIR build using DIR/include and DIR/lib], [ for d in `echo $withval | tr : ' '`; do test -d $d || AC_MSG_ERROR([build path $d not found.]) test -d $d/include && CPPFLAGS="$CPPFLAGS -I$d/include" test -d $d/lib && LDFLAGS="$LDFLAGS -L$d/lib" done ]) ]) minc-2.2.00/progs/0000755000265600003100000000000012030114723010642 500000000000000minc-2.2.00/progs/coordinates/0000755000265600003100000000000012030114723013154 500000000000000minc-2.2.00/progs/coordinates/voxeltoworld.man10000644000265600003100000000156512027132662016441 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH VOXELTOWORLD 1 "$Date: 2004-05-20 21:52:07 $" "" "MINC User's Guide" .SH NAME voxeltoworld \- convert voxel coordinates to world coordinates worldtovoxel \- convert world coordinates to voxel coordinates .SH SYNOPSIS .B voxeltoworld filename v1 v2 v3 .B worldtovoxel filename x y z .SH DESCRIPTION Transform coordinates of a point between voxel and world coordinate systems. The voxel coordinate system is aligned with the sampling grid of the image volume. .SH OPTIONS .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES To get the start positions of all three spatial coordinate axes in world coordinates: .IP voxeltoworld file.mnc 0 0 0 .SH AUTHOR Peter Neelin .SH COPYRIGHT Copyright \(co 1993 by Peter Neelin minc-2.2.00/progs/coordinates/voxeltoworld.c0000644000265600003100000001061612027132662016024 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : voxeltoworld @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to convert voxel coordinates to world coordinates @METHOD : @GLOBALS : @CALLS : @CREATED : June 13, 1994 (Peter Neelin) @MODIFIED : * $Log: voxeltoworld.c,v $ * Revision 6.9 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.8 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.7 2006/05/19 00:35:58 bert * Add config.h to several files that might need it * * Revision 6.6 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.5 2004/04/27 15:38:47 bert * Added milog_init() * * Revision 6.4 2004/02/02 18:27:51 bert * Call ParseArgv() so that version information can be output * * Revision 6.3 2001/04/24 13:38:41 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.2 2001/04/17 18:40:15 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:16 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:08 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:07 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:38 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:32:23 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:35 neelin * Release of minc version 0.2 * * Revision 1.3 94/09/28 10:36:30 neelin * Pre-release * * Revision 1.2 94/09/26 10:05:15 neelin * Changed vx,vy,vz to v0, v1, v2. * * Revision 1.1 94/06/13 10:21:47 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #ifndef public # define public # define private static #endif /* Function to print to stderr */ void print_to_stderr(char *string) { (void) fprintf(stderr, "%s", string); return; } /* Argument table */ ArgvInfo argTable[] = { {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { Volume volume; volume_input_struct input_info; char *filename; double v0, v1, v2, wx, wy, wz; static char *dim_names[] = {ANY_SPATIAL_DIMENSION, ANY_SPATIAL_DIMENSION, ANY_SPATIAL_DIMENSION}; milog_init(argv[0]); /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || argc != 5) { (void) fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } filename = argv[1]; v0 = atof(argv[2]); v1 = atof(argv[3]); v2 = atof(argv[4]); /* Open the image file */ set_print_function(print_to_stderr); if (start_volume_input(filename, 3, dim_names, MI_ORIGINAL_TYPE, TRUE, 0.0, 0.0, TRUE, &volume, NULL, &input_info) != OK) { (void) fprintf(stderr, "Error opening file %s for input.\n", filename); exit(EXIT_FAILURE); } /* Convert the voxel to world coordinates */ convert_3D_voxel_to_world(volume, v0, v1, v2, &wx, &wy, &wz); /* Write out the result */ (void) printf("%.20g %.20g %.20g\n", wx, wy, wz); exit(EXIT_SUCCESS); } minc-2.2.00/progs/coordinates/worldtovoxel.c0000644000265600003100000001045212027132662016022 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : worldtovoxel @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to convert world coordinates to voxel coordinates @METHOD : @GLOBALS : @CALLS : @CREATED : June 13, 1994 (Peter Neelin) @MODIFIED : * $Log: worldtovoxel.c,v $ * Revision 6.8 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.7 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.6 2006/05/19 00:35:58 bert * Add config.h to several files that might need it * * Revision 6.5 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.4 2004/02/02 18:27:51 bert * Call ParseArgv() so that version information can be output * * Revision 6.3 2001/04/24 13:38:41 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.2 2001/04/17 18:40:16 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:17 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:08 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:07 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:38 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:32:23 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:36:36 neelin * Release of minc version 0.2 * * Revision 1.3 94/09/28 10:36:31 neelin * Pre-release * * Revision 1.2 94/09/26 10:05:26 neelin * Changed vx,vy,vz to v0, v1, v2. * * Revision 1.1 94/06/13 10:22:04 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #ifndef public # define public # define private static #endif /* Function to print to stderr */ void print_to_stderr(char *string) { (void) fprintf(stderr, "%s", string); return; } /* Argument table */ ArgvInfo argTable[] = { {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { Volume volume; volume_input_struct input_info; char *filename; double v0, v1, v2, wx, wy, wz; static char *dim_names[] = {ANY_SPATIAL_DIMENSION, ANY_SPATIAL_DIMENSION, ANY_SPATIAL_DIMENSION}; /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || argc != 5) { (void) fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } filename = argv[1]; wx = atof(argv[2]); wy = atof(argv[3]); wz = atof(argv[4]); /* Open the image file */ set_print_function(print_to_stderr); if (start_volume_input(filename, 3, dim_names, MI_ORIGINAL_TYPE, TRUE, 0.0, 0.0, TRUE, &volume, NULL, &input_info) != OK) { (void) fprintf(stderr, "Error opening file %s for input.\n", filename); exit(EXIT_FAILURE); } /* Convert the voxel to world coordinates */ convert_3D_world_to_voxel(volume, wx, wy, wz, &v0, &v1, &v2); /* Write out the result */ (void) printf("%.20g %.20g %.20g\n", v0, v1, v2); exit(EXIT_SUCCESS); } minc-2.2.00/progs/mincaverage/0000755000265600003100000000000012030114723013123 500000000000000minc-2.2.00/progs/mincaverage/mincaverage.man10000644000265600003100000001256612027132662016124 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincaverage/mincaverage.man1,v 6.3 2004-05-20 21:52:07 bert Exp $ .\" .TH MINCAVERAGE 1 "$Date: 2004-05-20 21:52:07 $" "" "MINC User's Guide" .SH NAME mincaverage - average minc files .SH SYNOPSIS .B mincaverage [] .mnc [.mnc...] .mnc .SH DESCRIPTION \fIMincaverage\fR averages minc files together. A range of optional behaviour is permitted as well: pre-normalizing volumes, creating a standard deviation volume, averaging over a specified dimension of the input files. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create a MINC 2.0 format output file. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-verbose\fR Print out progress information for each chunk of data copied (default). .TP \fB\-quiet\fR Do not print out progress information. .TP \fB\-debug\fR Print extra information (e.g. normalization factors). .TP \fB\-filelist\fR \fIfilename\fR Specify a file containing a list of input file names. If "-" is given, then file names are read from stdin. If this option is given, then there should be no input file names specified on the command line. Empty lines in the input file are ignored. .TP \fB\-max_buffer_size_in_kb\fR \fIbuffer-size\fR Specify the maximum size of the internal buffers (in kbytes). Default is 4096 kbytes. .SH Output type options These options control the storage precision and size of individual voxel values in the output file. .TP \fB-filetype\fR Don't do any type conversion (default). .TP \fB\-byte\fR Write out 8-bit integer values. .TP \fB\-short\fR Write out 16-bit integer values. .TP \fB-int\fR Write out 32-bit integer values. .TP \fB\-long\fR Superseded by -int. .TP \fB\-float\fR Write out single-precision floating point values. .TP \fB\-double\fR Write out double-precision floating point values. .P \fB\-signed\fR Write out values as signed integers (default for short and long). Ignored for floating point types. .TP \fB\-unsigned\fR Write out values as unsigned integers (default for byte). Ignored for floating point types. .TP \fB\-range\fR \fImin max\fR specifies the valid range of output voxel values in their integer representation. Default is the full range for the type and sign. This option is ignored for floating point values. For it to have any effect, you must specify a type. .SH Averaging options .TP \fB\-normalize\fR Normalize volumes to their global average before averaging them (based on the mean of voxels with value greater than 2 percent of full range above the minimum). .TP \fB\-nonormalize\fR Do not normalize volumes (default). .TP \fB\-sdfile\fR \fIsdfile.mnc\fR Specify the name of an output standard deviation file, to be calculated in addition the mean that is normally calculated. .TP \fB\-copy_header\fR Copy all of the additional header information from the first input file (default for one input file). .TP \fB\-nocopy_header\fR Do not copy additional header information (default for many input files). .TP \fB\-avgdim\fR \fIdimname\fR Specify the name of a dimension over which we should be averaging (or calculating standard deviation). If normalization is done, it still only applies to separate files only - no normalization is done within a file. .TP \fB\-binarize\fR Binarize the input volumes before calculating the average. The binarization is done by specifying a range of values that contribute 1 to the average. Normalization of the input is not permitted when performing binarization. .TP \fB\-binrange\fR \fImin max\fR Specify the range of values for binarization. .TP \fB\-binvalue\fR \fIvalue\fR Specify a single legal value (integer) for binarization. The range is set to be +/- 0.5 around this value to achieve an effective rounding of input values. .TP \fB\-weights\fR \fI\fR Specify a series of weights for averaging. The number of weighting values must match the number of input files and the values must be provided as a single argument with commas or spaces as separators. The sum of the weights must be non-zero. If weights are used with an averaging dimension, then only one input file can be specified. .TP \fB\-width_weighted\fR This option can only be used when averaging across a dimension (\fB-avgdim\fR option). It specifies that weighting should be done using the width variable that corresponds to the averaging dimension. For example, using \fB\-width_weighted\fR with \fB\-avgdim\fR time will use the time-width variable to weight the values. .SH Generic options for all commands: .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1995 by Peter Neelin minc-2.2.00/progs/mincaverage/mincaverage.c0000644000265600003100000010172112027132662015502 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincaverage @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to average minc files @METHOD : @GLOBALS : @CALLS : @CREATED : April 28, 1995 (Peter Neelin) @MODIFIED : * $Log: mincaverage.c,v $ * Revision 6.11 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.10 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.9 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.8 2005/08/26 21:07:16 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.7 2004/12/14 23:52:50 bert * Get rid of compilation warnings w/c99 * * Revision 6.6 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.5 2004/04/27 15:38:15 bert * Added -2 option * * Revision 6.4 2001/04/24 13:38:42 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.3 2001/04/17 18:40:17 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.2 2000/07/07 13:19:12 neelin * Added option -filelist to read file names from a file. This gets around * command-line length limits. * * Revision 6.1 1999/10/19 14:45:18 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:19 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:18 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:05:59 neelin * Release of minc version 0.4 * * Revision 3.2 1996/04/02 20:16:09 neelin * Added -width_weighted option. Allow -weights with -avgdim option. * * Revision 3.1 1995/11/20 14:24:47 neelin * Added -weights option. * * Revision 3.0 1995/05/15 19:32:44 neelin * Release of minc version 0.3 * * Revision 1.6 1995/05/05 18:08:17 neelin * Removed debugging line for sd calculation. * * Revision 1.5 1995/05/02 16:08:17 neelin * Added -check, -nocheck options. * * Revision 1.4 1995/04/27 14:05:38 neelin * Added binarization options. * * Revision 1.3 1995/04/27 12:48:42 neelin * Changed order of options. * * Revision 1.2 1995/04/27 11:50:35 neelin * Require either -norm or -nonorm on command line. * * Revision 1.1 1995/04/26 14:16:38 neelin * Initial revision * ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "read_file_names.h" /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define THRESH_FRACTION (1/50.0) #define WIDTH_SUFFIX "-width" #define DEFAULT_BOOLEAN -1 /* Double_Array structure */ typedef struct { int numvalues; double *values; } Double_Array; /* Structures for averaging and normalizing information */ typedef struct { int binarize; int need_sd; double binrange[2]; double *norm_factor; int averaging_over_dimension; int num_weights; double *weights; } Average_Data; typedef struct { int threshold_set; double threshold; double sum0, sum1; } Norm_Data; /* Function prototypes */ static void do_normalization(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void find_mincfile_range(int mincid, double *minimum, double *maximum); static void do_average(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void start_average(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void finish_average(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static int get_double_list(char *dst, char *key, char *nextarg); /* Argument variables */ static int clobber = FALSE; static int verbose = TRUE; static int debug = FALSE; static int check_dimensions = TRUE; #ifdef NO_DEFAULT_NORM static int normalize = -1; #else static int normalize = FALSE; #endif static char *sdfile = NULL; static nc_type datatype = MI_ORIGINAL_TYPE; static int is_signed = FALSE; static double valid_range[2] = {0.0, 0.0}; static int copy_all_header = DEFAULT_BOOLEAN; static char *averaging_dimension = NULL; static int max_buffer_size_in_kb = 4 * 1024; static int binarize = FALSE; static double binrange[2] = {DBL_MAX, -DBL_MAX}; static double binvalue = -DBL_MAX; static Double_Array weights = {0, NULL}; static int width_weighted = FALSE; static char *filelist = NULL; #if MINC2 static int minc2_format = FALSE; #endif /* MINC2 */ /* Argument table */ ArgvInfo argTable[] = { #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &minc2_format, "Produce a MINC 2.0 format output file"}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-no_clobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Synonym for -noclobber."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages (default)."}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out log messages."}, {"-debug", ARGV_CONSTANT, (char *) TRUE, (char *) &debug, "Print out debugging messages."}, {"-filelist", ARGV_STRING, (char *) 1, (char *) &filelist, "Specify the name of a file containing input file names (- for stdin)."}, {"-check_dimensions", ARGV_CONSTANT, (char *) TRUE, (char *) &check_dimensions, "Check that dimension info matches across files (default)."}, {"-nocheck_dimensions", ARGV_CONSTANT, (char *) FALSE, (char *) &check_dimensions, "Do not check dimension info."}, {"-max_buffer_size_in_kb", ARGV_INT, (char *) 1, (char *) &max_buffer_size_in_kb, "Specify the maximum size of the internal buffers (in kbytes)."}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Use data type of first file (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Write out byte data."}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Write out short integer data."}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Write out 32-bit integer data."}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int."}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Write out single-precision floating-point data."}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Write out double-precision floating-point data."}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Write signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Write unsigned integer data (default if type specified)."}, {"-range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data."}, {"-normalize", ARGV_CONSTANT, (char *) TRUE, (char *) &normalize, "Normalize data sets for mean intensity."}, {"-nonormalize", ARGV_CONSTANT, (char *) FALSE, (char *) &normalize, "Do not normalize data sets (default)."}, {"-sdfile", ARGV_STRING, (char *) 1, (char *) &sdfile, "Specify an output sd file (default=none)."}, {"-copy_header", ARGV_CONSTANT, (char *) TRUE, (char *) ©_all_header, "Copy all of the header from the first file (default for one file)."}, {"-nocopy_header", ARGV_CONSTANT, (char *) FALSE, (char *) ©_all_header, "Do not copy all of the header from the first file (default for many files))."}, {"-avgdim", ARGV_STRING, (char *) 1, (char *) &averaging_dimension, "Specify a dimension along which we wish to average."}, {"-binarize", ARGV_CONSTANT, (char *) TRUE, (char *) &binarize, "Binarize the volume by looking for values in a given range."}, {"-binrange", ARGV_FLOAT, (char *) 2, (char *) binrange, "Specify a range for binarization."}, {"-binvalue", ARGV_FLOAT, (char *) 1, (char *) &binvalue, "Specify a target value (+/- 0.5) for binarization."}, {"-weights", ARGV_FUNC, (char *) get_double_list, (char *) &weights, "Specify weights for averaging (\",,...\")."}, {"-width_weighted", ARGV_CONSTANT, (char *) TRUE, (char *) &width_weighted, "Weight by dimension widths when -avgdim is used."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char **infiles, *outfiles[2]; int nfiles, nout; char *arg_string; Norm_Data norm_data; Average_Data average_data; Loop_Options *loop_options; double *vol_mean, vol_total, nvols, global_mean, total_weight; int ifile, iweight; int weights_specified; int first_mincid, dimid, varid, dim[MAX_VAR_DIMS]; int ndims; long start, count; int old_ncopts; int strlength; char dimname[MAX_NC_NAME]; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) { (void) fprintf(stderr, "\nUsage: %s [options] [ ...] \n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } outfiles[0] = argv[argc-1]; outfiles[1] = sdfile; nout = ((sdfile == NULL) ? 1 : 2); first_mincid = MI_ERROR; /* Get the list of input files either from the command line or from a file, or report an error if both are specified */ nfiles = argc - 2; if (filelist == NULL) { infiles = &argv[1]; } else if (nfiles <= 0) { infiles = read_file_names(filelist, &nfiles); if (infiles == NULL) { (void) fprintf(stderr, "Error reading in file names from file \"%s\"\n", filelist); exit(EXIT_FAILURE); } } else { (void) fprintf(stderr, "Do not specify both -filelist and input file names\n"); exit(EXIT_FAILURE); } /* Make sure that we have something to process */ if (nfiles == 0) { (void) fprintf(stderr, "No input files specified\n"); exit(EXIT_FAILURE); } /* Set default value of copy_all_header */ if (copy_all_header == DEFAULT_BOOLEAN) { copy_all_header = (nfiles <= 1); } /* Are we averaging over a dimension? */ average_data.averaging_over_dimension = (averaging_dimension != NULL); /* Check for weights and width-weighting */ weights_specified = weights.numvalues > 0; if (weights_specified && width_weighted) { (void) fprintf(stderr, "%s: Please do not specify weights and width-weighting.\n", argv[0]); exit(EXIT_FAILURE); } /* Default is no weighting */ average_data.num_weights = 0; average_data.weights = NULL; /* Check for weights */ if (weights_specified) { if (averaging_dimension == NULL) { if (weights.numvalues != nfiles) { (void) fprintf(stderr, "%s: Number of weights does not match number of files.\n", argv[0]); exit(EXIT_FAILURE); } } else { if (nfiles > 1) { (void) fprintf(stderr, "%s: Only one input file allowed with -weights and -avgdim.\n", argv[0]); exit(EXIT_FAILURE); } /* Check that the dimension size matches the number of weights */ first_mincid = miopen(infiles[0], NC_NOWRITE); dimid = ncdimid(first_mincid, averaging_dimension); (void) ncdiminq(first_mincid, dimid, NULL, &count); if (weights.numvalues != count) { (void) fprintf(stderr, "%s: Number of weights does not match size of dimension.\n", argv[0]); } } /* Save the weights */ average_data.num_weights = weights.numvalues; average_data.weights = malloc(sizeof(*average_data.weights) * average_data.num_weights); for (iweight=0; iweight < average_data.num_weights; iweight++) { average_data.weights[iweight] = weights.values[iweight]; } free(weights.values); } /* Check for width weighting */ if (width_weighted) { /* Check for errors */ if (averaging_dimension == NULL) { (void) fprintf(stderr, "%s: Please specify -avgdim with -width_weighted.\n", argv[0]); exit(EXIT_FAILURE); } if (nfiles > 1) { (void) fprintf(stderr, "%s: Use -width_weighted with only one input file.\n", argv[0]); exit(EXIT_FAILURE); } /* Open the file */ first_mincid = miopen(infiles[0], NC_NOWRITE); /* Get the dimension id */ dimid = ncdimid(first_mincid, averaging_dimension); /* Look for the width variable */ strlength = MAX_NC_NAME - strlen(WIDTH_SUFFIX) - 1; (void) strncpy(dimname, averaging_dimension, strlength); dimname[strlength] = '\0'; (void) strcat(dimname, WIDTH_SUFFIX); old_ncopts = ncopts; ncopts = 0; varid = ncvarid(first_mincid, dimname); (void) ncvarinq(first_mincid, varid, NULL, NULL, &ndims, dim, NULL); ncopts = old_ncopts; if (varid != MI_ERROR) { /* Check that things match up */ if ((ndims != 1) || (dim[0] != dimid)) { (void) fprintf(stderr, "%s: Dimension width variable does not match avgdim.\n", argv[0]); } /* Get the size of the dimension */ (void) ncdiminq(first_mincid, dim[0], NULL, &count); average_data.num_weights = count; average_data.weights = malloc(sizeof(*average_data.weights) * average_data.num_weights); /* Read in the widths */ start = 0; (void) mivarget(first_mincid, varid, &start, &count, NC_DOUBLE, NULL, average_data.weights); } } /* If width_weighted */ /* Check that weights sum to non-zero. We don't need to normalize them, since a running sum is done in the averaging. */ if (average_data.num_weights > 0) { total_weight = 0.0; for (iweight=0; iweight < average_data.num_weights; iweight++) { total_weight += average_data.weights[iweight]; } if (total_weight == 0.0) { (void) fprintf(stderr, "%s: Weights sum to zero.\n", argv[0]); exit(EXIT_FAILURE); } } /* Check for binarization */ if (binarize) { if (normalize == TRUE) { (void) fprintf(stderr, "%s: Normalization and binarization cannot both be specified\n", argv[0]); exit(EXIT_FAILURE); } normalize = FALSE; if (binvalue != -DBL_MAX) { binrange[0] = binvalue - 0.5; binrange[1] = binvalue + 0.5; } if (binrange[0] > binrange[1]) { (void) fprintf(stderr, "%s: Please specify a binarization range with min less than max\n", argv[0]); exit(EXIT_FAILURE); } average_data.binrange[0] = binrange[0]; average_data.binrange[1] = binrange[1]; } average_data.binarize = binarize; /* Check for no specification of normalization */ #ifdef NO_DEFAULT_NORM if (normalize == -1) { (void) fprintf(stderr, "\n%s: %s\n\n%s\n%s\n%s\n%s\n%s\n\n", argv[0], "Please specify either -norm or -nonorm.", "The default setting for normalization is being changed from \"-norm\" to", "\"-nonorm\". To prevent undetected problems with data, this program will ", "not work unless one of these flags is explicitly given on the command-line", "(ie. no default is permitted). The new default will come into effect some", "time in the future." ); exit(EXIT_FAILURE); } #endif /* Do normalization if needed */ average_data.norm_factor = malloc(sizeof(*average_data.norm_factor) * nfiles); if (normalize) { vol_mean = malloc(sizeof(*vol_mean) * nfiles); loop_options = create_loop_options(); set_loop_verbose(loop_options, FALSE); #if MINC2 set_loop_v2format(loop_options, minc2_format); #endif /* MINC2 */ set_loop_accumulate(loop_options, TRUE, 0, NULL, NULL); set_loop_buffer_size(loop_options, (long) 1024 * max_buffer_size_in_kb); set_loop_check_dim_info(loop_options, check_dimensions); vol_total = 0.0; nvols = 0; if (verbose) { (void) fprintf(stderr, "Normalizing:"); (void) fflush(stderr); } for (ifile=0; ifile < nfiles; ifile++) { norm_data.threshold_set = FALSE; norm_data.sum0 = 0.0; norm_data.sum1 = 0.0; if (verbose) { (void) fprintf(stderr, "."); (void) fflush(stderr); } if (first_mincid != MI_ERROR) { set_loop_first_input_mincid(loop_options, first_mincid); first_mincid = MI_ERROR; } voxel_loop(1, &infiles[ifile], 0, NULL, NULL, loop_options, do_normalization, (void *) &norm_data); if (norm_data.sum0 > 0.0) { vol_mean[ifile] = norm_data.sum1 / norm_data.sum0; vol_total += vol_mean[ifile]; nvols++; } else { vol_mean[ifile] = 0.0; } if (debug) { (void) fprintf(stderr, "Volume %d mean = %.15g\n", ifile, vol_mean[ifile]); } } free_loop_options(loop_options); if (verbose) { (void) fprintf(stderr, "Done\n"); (void) fflush(stderr); } if (nvols > 0) global_mean = vol_total / nvols; else global_mean = 0.0; for (ifile=0; ifile < nfiles; ifile++) { if (vol_mean[ifile] > 0.0) average_data.norm_factor[ifile] = global_mean / vol_mean[ifile]; else average_data.norm_factor[ifile] = 0.0; if (debug) { (void) fprintf(stderr, "Volume %d norm factor = %.15g\n", ifile, average_data.norm_factor[ifile]); } } free(vol_mean); } else { for (ifile=0; ifile < nfiles; ifile++) { average_data.norm_factor[ifile] = 1.0; } } /* Do averaging */ average_data.need_sd = (sdfile != NULL); loop_options = create_loop_options(); if (first_mincid != MI_ERROR) { set_loop_first_input_mincid(loop_options, first_mincid); first_mincid = MI_ERROR; } set_loop_verbose(loop_options, verbose); set_loop_clobber(loop_options, clobber); set_loop_datatype(loop_options, datatype, is_signed, valid_range[0], valid_range[1]); set_loop_accumulate(loop_options, TRUE, 1, start_average, finish_average); set_loop_copy_all_header(loop_options, copy_all_header); set_loop_dimension(loop_options, averaging_dimension); set_loop_buffer_size(loop_options, (long) 1024 * max_buffer_size_in_kb); set_loop_check_dim_info(loop_options, check_dimensions); voxel_loop(nfiles, infiles, nout, outfiles, arg_string, loop_options, do_average, (void *) &average_data); free_loop_options(loop_options); /* Free stuff */ free(average_data.weights); free(average_data.norm_factor); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_normalization @INPUT : Standard for voxel_loop @OUTPUT : Standard for voxel_loop @RETURNS : (nothing) @DESCRIPTION: Routine to loop through an array of voxels and calculate normalization values. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_normalization(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Norm_Data *norm_data; long ivox; double value, minimum, maximum; /* Get pointer to window info */ norm_data = (Norm_Data *) caller_data; /* Check arguments */ if ((input_num_buffers != 1) || (output_num_buffers != 0)) { (void) fprintf(stderr, "Bad arguments to do_normalization!\n"); exit(EXIT_FAILURE); } /* Check to see if the threshold has been set */ if (!norm_data->threshold_set) { find_mincfile_range(get_info_current_mincid(loop_info), &minimum, &maximum); norm_data->threshold = minimum + (maximum - minimum) * THRESH_FRACTION; norm_data->threshold_set = TRUE; } /* Loop through the voxels */ for (ivox=0; ivox < num_voxels*input_vector_length; ivox++) { value = input_data[0][ivox]; if ((value != -DBL_MAX) && (value > norm_data->threshold)) { norm_data->sum0 += 1.0; norm_data->sum1 += value; } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : find_mincfile_range @INPUT : mincid - id of minc file @OUTPUT : minimum - minimum for file maximum - maximum for file @RETURNS : (nothing) @DESCRIPTION: Routine to find the min and max in a minc file @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void find_mincfile_range(int mincid, double *minimum, double *maximum) { int varid; char *varname; double sign, value; double *extreme; long index[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; int ndims, dim[MAX_VAR_DIMS]; int idim, imm; int old_ncopts; *minimum = 0.0; *maximum = 1.0; for (imm=0; imm < 2; imm++) { /* Set up for max or min */ if (imm == 0) { varname = MIimagemin; sign = -1.0; extreme = minimum; } else { varname = MIimagemax; sign = 1.0; extreme = maximum; } /* Get the variable id */ old_ncopts = ncopts; ncopts = 0; varid = ncvarid(mincid, varname); ncopts = old_ncopts; if (varid == MI_ERROR) continue; /* Get the dimension info */ (void) ncvarinq(mincid, varid, NULL, NULL, &ndims, dim, NULL); for (idim=0; idim < ndims; idim++) { (void) ncdiminq(mincid, dim[idim], NULL, &count[idim]); } if (ndims <= 0) { ndims = 1; count[0] = 1; } /* Loop through values, getting extrema */ (void) miset_coords(ndims, (long) 0, index); *extreme = sign * (-DBL_MAX); while (index[0] < count[0]) { (void) mivarget1(mincid, varid, index, NC_DOUBLE, NULL, &value); if ((value * sign) > (*extreme * sign)) { *extreme = value; } idim = ndims-1; index[idim]++; while ((index[idim] > count[idim]) && (idim > 0)) { idim--; index[idim]++; } } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_average @INPUT : Standard for voxel loop @OUTPUT : Standard for voxel loop @RETURNS : (nothing) @DESCRIPTION: Routine to loop through an array of voxels and perform averaging of across volumes. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_average(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Average_Data *average_data; long ivox; double value; int curfile, curindex; int num_out; double norm_factor, binmin, binmax, weight; int binarize; /* Get pointer to window info */ average_data = (Average_Data *) caller_data; /* Check arguments */ num_out = (average_data->need_sd ? 3 : 2); if ((input_num_buffers != 1) || (output_num_buffers != num_out) || (output_vector_length != input_vector_length)) { (void) fprintf(stderr, "Bad arguments to do_average!\n"); exit(EXIT_FAILURE); } /* Get the normalization factor and binarization range */ curfile = get_info_current_file(loop_info); curindex = get_info_current_index(loop_info); norm_factor = average_data->norm_factor[curfile]; if ((average_data->num_weights <= 0) || (average_data->weights == NULL)) { weight = 1.0; } else { if (average_data->averaging_over_dimension) { if (curindex >= average_data->num_weights) { (void) fprintf(stderr, "Internal error in index!\n"); exit(EXIT_FAILURE); } weight = average_data->weights[curindex]; } else { if (curfile >= average_data->num_weights) { (void) fprintf(stderr, "Internal error in file number!\n"); exit(EXIT_FAILURE); } weight = average_data->weights[curfile]; } } binarize = average_data->binarize; binmin = average_data->binrange[0]; binmax = average_data->binrange[1]; /* Loop through the voxels */ for (ivox=0; ivox < num_voxels*input_vector_length; ivox++) { value = input_data[0][ivox]; if (binarize) { value = ( ((value >= binmin) && (value <= binmax)) ? 1.0 : 0.0 ); } if (value != -DBL_MAX) { value *= norm_factor; output_data[0][ivox] += weight; output_data[1][ivox] += value * weight; if (average_data->need_sd) output_data[2][ivox] += value * value * weight; } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : start_average @INPUT : Standard for voxel loop @OUTPUT : Standard for voxel loop @RETURNS : (nothing) @DESCRIPTION: Start routine for averaging. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void start_average(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Average_Data *average_data; long ivox; int num_out; /* Get pointer to window info */ average_data = (Average_Data *) caller_data; /* Check arguments */ num_out = (average_data->need_sd ? 3 : 2); if (output_num_buffers != num_out) { (void) fprintf(stderr, "Bad arguments to start_average!\n"); exit(EXIT_FAILURE); } /* Loop through the voxels */ for (ivox=0; ivox < num_voxels*output_vector_length; ivox++) { output_data[0][ivox] = 0.0; output_data[1][ivox] = 0.0; if (average_data->need_sd) output_data[2][ivox] = 0.0; } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : finish_average @INPUT : Standard for voxel loop @OUTPUT : Standard for voxel loop @RETURNS : (nothing) @DESCRIPTION: Finish routine for averaging. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void finish_average(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Average_Data *average_data; long ivox; int num_out; double sum0, sum1, sum2, value; /* Get pointer to window info */ average_data = (Average_Data *) caller_data; /* Check arguments */ num_out = (average_data->need_sd ? 3 : 2); if (output_num_buffers != num_out) { (void) fprintf(stderr, "Bad arguments to finish_average!\n"); exit(EXIT_FAILURE); } /* Loop through the voxels */ for (ivox=0; ivox < num_voxels*output_vector_length; ivox++) { sum0 = output_data[0][ivox]; sum1 = output_data[1][ivox]; if (sum0 > 0.0) { output_data[0][ivox] = sum1 / sum0; if (average_data->need_sd) { sum2 = output_data[2][ivox]; if (sum0 > 1.0) { value = (sum2 - sum1*sum1 / sum0) / (sum0 - 1.0); if (value > 0.0) value = sqrt(value); else value = 0.0; output_data[1][ivox] = value; } else output_data[1][ivox] = 0.0; } } else { output_data[0][ivox] = 0.0; if (average_data->need_sd) output_data[1][ivox] = 0.0; } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_double_list @INPUT : dst - client data passed by ParseArgv key - matching key in argv nextarg - argument following key in argv @OUTPUT : (none) @RETURNS : TRUE since nextarg is used. @DESCRIPTION: Gets a list (array) of double values. @METHOD : @GLOBALS : @CALLS : @CREATED : March 8, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_double_list(char *dst, char *key, char *nextarg) { #define VECTOR_SEPARATOR ',' int num_elements; int num_alloc; double *double_list; double dvalue; char *cur, *end, *prev; Double_Array *double_array; /* Check for a following argument */ if (nextarg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get pointers to array variables */ double_array = (Double_Array *) dst; /* Set up pointers to end of string and first non-space character */ end = nextarg + strlen(nextarg); cur = nextarg; while (isspace(*cur)) cur++; num_elements = 0; num_alloc = 0; double_list = NULL; /* Loop through string looking for doubles */ while (cur!=end) { /* Get double */ prev = cur; dvalue = strtod(prev, &cur); if (cur == prev) { (void) fprintf(stderr, "expected vector of doubles for \"%s\", but got \"%s\"\n", key, nextarg); exit(EXIT_FAILURE); } /* Add the value to the list */ num_elements++; if (num_elements > num_alloc) { num_alloc += 20; if (double_list == NULL) { double_list = malloc(num_alloc * sizeof(*double_list)); } else { double_list = realloc(double_list, num_alloc * sizeof(*double_list)); } } double_list[num_elements-1] = dvalue; /* Skip any spaces */ while (isspace(*cur)) cur++; /* Skip an optional comma */ if (*cur == VECTOR_SEPARATOR) cur++; } /* Update the global variables */ double_array->numvalues = num_elements; if (double_array->values != NULL) { free(double_array->values); } double_array->values = double_list; return TRUE; } minc-2.2.00/progs/mincblob/0000755000265600003100000000000012030114723012427 500000000000000minc-2.2.00/progs/mincblob/mincblob.man10000644000265600003100000000574412030075003014721 00000000000000.\" Copyright 2001 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .TH MINCBLOB 1 "$Date: 2004-05-20 21:52:09 $" "" "MINC User's Guide" .SH NAME mincblob - calculate blobs from minc deformation grids .SH SYNOPSIS .B mincblob [] .mnc .SH DESCRIPTION \fImincblob\fR will calculate simple statistical metrics of a minc deformation grid file related to local volume change. The input deformation grid files are typically produced by minctracc. There are currently 4 deformation grid metrics to choose from: trace, determinant, translation and magnitude. The first two relate to different estimates of local volume change the third is a measure of how consistent movement is in a direction but without a local change in volume. The last calcuates the magnitude of the local deformation vector. These metrics are all calculated with respect to a vectors immediate neighbours. No smoothing of the field is performed as part of this calculation so if a smooth results is desired input grid files should be first smoothed or blurred. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-verbose\fR Print out extra information (more than the default). \fB\-trace\fR Compute the areas within the deformation field that equate to volume increase or decrease (+ve or -ve dilation) Dilation is defined as the trace of the deformation field Thus it should range between -1..1 with -1 being compression and 1 being dilation. This measure while fast is essentially a sum of partial derivatives in all three directions. .TP \fB\-determinant\fR This computes the same metric as -trace but with greater accuracy as the local Jacobian matrix is first estimated. The first order determinant of the Jacobian is then returned. .TP \fB\-translation\fR Compute the areas within the deformation field that equate to translation Translation is defined as: trans = arccos( A.B / |A|.|B| ) * e^- (|A|-|B|) Thus it should range between 0..1 with 1 being "translation". .TP \fB\-magnitude\fR Compute the magnitude of the local deformation vector. . .SH Generic options for all commands: .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Andrew Janke .SH COPYRIGHTS .P Program: Copyright \(co 2000 by Andrew Janke .P Man page: Copyright \(co 2001 by Peter Neelin minc-2.2.00/progs/mincblob/mincblob.c0000644000265600003100000004102612030075003014300 00000000000000/* mincblob.c */ /* */ /* Andrew Janke - a.janke@gmail.com */ /* Center for Magnetic Resonance */ /* University of Queensland */ /* */ /* Copyright Andrew Janke, The University of Queensland. */ /* Permission to use, copy, modify, and distribute this software and its */ /* documentation for any purpose and without fee is hereby granted, */ /* provided that the above copyright notice appear in all copies. The */ /* author and the University of Queensland make no representations about the */ /* suitability of this software for any purpose. It is provided "as is" */ /* without express or implied warranty. */ /* */ /* The bloberiser */ /* */ /* Mon Aug 21 16:18:36 EST 2000 - Original version */ /* Wed Nov 1 17:47:35 EST 2000 - rewrote translation option (new equation) */ /* Thu Feb 7 23:42:40 EST 2002 - complete rewrite to use volume_io */ /* Mon May 6 21:07:18 EDT 2002 - added -determinant option (jacobian) */ /* TRACE */ /* Compute the areas within the deformation field that equate to volume */ /* increase or decrease (+ve or -ve dilation) */ /* Dilation is defined as the trace of the deformation field */ /* Thus it should range between -1..1 with -1 being compression and */ /* 1 being dilation. */ /* TRANSLATION */ /* Compute the areas within the deformation field that equate to translation */ /* Translation is defined as: trans = arccos( A.B / |A|.|B| ) * e^- (|A|-|B|) */ /* Thus it should range between 0..1 with 1 being "translation". */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include typedef enum { NO_OP, TRACE, DETERMINANT, TRANSLATION, MAGNITUDE } op; /* function prototypes */ double fdiv(double num, double denom); double farccos(double a0, double b0, double c0, double a1, double b1, double c1); double cindex(double a0, double b0, double c0, double a1, double b1, double c1); double feuc(double a, double b, double c); void clear_borders(Volume v, int sizes[3]); void fill_slice0(Volume v, Real value, int v0, int v1_size, int v2_size); void fill_slice1(Volume v, Real value, int v0_size, int v1, int v2_size); void fill_slice2(Volume v, Real value, int v0_size, int v1_size, int v2); void print_version_info(void); /* argument variables */ static int verbose = FALSE; static int clobber = FALSE; static op operation = NO_OP; /* argument table */ static ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "General options:"}, {"-version", ARGV_FUNC, (char *)print_version_info, (char *)NULL, "print version info and exit"}, {"-verbose", ARGV_CONSTANT, (char *)TRUE, (char *)&verbose, "print out extra information"}, {"-clobber", ARGV_CONSTANT, (char *)TRUE, (char *)&clobber, "clobber existing files"}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nOperations:"}, {"-trace", ARGV_CONSTANT, (char *)TRACE, (char *)&operation, "compute the trace (approximate growth and shrinkage) -- FAST"}, {"-determinant", ARGV_CONSTANT, (char *)DETERMINANT, (char *)&operation, "compute the determinant (exact growth and shrinkage) -- SLOW"}, {"-translation", ARGV_CONSTANT, (char *)TRANSLATION, (char *)&operation, "compute translation (structure displacement)"}, {"-magnitude", ARGV_CONSTANT, (char *)MAGNITUDE, (char *)&operation, "compute the magnitude of the displacement vector"}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char **argv) { char *arg_string; char *infile; char *outfile; Volume in_vol; Volume out_vol; nc_type datatype; BOOLEAN signed_flag; Real steps[MAX_VAR_DIMS]; Real starts[MAX_VAR_DIMS]; int sizes[MAX_VAR_DIMS]; double out_real_max, out_real_min; char *in_axis_order[4] = { MIvector_dimension, MIzspace, MIyspace, MIxspace }; char *out_axis_order[3] = { MIzspace, MIyspace, MIxspace }; int x, y, z; double value; progress_struct progress; /* Jacobian matrix */ Real J[3][3]; /* Save list of arguments as strings */ arg_string = time_stamp(argc, argv); /* Check arguments */ if(ParseArgv(&argc, argv, argTable, 0) || (argc != 3)){ fprintf(stderr, "\nUsage: %s [options] \n", argv[0]); fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* check for an operation */ if(operation == NO_OP){ fprintf(stderr, "%s: You need to specify an operation!\n\n", argv[0]); exit(EXIT_FAILURE); } /* check for the infile and outfile */ if(access(infile, F_OK) != 0){ fprintf(stderr, "%s: Couldn't find %s\n\n", argv[0], infile); exit(EXIT_FAILURE); } if(access(outfile, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists! (use -clobber to overwrite)\n\n", argv[0], outfile); exit(EXIT_FAILURE); } /* read in the input volume and a few other things.... */ if(input_volume(infile, 4, in_axis_order, NC_UNSPECIFIED, TRUE, 0.0, 0.0, TRUE, &in_vol, NULL) != 0){ fprintf(stderr, "%s: Error reading input volume (%s)\n\n", argv[0], infile); exit(EXIT_FAILURE); } datatype = get_volume_nc_data_type(in_vol, &signed_flag); get_volume_sizes(in_vol, sizes); get_volume_starts(in_vol, starts); get_volume_separations(in_vol, steps); switch (operation){ default: case NO_OP: fprintf(stderr, "%s: GNARKLE! this shouldn't happen!\n\n", argv[0]); exit(EXIT_FAILURE); break; case TRACE: case DETERMINANT: out_real_min = -1.0; out_real_max = 1.0; break; case MAGNITUDE: case TRANSLATION: out_real_min = 0.0; out_real_max = 1.0; break; } /* set up the output volume */ out_vol = create_volume(3, out_axis_order, NC_DOUBLE, TRUE, 0.0, 0.0); set_volume_sizes(out_vol, &sizes[1]); set_volume_starts(out_vol, &starts[1]); set_volume_separations(out_vol, &steps[1]); alloc_volume_data(out_vol); /* set the surrounding voxels to 0 */ clear_borders(out_vol, &sizes[1]); /* start to do some stuff */ initialize_progress_report(&progress, FALSE, sizes[2] - 2, "Blobberising"); for(z = 1; z < sizes[1] - 1; z++){ for(y = 1; y < sizes[2] - 1; y++){ for(x = 1; x < sizes[3] - 1; x++){ switch (operation){ default: case NO_OP: fprintf(stderr, "%s: GNARKLE! this shouldn't happen!\n\n", argv[0]); exit(EXIT_FAILURE); break; case TRACE: value = ((get_volume_real_value(in_vol, 0, z, y, x + 1, 0) - get_volume_real_value(in_vol, 0, z, y, x - 1, 0)) / (steps[3] * 2)) + ((get_volume_real_value(in_vol, 1, z, y + 1, x, 0) - get_volume_real_value(in_vol, 1, z, y - 1, x, 0)) / (steps[2] * 2)) + ((get_volume_real_value(in_vol, 2, z + 1, y, x, 0) - get_volume_real_value(in_vol, 2, z - 1, y, x, 0)) / (steps[1] * 2)); break; case DETERMINANT: /* compute the Jacobian matrix */ J[0][0] = 1 + ((get_volume_real_value(in_vol, 0, z, y, x + 1, 0) - get_volume_real_value(in_vol, 0, z, y, x - 1, 0)) / (steps[3] * 2)); J[0][1] = (get_volume_real_value(in_vol, 0, z, y + 1, x, 0) - get_volume_real_value(in_vol, 0, z, y - 1, x, 0)) / (steps[2] * 2); J[0][2] = (get_volume_real_value(in_vol, 0, z + 1, y, x, 0) - get_volume_real_value(in_vol, 0, z - 1, y, x, 0)) / (steps[1] * 2); J[1][0] = (get_volume_real_value(in_vol, 1, z, y, x + 1, 0) - get_volume_real_value(in_vol, 1, z, y, x - 1, 0)) / (steps[3] * 2); J[1][1] = 1 + ((get_volume_real_value(in_vol, 1, z, y + 1, x, 0) - get_volume_real_value(in_vol, 1, z, y - 1, x, 0)) / (steps[2] * 2)); J[1][2] = (get_volume_real_value(in_vol, 1, z + 1, y, x, 0) - get_volume_real_value(in_vol, 1, z - 1, y, x, 0)) / (steps[1] * 2); J[2][0] = (get_volume_real_value(in_vol, 2, z, y, x + 1, 0) - get_volume_real_value(in_vol, 2, z, y, x - 1, 0)) / (steps[3] * 2); J[2][1] = (get_volume_real_value(in_vol, 2, z, y + 1, x, 0) - get_volume_real_value(in_vol, 2, z, y - 1, x, 0)) / (steps[2] * 2); J[2][2] = 1 + ((get_volume_real_value(in_vol, 2, z + 1, y, x, 0) - get_volume_real_value(in_vol, 2, z - 1, y, x, 0)) / (steps[1] * 2)); value = (J[0][0] * ((J[1][1] * J[2][2]) - (J[1][2] * J[2][1])) - J[0][1] * ((J[1][0] * J[2][2]) - (J[1][2] * J[2][0])) + J[0][2] * ((J[1][0] * J[2][1]) - (J[1][1] * J[2][0])) ) - 1; break; case TRANSLATION: value = ( /* x direction */ cindex(get_volume_real_value(in_vol, 0, z, y, x, 0), get_volume_real_value(in_vol, 1, z, y, x, 0), get_volume_real_value(in_vol, 2, z, y, x, 0), get_volume_real_value(in_vol, 0, z, y, x - 1, 0), get_volume_real_value(in_vol, 1, z, y, x - 1, 0), get_volume_real_value(in_vol, 2, z, y, x - 1, 0)) + cindex(get_volume_real_value(in_vol, 0, z, y, x, 0), get_volume_real_value(in_vol, 1, z, y, x, 0), get_volume_real_value(in_vol, 2, z, y, x, 0), get_volume_real_value(in_vol, 0, z, y, x + 1, 0), get_volume_real_value(in_vol, 1, z, y, x + 1, 0), get_volume_real_value(in_vol, 2, z, y, x + 1, 0)) + /* y direction */ cindex(get_volume_real_value(in_vol, 0, z, y, x, 0), get_volume_real_value(in_vol, 1, z, y, x, 0), get_volume_real_value(in_vol, 2, z, y, x, 0), get_volume_real_value(in_vol, 0, z, y - 1, x, 0), get_volume_real_value(in_vol, 1, z, y - 1, x, 0), get_volume_real_value(in_vol, 2, z, y - 1, x, 0)) + cindex(get_volume_real_value(in_vol, 0, z, y, x, 0), get_volume_real_value(in_vol, 1, z, y, x, 0), get_volume_real_value(in_vol, 2, z, y, x, 0), get_volume_real_value(in_vol, 0, z, y + 1, x, 0), get_volume_real_value(in_vol, 1, z, y + 1, x, 0), get_volume_real_value(in_vol, 2, z, y + 1, x, 0)) + /* z direction */ cindex(get_volume_real_value(in_vol, 0, z, y, x, 0), get_volume_real_value(in_vol, 1, z, y, x, 0), get_volume_real_value(in_vol, 2, z, y, x, 0), get_volume_real_value(in_vol, 0, z - 1, y, x, 0), get_volume_real_value(in_vol, 1, z - 1, y, x, 0), get_volume_real_value(in_vol, 2, z - 1, y, x, 0)) + cindex(get_volume_real_value(in_vol, 0, z, y, x, 0), get_volume_real_value(in_vol, 1, z, y, x, 0), get_volume_real_value(in_vol, 2, z, y, x, 0), get_volume_real_value(in_vol, 0, z + 1, y, x, 0), get_volume_real_value(in_vol, 1, z + 1, y, x, 0), get_volume_real_value(in_vol, 2, z + 1, y, x, 0)) ) / 6; break; case MAGNITUDE: value = sqrt((get_volume_real_value(in_vol, 0, z, y, x, 0) * get_volume_real_value(in_vol, 0, z, y, x, 0)) + (get_volume_real_value(in_vol, 1, z, y, x, 0) * get_volume_real_value(in_vol, 1, z, y, x, 0)) + (get_volume_real_value(in_vol, 2, z, y, x, 0) * get_volume_real_value(in_vol, 2, z, y, x, 0))); break; } set_volume_real_value(out_vol, z, y, x, 0, 0, value); /* check the min and max */ if(value < out_real_min){ out_real_min = value; } else if(value > out_real_max){ out_real_max = value; } } } update_progress_report(&progress, z + 1); } terminate_progress_report(&progress); if(verbose){ fprintf(stdout, "%s: Found output range of [%g:%g]\n", argv[0], out_real_min, out_real_max); } set_volume_real_range(out_vol, out_real_min, out_real_max); output_volume(outfile, datatype, signed_flag, 0.0, 0.0, out_vol, arg_string, NULL); return (EXIT_SUCCESS); } double fdiv(double num, double denom) { if(fabs(denom) < 0.0005){ return 0.0; } else { return num / denom; } } double feuc(double a, double b, double c) { return sqrt((a * a) + (b * b) + (c * c)); } double farccos(double a0, double b0, double c0, double a1, double b1, double c1) { return acos(fdiv((a0 * a1) + (b0 * b1) + (c0 * c1), feuc(a0, b0, c0) * feuc(a1, b1, c1))); } double cindex(double a0, double b0, double c0, double a1, double b1, double c1) { return (1.0 - farccos(a0, b0, c0, a1, b1, c1)) * exp(-1.0 * (fabs(feuc(a0, b0, c0) - feuc(a1, b1, c1)))); } /* steve's super-dooper padding function(s) */ void clear_borders(Volume v, int sizes[3]) { fill_slice0(v, 0, 0, sizes[1], sizes[2]); fill_slice0(v, 0, sizes[0] - 1, sizes[1], sizes[2]); fill_slice1(v, 0, sizes[0], 0, sizes[2]); fill_slice1(v, 0, sizes[0], sizes[1] - 1, sizes[2]); fill_slice2(v, 0, sizes[0], sizes[1], 0); fill_slice2(v, 0, sizes[0], sizes[1], sizes[2] - 1); } void fill_slice0(Volume v, Real value, int v0, int v1_size, int v2_size) { int v1, v2; for(v1 = 0; v1 < v1_size; ++v1){ for(v2 = 0; v2 < v2_size; ++v2){ set_volume_real_value(v, v0, v1, v2, 0, 0, value); } } } void fill_slice1(Volume v, Real value, int v0_size, int v1, int v2_size) { int v0, v2; for(v0 = 0; v0 < v0_size; ++v0){ for(v2 = 0; v2 < v2_size; ++v2){ set_volume_real_value(v, v0, v1, v2, 0, 0, value); } } } void fill_slice2(Volume v, Real value, int v0_size, int v1_size, int v2) { int v0, v1; for(v0 = 0; v0 < v0_size; ++v0){ for(v1 = 0; v1 < v1_size; ++v1){ set_volume_real_value(v, v0, v1, v2, 0, 0, value); } } } void print_version_info(void) { fprintf(stdout, "%s version %s\n", PACKAGE_STRING, PACKAGE_VERSION); fprintf(stdout, "Comments to %s\n", PACKAGE_BUGREPORT); fprintf(stdout, "\n"); exit(EXIT_SUCCESS); } minc-2.2.00/progs/minccalc/0000755000265600003100000000000012030114723012413 500000000000000minc-2.2.00/progs/minccalc/errx.h0000644000265600003100000000064012027132662013474 00000000000000/* Just in case you don't have errx, but you have gcc */ #if !defined(__OpenBSD__) && defined(__GNUC__) # define errx(exitcode, fmt , args) \ do { fprintf(stderr, "imgcalc: " fmt "\n", ## args ); exit(1); } while(0) # define err(exitcode, fmt , args) \ do { fprintf(stderr, "imgcalc: " fmt , ## args ); \ fprintf(stderr, ": %s\n", strerror(errno)); exit(1); } while(0) #else # include #endif minc-2.2.00/progs/minccalc/node.h0000644000265600003100000000530112027132662013440 00000000000000#include "errx.h" struct node; struct scalar; struct vector; struct sym; typedef int ident_t; typedef struct node *node_t; typedef struct scalar *scalar_t; typedef struct vector *vector_t; typedef struct sym *sym_t; #define SCALAR_ROUND(s) (floor(s + 0.5)) struct scalar { int width; double *vals; int refcnt; }; struct vector { int len; scalar_t *el; int maxlen; int refcnt; }; enum nodetype { NODETYPE_ADD, NODETYPE_SUB, NODETYPE_MUL, NODETYPE_DIV, NODETYPE_POW, NODETYPE_INDEX, NODETYPE_SUM, NODETYPE_PROD, NODETYPE_AVG, NODETYPE_LEN, NODETYPE_MAX, NODETYPE_MIN, NODETYPE_IMAX, NODETYPE_IMIN, NODETYPE_IDENT, NODETYPE_REAL, NODETYPE_LET, NODETYPE_VEC1, NODETYPE_VEC2, NODETYPE_GEN, NODETYPE_RANGE, NODETYPE_LT, NODETYPE_LE, NODETYPE_GT, NODETYPE_GE, NODETYPE_EQ, NODETYPE_NE, NODETYPE_NOT, NODETYPE_AND, NODETYPE_OR, NODETYPE_ISNAN, NODETYPE_SQRT, NODETYPE_ABS, NODETYPE_EXP, NODETYPE_LOG, NODETYPE_SIN, NODETYPE_COS, NODETYPE_TAN, NODETYPE_ASIN, NODETYPE_ACOS, NODETYPE_ATAN, NODETYPE_CLAMP, NODETYPE_SEGMENT, NODETYPE_EXPRLIST, NODETYPE_ASSIGN, NODETYPE_IFELSE, NODETYPE_FOR }; #define RANGE_EXACT_UPPER 1 #define RANGE_EXACT_LOWER 2 #define ALLARGS_SCALAR 4 #define NODE_IS_SCALAR 8 struct node { enum nodetype type; node_t expr[3]; ident_t ident; int flags; double real; int pos; int numargs; }; ident_t new_ident(const char *); const char *ident_str(ident_t); int ident_is_scalar(ident_t); ident_t ident_lookup(char *string); node_t new_node(int, int); node_t new_scalar_node(int); node_t new_vector_node(int); const char * node_name(node_t); int node_is_scalar(node_t); node_t optimize(node_t); vector_t new_vector(void); void vector_append(vector_t, scalar_t); void vector_free(vector_t); void vector_incr_ref(vector_t); scalar_t new_scalar(int); void scalar_free(scalar_t); void scalar_incr_ref(scalar_t); sym_t sym_enter_scope(sym_t sym); void sym_leave_scope(sym_t sym); void sym_declare_ident(ident_t id, sym_t sym); void sym_set_scalar(int, int *, scalar_t, ident_t, sym_t); void sym_set_vector(int, int *, vector_t, ident_t, sym_t); scalar_t sym_lookup_scalar(ident_t id, sym_t sym); vector_t sym_lookup_vector(ident_t id, sym_t sym); void lex_init(const char *); void lex_finalize(void); scalar_t eval_scalar(int, int *, node_t, sym_t); void show_error(int, const char *); int yyparse(void); int yylex(void); extern node_t root; minc-2.2.00/progs/minccalc/gram.h0000644000265600003100000000666312030102322013435 00000000000000 /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NAN = 258, IN = 259, TO = 260, IDENT = 261, REAL = 262, AVG = 263, PROD = 264, SUM = 265, LET = 266, NEG = 267, LEN = 268, MAX = 269, MIN = 270, IMAX = 271, IMIN = 272, ISNAN = 273, SQRT = 274, ABS = 275, EXP = 276, LOG = 277, SIN = 278, COS = 279, TAN = 280, ASIN = 281, ACOS = 282, ATAN = 283, CLAMP = 284, SEGMENT = 285, LT = 286, LE = 287, GT = 288, GE = 289, EQ = 290, NE = 291, NOT = 292, AND = 293, OR = 294, IF = 295, ELSE = 296, FOR = 297 }; #endif /* Tokens. */ #define NAN 258 #define IN 259 #define TO 260 #define IDENT 261 #define REAL 262 #define AVG 263 #define PROD 264 #define SUM 265 #define LET 266 #define NEG 267 #define LEN 268 #define MAX 269 #define MIN 270 #define IMAX 271 #define IMIN 272 #define ISNAN 273 #define SQRT 274 #define ABS 275 #define EXP 276 #define LOG 277 #define SIN 278 #define COS 279 #define TAN 280 #define ASIN 281 #define ACOS 282 #define ATAN 283 #define CLAMP 284 #define SEGMENT 285 #define LT 286 #define LE 287 #define GT 288 #define GE 289 #define EQ 290 #define NE 291 #define NOT 292 #define AND 293 #define OR 294 #define IF 295 #define ELSE 296 #define FOR 297 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 1676 of yacc.c */ #line 15 "gram.y" int pos; node_t node; double real; ident_t ident; /* Line 1676 of yacc.c */ #line 145 "progs/minccalc/gram.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; minc-2.2.00/progs/minccalc/minccalc.man10000644000265600003100000003123212027132662014673 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 2000 Andrew Janke .TH MINCCALC 1 "$Date: 2008-01-11 04:24:16 $" "" "MINC User's Guide" .SH NAME minccalc - perform complex math operations on minc files .SH SYNOPSIS .B mincalc [] .mnc [.mnc...] .mnc .SH DESCRIPTION \fIMinccalc\fR will perform complex, voxel-by-voxel math operations, on one or more minc files of the same shape and having the same coordinate sampling, producing a single output file. The operations to be performed are input using the \fB\-expression\fR argument (see \fBEXPRESSIONS\fR). By default, the output file is the last non-option argument. However, if the \fB-outfile\fR option is used, then all non-option arguments are considered input files and the output file names come from the \fB-outfile\fR options, of which there can be more than one. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .TP \fB\-2\fR Create MINC 2.0 format output files. .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-no_clobber\fR Synonym for -noclobber. .TP \fB\-verbose\fR Print out progress information for each chunk of data copied (default). .TP \fB\-quiet\fR Do not print out progress information. .TP \fB\-debug\fR Print out debugging information. .TP \fB\-copy_header\fR Copy all of the header information from the first input file (default for one input file). .TP \fB\-nocopy_header\fR Do not copy all of the header from the first input file; copy only coordinate information (default for more than one input file). .TP \fB\-filetype\fR Create an output file with the same type as the first input file (default). .TP \fB\-byte\fR Store output voxels in 8-bit integer format. .TP \fB\-short\fR Store output voxels in 16-bit integer format. .TP \fB\-int\fR Store output voxels in 32-bit integer format. .TP \fB\-long\fR Superseded by \fB\-int\fR. .TP \fB-float\fR Store output voxels in 32-bit floating point format. .TP \fB-double\fR Store output voxels in 64-bit floating point format. .TP \fB\-signed\fR Use signed, two's complement integer format. Applies only if the output voxel type is specified to be an integer type (one of \fB\-byte\fR, \fB\-short\fR, \fB\-int\fR or \fB-long\fR). .TP \fB\-unsigned\fR Use unsigned integer format. Applies only if the output voxel type is specified to be an integer type (one of \fB\-byte\fR, \fB\-short\fR, \fB\-int\fR or \fB-long\fR). .TP \fB\-range\fR \fImin max\fR Restrict the valid range of integer data. Applies only if one of the \fB-byte\fR, \fB-short\fR, \fB-int\fR or \fB\-long\fR options is specified. .TP \fB\-max_buffer_size_in_kb\fR \fIsize\fR Specify the maximum size of the internal buffers (in kbytes). Default is 4096 (4MB). .TP \fB\-dimension\fR\ \fIdimname\fR Specify a dimension along which we wish to perform a cumulative operation. .TP \fB\-check_dimensions\fR Check that all input files have matching sampling in world dimensions (default). .TP \fB\-nocheck_dimensions\fR Ignore any differences in world dimensions sampling for input files. .TP \fB\-propagate_nan\fR For cumulative vector operations (\fBsum\fR, \fBprod\fR and \fBavg\fR), invalid data (Not-A-Number or NaN) in any element of the vector will produce invalid data in the result (default). .TP \fB\-ignore_nan\fR For cumulative vector operations, invalid data (NaN) in the vector is ignored, ie. treated as though it is not present. .TP \fB\-nan\fR When an illegal operation is attempted at a voxel (such as divide by zero), the result is invalid data (NaN) (default). Having no valid input data for a cumulative operation is also considered an illegal operation when \fB-ignore_nan\fR is used. .TP \fB\-zero\fR When an illegal operation is attempted at a voxel (such as divide by zero), the result is value zero. .TP \fB\-illegal_value\fR\ \fIvalue\fR When an illegal operation is attempted at a voxel (such as divide by zero), the result is the value specified by this option. .TP \fB\-expression\fR \fIstring\fR Specify the expression to evaluate at each voxel (see EXPRESSIONS). .TP \fB\-expfile\fR \fIfilename\fR Specify a file containing an expression to evaluate at each voxel (see EXPRESSIONS). If filename ``-'' is given, then the expression is read from stdin. The only difference from command-line expressions is that comments can be given in the file. A comment line is specified by placing a ``#'' as the first non-whitespace character of the line. Minccalc scripts can be created by setting the first line to #! /usr/local/mni/bin/minccalc -expfile .TP \fB\-outfile\fR \fIsymbol output-file\fR Specify that output should be written to the specified file, taking values from the symbol which should be created in the expression (see the \fBEXAMPLES\fR section). If this option is given, then all non-option arguments are taken as input files. This option can be used multiple times for multiple output files. .TP \fB\-eval_width\fR \fIvalue\fR Specify the number of voxels to process in parallel. Default is 200. .SH EXPRESSIONS .PP The \fB\-expression\fR argument is a single string that describes the function to evaluate. The function expression is typically written in terms of the vector A. For example, the following expression will sum the first two input files together: A[0] + A[1] Multiple expressions can be given separated by semicolons, in which case only the value of the last expression is used. These expression lists can be used with assignment expressions to make the syntax very C-like: ratio = A[0]/A[1]; A[2]*exp(-ratio) An expression list in curly brackets is a valid expression and returns the value of last expression in the list. This is particularly useful in \fBfor\fR and \fBif\fR expressions (see below). There are two types of values in the language: vectors and scalars. Scalars literals are floating point numbers or may appear as symbols whose name starts with a lowercase letter. Besides normal scalar operators such as +, -, * and /, the expression language also supports the infix exponentiation operator ^ , the usual relational operators <, <=, >, >=, ==, != as well as the boolean operators && (and), || (or) and ! (not). Note that the && and || boolean operators always evaluate both operands, unlike C. Scalar mathematical functions include \fBabs\fR, \fBsqrt\fR, \fBexp\fR, \fBlog\fR, \fBsin\fR, \fBcos\fR, \fBtan\fR, \fBasin\fR, \fBacos\fR and \fBatan\fR. There are also some specialized functions: isnan(v) - 1 if v is invalid and 0 otherwise clamp(v1,v2,v3) - v1 bounded by [v2, v3] segment(v1,v2,v3) - tests if v1 is in [v2, v3] The scalar constant NaN is defined such that isnan(NaN) return 1. Vectors can be written in the following `extensional' form [ value1, value2, ... ] or by using the following range-generating notations: [ a : b ] generates {a, a+1, ..., b-1, b} [ a : b ) generates {a, a+1, ..., b-1} ( a : b ] generates {a+1, ..., b-1, b} ( a : b ) generates {a+1, ..., b-1} or be generated, by `intension'. The following intension expression generates the vector {3,2,1}: { i in [1:3] | 4 - i } Vectors may also appear as symbols whose name starts with an uppercase letter. In addition to the scalar operators, the following vector operators are supplied: avg - the average value of the scalars in vector len - the length of sum - the sum of the elements of prod - the product of the elements of max - the maximum value of min - the minimum value of imax - the index of the maximum value of imin - the index of the minimum value of V[s] - the s'th element of vector V with origin 0. Symbol names are introduced into a global symbol table by assignment expressions of the form a = A[2] * log(2) Symbols starting with a lowercase letter represent scalars while those starting with an uppercase letter represent vectors. Since = is an operator, its result can be used in an expression (as in C). A few control constructs are provided: For loops can be created to loop over a vector, assigning each value to a symbol and then evaluating an expression. This is done with expressions of the form total=0; for{i in [0:len(A))} total=total+A[i]; total which is equivalent to sum(A). Note that this is similar to using total=0; len{i in [0:len(A)) | total=total+A[i]}; total since the \fBfor\fR construct is actually an operator (although it is usually only used for changing symbol values). Note also that without the final "total", the expression would not be very useful since it would only return the length of the vector. As in C, a list of expressions can be specified in curlies: total=total2 = 0; for {i in [0:len(A))} { total = total + A[i]; total2 = total2 + A[i]^2 } There are also a few forms of the \fBif-then-else\fR construct: A[0]<0 ? 0 : A[0] if (A[0]<0) result=0 else result=A[0] The \fBelse\fR is optional. Again, the if construct is an operator, and the \fBthen\fR or \fBelse\fR expressions can be expression lists in curlies, in which case the value of the last expression is returned. If the \fBelse\fR expression is missing, then the value 0 is returned when the test expression is 0 (false). The principal oddity with the \fBfor\fR and \fBif\fR constructs is that unlike C statements, they must be separated from the next expression by a semicolon even when an expression list in curlies is used: for i in [0:len(A)) {total=total+A[i]} ; total/len(A) if (A[i]>0) {result=2;} else {result=1} ; result*5 An alternative way to introduce symbol names is through \fBlet\fR-expressions. For example, the following expression will always evaluate to 3: let a = 1, b = 2 in a + b These were originally designed to create variables only within the evaluated expression, but modifications have been made so that the global symbol table is changed. .SH EXAMPLES Here is an expression for calculating standard deviation, taking into account the possibility of invalid input data, which is ignored: s0 = s1 = s2 = 0; for { i in [0:len(A)) } { v=A[i]; if (!isnan(v)) { s0 = s0 + 1; s1 = s1 + v; s2 = s2 + v*v; } }; if (s0 > 1) { sqrt((s2 - s1*s1/s0) / (s0-1)); } else { NaN; }; The last if could be changed to return 0 if s0 is > 0 but <= 1. We also drop the curly brackets, but then there must not be a ";" between the if and the else if (s0 > 1) sqrt((s2 - s1*s1/s0) / (s0-1)) else if (s0 > 0) 0 else NaN If we want both the mean and the standard deviation, we can use the \fB\-outfile\fR option, invoking the command with minccalc -expfile stdev \\ -outfile mean mean.mnc \\ -outfile stdev stdev.mnc \\ infile1.mnc infile2.mnc ... And using the expression file (with yet another form of if expression): s0 = s1 = s2 = 0; for {i in [0:len(A))} { v=A[i]; if (!isnan(v)) { s0 = s0 + 1; s1 = s1 + v; s2 = s2 + v*v; } }; stdev = (s0 > 1) ? sqrt((s2 - s1*s1/s0) / (s0-1)) : (s0 > 0) ? 0 : NaN ; mean = (s0 > 0) ? s1 / s0 : NaN ; .SH CAVEATS A few things you should remember... Vector variables must start with an uppercase letter. Vector variable names must not be one of the function keywords, sum, len, prod, ... etc For loops and if expressions always need to be separated from the next expression by a semicolon. The symbol table is global. Boolean operators && and || always evaluate both operands. A note on parallelism: For efficiency reasons, evaluations are done on many voxels at once (the number of voxels is referred to as the width of the evaluation and is changed with the \fB-eval_width\fR option). An odd consequence of this is that both sides of an if-else statement are always evaluated (unless all voxels give the same test result), but statements within each consequent are only evaluated on the appropriate voxels. In particular, entries in the symbol table are only modified according to a voxel mask. A side-effect of this is that any vector symbol set in an if-else consequent must not change the length of the symbol (although it can create it) and both sides of the consequent must agree on the length of any vector symbols that they both modify. If this is not clear, just try it - the program will complain if it is not happy. .SH AUTHOR Andrew Janke - a.janke@gmail.com .SH COPYRIGHTS Copyright \(co 2000 by Andrew Janke .SH "SEE ALSO" .LP .BR mincmath (1) minc-2.2.00/progs/minccalc/gram.c0000644000265600003100000023530212030102322013422 00000000000000 /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.4.1" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 1 "gram.y" #include #include #include #include #include #include "node.h" #define INVALID_VALUE (-DBL_MAX) /* Avoid problems with conflicting declarations */ void yyerror(const char *msg); /* Line 189 of yacc.c */ #line 88 "progs/minccalc/gram.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 1 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NAN = 258, IN = 259, TO = 260, IDENT = 261, REAL = 262, AVG = 263, PROD = 264, SUM = 265, LET = 266, NEG = 267, LEN = 268, MAX = 269, MIN = 270, IMAX = 271, IMIN = 272, ISNAN = 273, SQRT = 274, ABS = 275, EXP = 276, LOG = 277, SIN = 278, COS = 279, TAN = 280, ASIN = 281, ACOS = 282, ATAN = 283, CLAMP = 284, SEGMENT = 285, LT = 286, LE = 287, GT = 288, GE = 289, EQ = 290, NE = 291, NOT = 292, AND = 293, OR = 294, IF = 295, ELSE = 296, FOR = 297 }; #endif /* Tokens. */ #define NAN 258 #define IN 259 #define TO 260 #define IDENT 261 #define REAL 262 #define AVG 263 #define PROD 264 #define SUM 265 #define LET 266 #define NEG 267 #define LEN 268 #define MAX 269 #define MIN 270 #define IMAX 271 #define IMIN 272 #define ISNAN 273 #define SQRT 274 #define ABS 275 #define EXP 276 #define LOG 277 #define SIN 278 #define COS 279 #define TAN 280 #define ASIN 281 #define ACOS 282 #define ATAN 283 #define CLAMP 284 #define SEGMENT 285 #define LT 286 #define LE 287 #define GT 288 #define GE 289 #define EQ 290 #define NE 291 #define NOT 292 #define AND 293 #define OR 294 #define IF 295 #define ELSE 296 #define FOR 297 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 214 of yacc.c */ #line 15 "gram.y" int pos; node_t node; double real; ident_t ident; /* Line 214 of yacc.c */ #line 217 "progs/minccalc/gram.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 229 "progs/minccalc/gram.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 69 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 800 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 61 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 6 /* YYNRULES -- Number of rules. */ #define YYNRULES 63 /* YYNRULES -- Number of states. */ #define YYNSTATES 152 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 297 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 48, 45, 43, 56, 44, 51, 46, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 59, 58, 2, 52, 2, 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 49, 2, 50, 53, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 54, 57, 55, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 5, 9, 12, 14, 18, 22, 26, 34, 40, 46, 52, 58, 62, 66, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 118, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185, 194, 203, 209, 217, 223, 231, 233, 235, 237, 243, 249, 251 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 62, 0, -1, 63, -1, 64, 58, 63, -1, 64, 58, -1, 64, -1, 47, 64, 48, -1, 54, 63, 55, -1, 49, 66, 50, -1, 54, 6, 4, 64, 57, 64, 55, -1, 47, 64, 59, 64, 48, -1, 47, 64, 59, 64, 50, -1, 49, 64, 59, 64, 48, -1, 49, 64, 59, 64, 50, -1, 64, 43, 64, -1, 64, 44, 64, -1, 44, 64, -1, 64, 45, 64, -1, 64, 46, 64, -1, 64, 53, 64, -1, 64, 31, 64, -1, 64, 32, 64, -1, 64, 33, 64, -1, 64, 34, 64, -1, 64, 35, 64, -1, 64, 36, 64, -1, 64, 38, 64, -1, 64, 39, 64, -1, 64, 49, 64, 50, -1, 6, 52, 64, -1, 11, 65, -1, 37, 64, -1, 10, 64, -1, 9, 64, -1, 8, 64, -1, 13, 64, -1, 14, 64, -1, 15, 64, -1, 16, 64, -1, 17, 64, -1, 18, 64, -1, 19, 64, -1, 20, 64, -1, 21, 64, -1, 22, 64, -1, 23, 64, -1, 24, 64, -1, 25, 64, -1, 26, 64, -1, 27, 64, -1, 28, 64, -1, 29, 47, 64, 56, 64, 56, 64, 48, -1, 30, 47, 64, 56, 64, 56, 64, 48, -1, 64, 60, 64, 59, 64, -1, 40, 47, 64, 48, 64, 41, 64, -1, 40, 47, 64, 48, 64, -1, 42, 54, 6, 4, 64, 55, 64, -1, 6, -1, 7, -1, 3, -1, 6, 52, 64, 56, 65, -1, 6, 52, 64, 4, 64, -1, 64, -1, 66, 56, 64, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 53, 53, 57, 64, 67, 71, 74, 77, 80, 88, 96, 104, 112, 120, 128, 136, 146, 154, 162, 170, 178, 186, 194, 202, 210, 218, 226, 234, 241, 248, 251, 258, 264, 270, 276, 282, 288, 294, 300, 306, 313, 320, 327, 334, 341, 348, 355, 362, 369, 376, 383, 392, 401, 409, 417, 424, 432, 438, 444, 453, 460, 469, 474 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "NAN", "IN", "TO", "IDENT", "REAL", "AVG", "PROD", "SUM", "LET", "NEG", "LEN", "MAX", "MIN", "IMAX", "IMIN", "ISNAN", "SQRT", "ABS", "EXP", "LOG", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "CLAMP", "SEGMENT", "LT", "LE", "GT", "GE", "EQ", "NE", "NOT", "AND", "OR", "IF", "ELSE", "FOR", "'+'", "'-'", "'*'", "'/'", "'('", "')'", "'['", "']'", "'.'", "'='", "'^'", "'{'", "'}'", "','", "'|'", "';'", "':'", "'?'", "$accept", "top", "exprlist", "expr", "letexpr", "vector", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 43, 45, 42, 47, 40, 41, 91, 93, 46, 61, 94, 123, 125, 44, 124, 59, 58, 63 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 61, 62, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 66, 66 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 3, 2, 1, 3, 3, 3, 7, 5, 5, 5, 5, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 5, 7, 5, 7, 1, 1, 1, 5, 5, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 0, 59, 57, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 0, 34, 33, 32, 0, 30, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 0, 31, 0, 0, 16, 0, 62, 0, 57, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 29, 0, 0, 0, 0, 0, 6, 0, 0, 8, 0, 0, 7, 20, 21, 22, 23, 24, 25, 26, 27, 14, 15, 17, 18, 0, 19, 3, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 28, 0, 0, 0, 0, 0, 55, 0, 10, 11, 12, 13, 0, 53, 61, 60, 0, 0, 0, 0, 0, 0, 0, 54, 56, 9, 51, 52 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 33, 34, 35, 41, 66 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -48 static const yytype_int16 yypact[] = { 167, -48, -21, -48, 167, 167, 167, 27, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 6, 11, 167, 12, -11, 167, 167, 167, 216, 45, -48, 3, 167, 1, 1, 1, 8, -48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 167, 167, -9, 167, 56, -9, 240, 316, -27, -1, 9, -48, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 701, 167, 346, 376, 406, 61, -48, 167, 167, -48, 167, 167, -48, 42, 42, 42, 42, 747, 747, 74, 724, -25, -25, -9, -9, 429, -9, -48, 452, 112, 167, 167, 167, 167, 270, 293, 701, 482, -48, 167, 167, 27, 512, 542, 572, 595, -48, -48, -48, -48, 167, 701, 701, -48, 167, 167, 167, 167, 625, 655, 678, 701, 701, -48, -48, -48 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -48, -48, -2, -4, -47, -48 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { 37, 38, 39, 97, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 80, 81, 60, 95, 82, 63, 64, 65, 83, 96, 68, 36, 86, 40, 70, 71, 72, 73, 74, 75, 82, 76, 77, 62, 83, 69, 78, 79, 80, 81, 82, 36, 82, 58, 88, 89, 83, 90, 59, 61, 87, 84, 91, 85, 98, 119, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 139, 114, 113, 115, 0, 78, 79, 80, 81, 120, 121, 82, 122, 123, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 71, 72, 73, 74, 75, 0, 128, 129, 130, 131, 126, 78, 79, 80, 81, 137, 138, 82, 0, 0, 0, 83, 0, 0, 0, 0, 144, 0, 0, 0, 145, 146, 147, 148, 0, 0, 0, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 127, 0, 1, 0, 85, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 0, 0, 27, 0, 28, 0, 29, 0, 0, 30, 0, 31, 0, 0, 1, 0, 32, 67, 3, 4, 5, 6, 7, 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 0, 0, 27, 0, 28, 0, 29, 0, 0, 30, 0, 31, 0, 0, 0, 0, 32, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 92, 82, 0, 0, 0, 83, 0, 0, 0, 0, 0, 93, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 132, 82, 133, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 134, 82, 135, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 0, 0, 94, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 116, 0, 0, 0, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 117, 0, 0, 0, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 118, 82, 0, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 124, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 0, 0, 125, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 136, 0, 0, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 140, 0, 0, 0, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 141, 0, 0, 0, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 142, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 143, 0, 0, 0, 0, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 0, 149, 0, 0, 0, 0, 85, 70, 71, 72, 73, 74, 75, 0, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 150, 82, 0, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 151, 82, 0, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 77, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 70, 71, 72, 73, 74, 75, 85, 76, 0, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83, 70, 71, 72, 73, 0, 0, 0, 0, 0, 0, 0, 0, 78, 79, 80, 81, 0, 0, 82, 0, 0, 0, 83 }; static const yytype_int16 yycheck[] = { 4, 5, 6, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 45, 46, 26, 50, 49, 29, 30, 31, 53, 56, 32, 52, 36, 6, 31, 32, 33, 34, 35, 36, 49, 38, 39, 54, 53, 0, 43, 44, 45, 46, 49, 52, 49, 47, 58, 59, 53, 61, 47, 47, 52, 58, 6, 60, 55, 4, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 127, 85, 84, 87, -1, 43, 44, 45, 46, 93, 94, 49, 96, 97, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, 32, 33, 34, 35, 36, -1, 116, 117, 118, 119, 4, 43, 44, 45, 46, 125, 126, 49, -1, -1, -1, 53, -1, -1, -1, -1, 136, -1, -1, -1, 140, 141, 142, 143, -1, -1, -1, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, 56, -1, 3, -1, 60, 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -1, -1, -1, -1, -1, -1, 37, -1, -1, 40, -1, 42, -1, 44, -1, -1, 47, -1, 49, -1, -1, 3, -1, 54, 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -1, -1, -1, -1, -1, -1, 37, -1, -1, 40, -1, 42, -1, 44, -1, -1, 47, -1, 49, -1, -1, -1, -1, 54, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, 48, 49, -1, -1, -1, 53, -1, -1, -1, -1, -1, 59, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, 48, 49, 50, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, 48, 49, 50, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, -1, -1, -1, 59, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, 56, -1, -1, -1, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, 56, -1, -1, -1, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, 48, 49, -1, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, 50, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, -1, -1, -1, 59, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, -1, 57, -1, -1, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, 56, -1, -1, -1, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, -1, 56, -1, -1, -1, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, 41, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, 55, -1, -1, -1, -1, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, -1, 55, -1, -1, -1, -1, 60, 31, 32, 33, 34, 35, 36, -1, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, 48, 49, -1, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, 48, 49, -1, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, 31, 32, 33, 34, 35, 36, 60, 38, -1, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53, 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, 45, 46, -1, -1, 49, -1, -1, -1, 53 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 37, 40, 42, 44, 47, 49, 54, 62, 63, 64, 52, 64, 64, 64, 6, 65, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 47, 47, 64, 47, 54, 64, 64, 64, 66, 6, 63, 0, 31, 32, 33, 34, 35, 36, 38, 39, 43, 44, 45, 46, 49, 53, 58, 60, 64, 52, 64, 64, 64, 6, 48, 59, 59, 50, 56, 4, 55, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 64, 64, 56, 56, 48, 4, 64, 64, 64, 64, 50, 59, 4, 56, 64, 64, 64, 64, 48, 50, 48, 50, 57, 64, 64, 65, 56, 56, 41, 55, 64, 64, 64, 64, 64, 55, 48, 48 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*-------------------------. | yyparse or yypush_parse. | `-------------------------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: /* Line 1455 of yacc.c */ #line 54 "gram.y" { root = (yyvsp[(1) - (1)].node); } break; case 3: /* Line 1455 of yacc.c */ #line 58 "gram.y" { (yyval.node) = new_node(2, node_is_scalar((yyvsp[(3) - (3)].node))); (yyval.node)->type = NODETYPE_EXPRLIST; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 4: /* Line 1455 of yacc.c */ #line 65 "gram.y" { (yyval.node) = (yyvsp[(1) - (2)].node); } break; case 5: /* Line 1455 of yacc.c */ #line 68 "gram.y" { (yyval.node) = (yyvsp[(1) - (1)].node); } break; case 6: /* Line 1455 of yacc.c */ #line 72 "gram.y" { (yyval.node) = (yyvsp[(2) - (3)].node); } break; case 7: /* Line 1455 of yacc.c */ #line 75 "gram.y" { (yyval.node) = (yyvsp[(2) - (3)].node); } break; case 8: /* Line 1455 of yacc.c */ #line 78 "gram.y" { (yyval.node) = (yyvsp[(2) - (3)].node); } break; case 9: /* Line 1455 of yacc.c */ #line 81 "gram.y" { (yyval.node) = new_vector_node(2); (yyval.node)->type = NODETYPE_GEN; (yyval.node)->pos = (yyvsp[(7) - (7)].pos); (yyval.node)->ident = (yyvsp[(2) - (7)].ident); (yyval.node)->expr[0] = (yyvsp[(4) - (7)].node); (yyval.node)->expr[1] = (yyvsp[(6) - (7)].node); } break; case 10: /* Line 1455 of yacc.c */ #line 89 "gram.y" { (yyval.node) = new_vector_node(2); (yyval.node)->type = NODETYPE_RANGE; (yyval.node)->flags = 0; (yyval.node)->pos = (yyvsp[(5) - (5)].pos); (yyval.node)->expr[0] = (yyvsp[(2) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(4) - (5)].node); } break; case 11: /* Line 1455 of yacc.c */ #line 97 "gram.y" { (yyval.node) = new_vector_node(2); (yyval.node)->type = NODETYPE_RANGE; (yyval.node)->flags = RANGE_EXACT_UPPER; (yyval.node)->pos = (yyvsp[(5) - (5)].pos); (yyval.node)->expr[0] = (yyvsp[(2) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(4) - (5)].node); } break; case 12: /* Line 1455 of yacc.c */ #line 105 "gram.y" { (yyval.node) = new_vector_node(2); (yyval.node)->type = NODETYPE_RANGE; (yyval.node)->flags = RANGE_EXACT_LOWER; (yyval.node)->pos = (yyvsp[(5) - (5)].pos); (yyval.node)->expr[0] = (yyvsp[(2) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(4) - (5)].node); } break; case 13: /* Line 1455 of yacc.c */ #line 113 "gram.y" { (yyval.node) = new_vector_node(2); (yyval.node)->type = NODETYPE_RANGE; (yyval.node)->flags = RANGE_EXACT_UPPER | RANGE_EXACT_LOWER; (yyval.node)->pos = (yyvsp[(5) - (5)].pos); (yyval.node)->expr[0] = (yyvsp[(2) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(4) - (5)].node); } break; case 14: /* Line 1455 of yacc.c */ #line 121 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_ADD; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 15: /* Line 1455 of yacc.c */ #line 129 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_SUB; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 16: /* Line 1455 of yacc.c */ #line 137 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_SUB; (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = new_scalar_node(0); (yyval.node)->expr[0]->type = NODETYPE_REAL; (yyval.node)->expr[0]->real = 0.0; (yyval.node)->expr[1] = (yyvsp[(2) - (2)].node); } break; case 17: /* Line 1455 of yacc.c */ #line 147 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->type = NODETYPE_MUL; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 18: /* Line 1455 of yacc.c */ #line 155 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->type = NODETYPE_DIV; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 19: /* Line 1455 of yacc.c */ #line 163 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->type = NODETYPE_POW; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 20: /* Line 1455 of yacc.c */ #line 171 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_LT; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 21: /* Line 1455 of yacc.c */ #line 179 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_LE; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 22: /* Line 1455 of yacc.c */ #line 187 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_GT; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 23: /* Line 1455 of yacc.c */ #line 195 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_GE; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 24: /* Line 1455 of yacc.c */ #line 203 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_EQ; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 25: /* Line 1455 of yacc.c */ #line 211 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_NE; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 26: /* Line 1455 of yacc.c */ #line 219 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_AND; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 27: /* Line 1455 of yacc.c */ #line 227 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_OR; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; case 28: /* Line 1455 of yacc.c */ #line 235 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_INDEX; (yyval.node)->pos = (yyvsp[(4) - (4)].pos); (yyval.node)->expr[0] = (yyvsp[(1) - (4)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (4)].node); } break; case 29: /* Line 1455 of yacc.c */ #line 242 "gram.y" { (yyval.node) = new_node(1, node_is_scalar((yyvsp[(3) - (3)].node))); (yyval.node)->type = NODETYPE_ASSIGN; (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->ident = (yyvsp[(1) - (3)].ident); (yyval.node)->expr[0] = (yyvsp[(3) - (3)].node); } break; case 30: /* Line 1455 of yacc.c */ #line 249 "gram.y" { (yyval.node) = (yyvsp[(2) - (2)].node); } break; case 31: /* Line 1455 of yacc.c */ #line 252 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_NOT; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 32: /* Line 1455 of yacc.c */ #line 259 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_SUM; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 33: /* Line 1455 of yacc.c */ #line 265 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_PROD; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 34: /* Line 1455 of yacc.c */ #line 271 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_AVG; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 35: /* Line 1455 of yacc.c */ #line 277 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_LEN; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 36: /* Line 1455 of yacc.c */ #line 283 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_MAX; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 37: /* Line 1455 of yacc.c */ #line 289 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_MIN; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 38: /* Line 1455 of yacc.c */ #line 295 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_IMAX; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 39: /* Line 1455 of yacc.c */ #line 301 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_IMIN; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 40: /* Line 1455 of yacc.c */ #line 307 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_ISNAN; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 41: /* Line 1455 of yacc.c */ #line 314 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_SQRT; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 42: /* Line 1455 of yacc.c */ #line 321 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_ABS; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 43: /* Line 1455 of yacc.c */ #line 328 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_EXP; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 44: /* Line 1455 of yacc.c */ #line 335 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_LOG; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 45: /* Line 1455 of yacc.c */ #line 342 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_SIN; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 46: /* Line 1455 of yacc.c */ #line 349 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_COS; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 47: /* Line 1455 of yacc.c */ #line 356 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_TAN; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 48: /* Line 1455 of yacc.c */ #line 363 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_ASIN; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 49: /* Line 1455 of yacc.c */ #line 370 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_ACOS; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 50: /* Line 1455 of yacc.c */ #line 377 "gram.y" { (yyval.node) = new_scalar_node(1); (yyval.node)->pos = (yyvsp[(1) - (2)].pos); (yyval.node)->type = NODETYPE_ATAN; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(2) - (2)].node); } break; case 51: /* Line 1455 of yacc.c */ #line 384 "gram.y" { (yyval.node) = new_scalar_node(3); (yyval.node)->pos = (yyvsp[(1) - (8)].pos); (yyval.node)->type = NODETYPE_CLAMP; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(3) - (8)].node); (yyval.node)->expr[1] = (yyvsp[(5) - (8)].node); (yyval.node)->expr[2] = (yyvsp[(7) - (8)].node); } break; case 52: /* Line 1455 of yacc.c */ #line 393 "gram.y" { (yyval.node) = new_scalar_node(3); (yyval.node)->pos = (yyvsp[(1) - (8)].pos); (yyval.node)->type = NODETYPE_SEGMENT; (yyval.node)->flags |= ALLARGS_SCALAR; (yyval.node)->expr[0] = (yyvsp[(3) - (8)].node); (yyval.node)->expr[1] = (yyvsp[(5) - (8)].node); (yyval.node)->expr[2] = (yyvsp[(7) - (8)].node); } break; case 53: /* Line 1455 of yacc.c */ #line 402 "gram.y" { (yyval.node) = new_node(3, node_is_scalar((yyvsp[(3) - (5)].node))); (yyval.node)->pos = (yyvsp[(2) - (5)].pos); (yyval.node)->type = NODETYPE_IFELSE; (yyval.node)->expr[0] = (yyvsp[(1) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (5)].node); (yyval.node)->expr[2] = (yyvsp[(5) - (5)].node); } break; case 54: /* Line 1455 of yacc.c */ #line 410 "gram.y" { (yyval.node) = new_node(3, node_is_scalar((yyvsp[(5) - (7)].node))); (yyval.node)->pos = (yyvsp[(1) - (7)].pos); (yyval.node)->type = NODETYPE_IFELSE; (yyval.node)->expr[0] = (yyvsp[(3) - (7)].node); (yyval.node)->expr[1] = (yyvsp[(5) - (7)].node); (yyval.node)->expr[2] = (yyvsp[(7) - (7)].node); } break; case 55: /* Line 1455 of yacc.c */ #line 418 "gram.y" { (yyval.node) = new_node(2, node_is_scalar((yyvsp[(5) - (5)].node))); (yyval.node)->pos = (yyvsp[(1) - (5)].pos); (yyval.node)->type = NODETYPE_IFELSE; (yyval.node)->expr[0] = (yyvsp[(3) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(5) - (5)].node); } break; case 56: /* Line 1455 of yacc.c */ #line 425 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->pos = (yyvsp[(1) - (7)].pos); (yyval.node)->type = NODETYPE_FOR; (yyval.node)->ident = (yyvsp[(3) - (7)].ident); (yyval.node)->expr[0] = (yyvsp[(5) - (7)].node); (yyval.node)->expr[1] = (yyvsp[(7) - (7)].node); } break; case 57: /* Line 1455 of yacc.c */ #line 433 "gram.y" { (yyval.node) = new_node(0, ident_is_scalar((yyvsp[(1) - (1)].ident))); (yyval.node)->type = NODETYPE_IDENT; (yyval.node)->pos = -1; (yyval.node)->ident = (yyvsp[(1) - (1)].ident); } break; case 58: /* Line 1455 of yacc.c */ #line 439 "gram.y" { (yyval.node) = new_scalar_node(0); (yyval.node)->pos = -1; (yyval.node)->type = NODETYPE_REAL; (yyval.node)->real = (yyvsp[(1) - (1)].real); } break; case 59: /* Line 1455 of yacc.c */ #line 445 "gram.y" { (yyval.node) = new_scalar_node(0); (yyval.node)->pos = -1; (yyval.node)->type = NODETYPE_REAL; (yyval.node)->real = INVALID_VALUE; } break; case 60: /* Line 1455 of yacc.c */ #line 454 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->type = NODETYPE_LET; (yyval.node)->pos = (yyvsp[(2) - (5)].pos); (yyval.node)->ident = (yyvsp[(1) - (5)].ident); (yyval.node)->expr[0] = (yyvsp[(3) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(5) - (5)].node); } break; case 61: /* Line 1455 of yacc.c */ #line 461 "gram.y" { (yyval.node) = new_scalar_node(2); (yyval.node)->pos = (yyvsp[(2) - (5)].pos); (yyval.node)->type = NODETYPE_LET; (yyval.node)->ident = (yyvsp[(1) - (5)].ident); (yyval.node)->expr[0] = (yyvsp[(3) - (5)].node); (yyval.node)->expr[1] = (yyvsp[(5) - (5)].node); } break; case 62: /* Line 1455 of yacc.c */ #line 470 "gram.y" { (yyval.node) = new_vector_node(1); (yyval.node)->pos = (yyvsp[(1) - (1)].node)->pos; (yyval.node)->type = NODETYPE_VEC1; (yyval.node)->expr[0] = (yyvsp[(1) - (1)].node); } break; case 63: /* Line 1455 of yacc.c */ #line 475 "gram.y" { (yyval.node) = new_vector_node(2); (yyval.node)->pos = (yyvsp[(2) - (3)].pos); (yyval.node)->type = NODETYPE_VEC2; (yyval.node)->expr[0] = (yyvsp[(1) - (3)].node); (yyval.node)->expr[1] = (yyvsp[(3) - (3)].node); } break; /* Line 1455 of yacc.c */ #line 2348 "progs/minccalc/gram.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } /* Line 1675 of yacc.c */ #line 482 "gram.y" node_t root; void yyerror(msg) const char *msg; { extern int lexpos; show_error(lexpos, msg); } minc-2.2.00/progs/minccalc/lex.c0000644000265600003100000014515712030102322013274 00000000000000 #line 3 "progs/minccalc/lex.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 42 #define YY_END_OF_BUFFER 43 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[108] = { 0, 0, 0, 43, 41, 40, 40, 35, 41, 39, 29, 41, 31, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 41, 40, 34, 36, 39, 39, 0, 30, 33, 32, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 25, 38, 23, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 24, 37, 39, 0, 39, 28, 8, 38, 38, 38, 1, 38, 16, 38, 13, 27, 38, 38, 38, 5, 4, 14, 9, 10, 38, 38, 15, 38, 2, 17, 19, 18, 20, 38, 26, 11, 12, 38, 3, 38, 7, 21, 6, 38, 38, 22, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, 1, 1, 5, 1, 1, 1, 1, 6, 1, 6, 7, 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 9, 10, 11, 1, 1, 12, 12, 12, 12, 13, 12, 12, 12, 12, 12, 12, 12, 12, 14, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 15, 1, 16, 17, 18, 19, 20, 21, 22, 12, 23, 12, 12, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 12, 35, 12, 12, 1, 36, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[37] = { 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 } ; static yyconst flex_int16_t yy_base[109] = { 0, 0, 0, 135, 136, 35, 37, 124, 128, 34, 122, 121, 120, 0, 113, 26, 21, 26, 101, 38, 26, 33, 97, 42, 39, 90, 49, 136, 136, 59, 69, 62, 136, 136, 136, 0, 111, 93, 96, 99, 105, 98, 103, 87, 86, 88, 85, 0, 57, 0, 88, 52, 91, 77, 85, 83, 87, 82, 77, 81, 79, 0, 136, 73, 96, 95, 0, 0, 71, 75, 74, 0, 74, 0, 78, 0, 0, 62, 70, 79, 0, 0, 0, 0, 0, 75, 67, 0, 59, 0, 0, 0, 0, 0, 62, 0, 0, 0, 62, 0, 67, 0, 0, 0, 59, 51, 0, 136, 72 } ; static yyconst flex_int16_t yy_def[109] = { 0, 107, 1, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 0, 107 } ; static yyconst flex_int16_t yy_nxt[173] = { 0, 4, 5, 6, 7, 8, 4, 4, 9, 10, 11, 12, 13, 13, 14, 4, 15, 13, 16, 13, 17, 18, 13, 19, 20, 21, 13, 13, 22, 13, 13, 23, 24, 13, 13, 13, 25, 26, 26, 26, 26, 29, 30, 37, 38, 42, 51, 31, 43, 53, 44, 26, 26, 52, 31, 60, 54, 39, 40, 47, 41, 45, 56, 48, 49, 57, 61, 63, 64, 50, 65, 58, 31, 77, 35, 59, 29, 30, 80, 31, 78, 63, 31, 106, 81, 105, 31, 104, 103, 31, 102, 101, 100, 31, 99, 98, 97, 96, 95, 94, 93, 92, 91, 65, 65, 90, 89, 88, 87, 86, 85, 84, 83, 82, 79, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 62, 55, 46, 36, 34, 33, 32, 28, 27, 107, 3, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107 } ; static yyconst flex_int16_t yy_chk[173] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 6, 6, 9, 9, 15, 15, 16, 20, 9, 16, 21, 17, 26, 26, 20, 9, 24, 21, 15, 15, 19, 15, 17, 23, 19, 19, 23, 24, 29, 31, 19, 31, 23, 29, 48, 108, 23, 30, 30, 51, 29, 48, 63, 30, 105, 51, 104, 63, 100, 98, 30, 94, 88, 86, 63, 85, 79, 78, 77, 74, 72, 70, 69, 68, 65, 64, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 25, 22, 18, 14, 12, 11, 10, 8, 7, 3, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "lex.l" #line 2 "lex.l" #include #include "node.h" #include "gram.h" int lexpos = 0; #define setpos() yylval.pos = lexpos; lexpos += yyleng #line 537 "progs/minccalc/lex.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (void ); int yyget_debug (void ); void yyset_debug (int debug_flag ); YY_EXTRA_TYPE yyget_extra (void ); void yyset_extra (YY_EXTRA_TYPE user_defined ); FILE *yyget_in (void ); void yyset_in (FILE * in_str ); FILE *yyget_out (void ); void yyset_out (FILE * out_str ); int yyget_leng (void ); char *yyget_text (void ); int yyget_lineno (void ); void yyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif static void yyunput (int c,char *buf_ptr ); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 10 "lex.l" #line 727 "progs/minccalc/lex.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 108 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 136 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 12 "lex.l" setpos(); return AVG; YY_BREAK case 2: YY_RULE_SETUP #line 13 "lex.l" setpos(); return SUM; YY_BREAK case 3: YY_RULE_SETUP #line 14 "lex.l" setpos(); return PROD; YY_BREAK case 4: YY_RULE_SETUP #line 15 "lex.l" setpos(); return LET; YY_BREAK case 5: YY_RULE_SETUP #line 16 "lex.l" setpos(); return LEN; YY_BREAK case 6: YY_RULE_SETUP #line 17 "lex.l" setpos(); return ISNAN; YY_BREAK case 7: YY_RULE_SETUP #line 18 "lex.l" setpos(); return SQRT; YY_BREAK case 8: YY_RULE_SETUP #line 19 "lex.l" setpos(); return ABS; YY_BREAK case 9: YY_RULE_SETUP #line 20 "lex.l" setpos(); return MAX; YY_BREAK case 10: YY_RULE_SETUP #line 21 "lex.l" setpos(); return MIN; YY_BREAK case 11: YY_RULE_SETUP #line 22 "lex.l" setpos(); return IMAX; YY_BREAK case 12: YY_RULE_SETUP #line 23 "lex.l" setpos(); return IMIN; YY_BREAK case 13: YY_RULE_SETUP #line 24 "lex.l" setpos(); return EXP; YY_BREAK case 14: YY_RULE_SETUP #line 25 "lex.l" setpos(); return LOG; YY_BREAK case 15: YY_RULE_SETUP #line 26 "lex.l" setpos(); return SIN; YY_BREAK case 16: YY_RULE_SETUP #line 27 "lex.l" setpos(); return COS; YY_BREAK case 17: YY_RULE_SETUP #line 28 "lex.l" setpos(); return TAN; YY_BREAK case 18: YY_RULE_SETUP #line 29 "lex.l" setpos(); return ASIN; YY_BREAK case 19: YY_RULE_SETUP #line 30 "lex.l" setpos(); return ACOS; YY_BREAK case 20: YY_RULE_SETUP #line 31 "lex.l" setpos(); return ATAN; YY_BREAK case 21: YY_RULE_SETUP #line 32 "lex.l" setpos(); return CLAMP; YY_BREAK case 22: YY_RULE_SETUP #line 33 "lex.l" setpos(); return SEGMENT; YY_BREAK case 23: YY_RULE_SETUP #line 34 "lex.l" setpos(); return IN; YY_BREAK case 24: YY_RULE_SETUP #line 35 "lex.l" setpos(); return TO; YY_BREAK case 25: YY_RULE_SETUP #line 36 "lex.l" setpos(); return IF; YY_BREAK case 26: YY_RULE_SETUP #line 37 "lex.l" setpos(); return ELSE; YY_BREAK case 27: YY_RULE_SETUP #line 38 "lex.l" setpos(); return FOR; YY_BREAK case 28: YY_RULE_SETUP #line 39 "lex.l" setpos(); return NAN; YY_BREAK case 29: YY_RULE_SETUP #line 40 "lex.l" setpos(); return LT; YY_BREAK case 30: YY_RULE_SETUP #line 41 "lex.l" setpos(); return LE; YY_BREAK case 31: YY_RULE_SETUP #line 42 "lex.l" setpos(); return GT; YY_BREAK case 32: YY_RULE_SETUP #line 43 "lex.l" setpos(); return GE; YY_BREAK case 33: YY_RULE_SETUP #line 44 "lex.l" setpos(); return EQ; YY_BREAK case 34: YY_RULE_SETUP #line 45 "lex.l" setpos(); return NE; YY_BREAK case 35: YY_RULE_SETUP #line 46 "lex.l" setpos(); return NOT; YY_BREAK case 36: YY_RULE_SETUP #line 47 "lex.l" setpos(); return AND; YY_BREAK case 37: YY_RULE_SETUP #line 48 "lex.l" setpos(); return OR; YY_BREAK case 38: YY_RULE_SETUP #line 49 "lex.l" { setpos(); yylval.ident = new_ident(yytext); return IDENT; } YY_BREAK case 39: YY_RULE_SETUP #line 54 "lex.l" { setpos(); yylval.real = atof(yytext);; return REAL; } YY_BREAK case 40: /* rule 40 can match eol */ YY_RULE_SETUP #line 59 "lex.l" setpos(); YY_BREAK case 41: YY_RULE_SETUP #line 60 "lex.l" setpos(); return yytext[0]; YY_BREAK case 42: YY_RULE_SETUP #line 63 "lex.l" ECHO; YY_BREAK #line 1029 "progs/minccalc/lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 108 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 108 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 107); return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ int yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param line_number * */ void yyset_lineno (int line_number ) { yylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * in_str ) { yyin = in_str ; } void yyset_out (FILE * out_str ) { yyout = out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int bdebug ) { yy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 63 "lex.l" static YY_BUFFER_STATE lex_state; void lex_init(const char *s){ lex_state = yy_scan_string(s); } void lex_finalize(){ yy_delete_buffer(lex_state); } int yywrap(){ return 1; } minc-2.2.00/progs/minccalc/minccalc.c0000644000265600003100000005542312027132662014271 00000000000000/* ----------------------------- MNI Header ----------------------------------- minccalc.c A expression parser that works voxel-by-voxel for minc files Andrew Janke - a.janke@gmail.com Center for Magnetic Resonance University of Queensland Original Grammar and parser by David Leonard - leonard@csee.uq.edu.au Department of Computer Science University of Queensland Modifications by Peter Neelin - neelin@bic.mni.mcgill.ca McConnell Brain Imaging Centre Montreal Neurological Institute McGill University This is predominately a rehash of mincmath by Peter Neelin * $Log: minccalc.c,v $ * Revision 1.19 2010-03-27 15:24:03 rotor * * added outfile checks (with clobber) in minccalc * * Revision 1.18 2008/01/17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 1.17 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 1.16 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 1.15 2008/01/11 04:24:16 rotor * * updated all my email addresses * * removed a (very) outdated TODO file * * Revision 1.14 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 1.13 2005/08/26 21:07:16 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 1.12 2004/12/14 23:52:23 bert * Get rid of compilation warnings w/c99 * * Revision 1.11 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 1.10 2004/06/11 20:55:37 bert * Fix for nasty bug which causes lots of bogus zero values to be inserted when minccalc is used with a file with a vector_dimension * * Revision 1.9 2004/04/27 15:37:52 bert * Added -2 option * * Revision 1.8 2001/05/24 15:08:40 neelin * Added support for comments so that minccalc scripts can be created. * * Revision 1.7 2001/05/04 15:40:33 neelin * Added -outfile option. * Changed syntax of for to use curlies around first part. * Changed syntax of for and if to evaluate an expression in the body, rather * than an expression list in curlies. * * Revision 1.6 2001/05/02 16:27:19 neelin * Fixed handling of invalid values. Added NaN constant. Force copy of * data when assigning to a symbol so that s1 = s2 = expr does the right * thing (s1 and s2 should be separate copies of the data). Updated man * page. * * Revision 1.5 2001/05/02 01:38:15 neelin * Major changes to allow parallel evaluations. Created scalar_t type * along the lines of vector_t (reference counting, etc.). Compiles * and runs on basic standard deviation calculation (with test for invalid * data). Gives over 3 times speedup compared to old version (on linux box). * SD calculation is slightly under half the speed of mincaverage. * Changes are significant enough and testing is little enough that there * are probably lots of bugs left. * * Revision 1.4 2001/04/30 19:16:43 neelin * Added assignment operator, made symbol table global, added expression lists, * for loops, if operators and changed range operator to colon. * * Revision 1.3 2001/04/26 19:12:39 neelin * Finished up addition of operators and handling of invalid values. * This version seems to work. * * Revision 1.2 2001/04/24 18:17:09 neelin * Added CVS logging. * Thu Dec 21 17:26:46 EST 2000 - Added use of voxel_loop Thu Oct 5 17:09:12 EST 2000 - First alpha version Mon May 28 01:00:01 EST 2000 - First minc version - Andrew Janke Mon May 21 01:01:01 EST 2000 - Original version "imgcalc" by David Leonard ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "node.h" #include "read_file_names.h" /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Data values for invalid data and for uninitialized data */ #define INVALID_DATA -DBL_MAX #define UNINITIALIZED_DATA DBL_MAX /* Values for representing default case for command-line options */ #define DEFAULT_DBL DBL_MAX #define DEFAULT_BOOL -1 /* Function prototypes */ static void do_math(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static char *read_expression_file(char *filename); static int get_list_option(char *dst, char *key, int argc, char **argv); /* Argument variables */ static int Output_list_size = 0; static int Output_list_alloc = 0; struct { char *symbol; char *file; } *Output_list = NULL; static int clobber = FALSE; static int verbose = TRUE; int debug = FALSE; static int is_signed = FALSE; int propagate_nan = TRUE; static int check_dim_info = TRUE; static int copy_all_header = DEFAULT_BOOL; static int use_nan_for_illegal_values = TRUE; static int max_buffer_size_in_kb = 0; static double valid_range[2] = {0.0, 0.0}; double value_for_illegal_operations = DEFAULT_DBL; static nc_type datatype = MI_ORIGINAL_TYPE; static char *filelist = NULL; static char *expr_file = NULL; char *expression = NULL; static int eval_width = 200; #if MINC2 static int minc2_format = FALSE; #endif /* MINC2 */ /* Argument table */ ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "General options:"}, #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &minc2_format, "Produce a MINC 2.0 format output file"}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-no_clobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Synonym for -noclobber."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages (default)."}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out log messages."}, {"-debug", ARGV_CONSTANT, (char *) TRUE, (char *) &debug, "Print out debugging messages."}, {"-filelist", ARGV_STRING, (char *) 1, (char *) &filelist, "Specify the name of a file containing input file names (- for stdin)."}, {"-copy_header", ARGV_CONSTANT, (char *) TRUE, (char *) ©_all_header, "Copy all of the header from the first file."}, {"-nocopy_header", ARGV_CONSTANT, (char *) FALSE, (char *) ©_all_header, "Do not copy all of the header from the first file."}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Use data type of first file (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Write out byte data."}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Write out short integer data."}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Write out 32-bit integer data."}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int."}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Write out single-precision floating-point data."}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Write out double-precision floating-point data."}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Write signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Write unsigned integer data (default if type specified)."}, {"-range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data."}, {"-max_buffer_size_in_kb", ARGV_INT, (char *) 1, (char *) &max_buffer_size_in_kb, "Specify the maximum size of the internal buffers (in kbytes)."}, {"-check_dimensions", ARGV_CONSTANT, (char *) TRUE, (char *) &check_dim_info, "Check that files have matching dimensions (default)."}, {"-nocheck_dimensions", ARGV_CONSTANT, (char *) FALSE, (char *) &check_dim_info, "Do not check that files have matching dimensions."}, {"-ignore_nan", ARGV_CONSTANT, (char *) FALSE, (char *) &propagate_nan, "Ignore invalid data (NaN) for accumulations."}, {"-propagate_nan", ARGV_CONSTANT, (char *) TRUE, (char *) &propagate_nan, "Invalid data in any file at a voxel produces a NaN (default)."}, {"-nan", ARGV_CONSTANT, (char *) TRUE, (char *) &use_nan_for_illegal_values, "Output NaN when an illegal operation is done (default)."}, {"-zero", ARGV_CONSTANT, (char *) FALSE, (char *) &use_nan_for_illegal_values, "Output zero when an illegal operation is done."}, {"-illegal_value", ARGV_FLOAT, (char *) 1, (char *) &value_for_illegal_operations, "Value to write out when an illegal operation is done."}, {"-expression", ARGV_STRING, (char*)1, (char*) &expression, "Expression to use in calculations."}, {"-expfile", ARGV_STRING, (char*)1, (char*) &expr_file, "Name of file containing expression."}, {"-outfile", ARGV_GENFUNC, (char*)get_list_option, (char*) &Output_list, "Symbol to save in an output file (2 args)."}, {"-eval_width", ARGV_INT, (char*)1, (char*) &eval_width, "Number of voxels to evaluate simultaneously."}, {NULL, ARGV_END, NULL, NULL, NULL} }; extern int yydebug; sym_t rootsym; vector_t A; scalar_t *Output_values; /* Main program */ int main(int argc, char *argv[]){ char **infiles, **outfiles; int nfiles, nout; char *arg_string; Loop_Options *loop_options; char *pname; int i; ident_t ident; scalar_t scalar; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ pname = argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) { (void) fprintf(stderr, "\nUsage: %s [options] [ ...] \n", pname); (void) fprintf(stderr, " %s -help\n\n", pname); exit(EXIT_FAILURE); } /* Get output file names */ nout = (Output_list == NULL ? 1 : Output_list_size); outfiles = malloc(nout * sizeof(*outfiles)); if (Output_list == NULL) { outfiles[0] = argv[argc-1]; } else { for (i=0; i < Output_list_size; i++) { outfiles[i] = Output_list[i].file; } } /* check for output files */ for (i=0; i < nout; i++){ if(access(outfiles[i], F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists, use -clobber to overwrite\n\n", argv[0], outfiles[i]); exit(EXIT_FAILURE); } } /* Get the list of input files either from the command line or from a file, or report an error if both are specified. Note that if -outfile is given then there is no output file name left on argv after option parsing. */ nfiles = argc - 2; if (Output_list != NULL) nfiles++; if (filelist == NULL) { infiles = &argv[1]; } else if (nfiles <= 0) { infiles = read_file_names(filelist, &nfiles); if (infiles == NULL) { (void) fprintf(stderr, "Error reading in file names from file \"%s\"\n", filelist); exit(EXIT_FAILURE); } } else { (void) fprintf(stderr, "Do not specify both -filelist and input file names\n"); exit(EXIT_FAILURE); } /* Make sure that we have something to process */ if (nfiles == 0) { (void) fprintf(stderr, "No input files specified\n"); exit(EXIT_FAILURE); } /* Get the expression from the file if needed */ if ((expression == NULL) && (expr_file == NULL)) { (void) fprintf(stderr, "An expression must be specified on the command line\n"); exit(EXIT_FAILURE); } else if (expression == NULL) { expression = read_expression_file(expr_file); } /* Parse expression argument */ if (debug) fprintf(stderr, "Feeding in expression %s\n", expression); lex_init(expression); if (debug) yydebug = 1; else yydebug = 0; yyparse(); lex_finalize(); /* Optimize the expression tree */ root = optimize(root); /* Setup the input vector from the input files */ A = new_vector(); for (i=0; i total_values) nvox = total_values - ivox; /* Copy the data into the A vector */ for (ivalue=0; ivalue < nvox; ivalue++) { for (ibuff=0; ibuff < input_num_buffers; ibuff++){ A->el[ibuff]->vals[ivalue] = input_data[ibuff][ivox+ivalue]; } } /* Some debugging */ if (debug) { (void) fprintf(stderr, "\n===New voxel===\n"); } /* Evaluate the expression */ scalar = eval_scalar((int) nvox, NULL, root, rootsym); /* Get the list of scalar values to write out */ if (Output_values == NULL) { num_output = 1; output_scalars = &scalar; } else { num_output = Output_list_size; output_scalars = Output_values; } /* Copy the scalar values into the right buffers */ for (iout=0; iout < num_output; iout++) { for (ivalue=0; ivalue < nvox; ivalue++) { output_data[iout][ivox+ivalue] = output_scalars[iout]->vals[ivalue]; } } /* Free things up */ scalar_free(scalar); if (debug) { (void) printf("Voxel result = %g\n", output_data[0][ivox]); } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_expression_file @INPUT : filename - Name of file from which to read expression @OUTPUT : (none) @RETURNS : String containing expression - must be freed by caller. @DESCRIPTION: Reads in an expression from a file. @METHOD : @GLOBALS : @CALLS : @CREATED : May 3, 2001 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static char *read_expression_file(char *filename) { struct stat statbuf; size_t size; FILE *fp; char *expression; int ichar; int beginning_of_line, in_comment; int ch; #define ALLOC_SIZE 1024 /* Set the default allocation size - zero means allocate as we go */ size = 0; /* Check for reading from stdin */ if (strcmp(filename, "-") == 0) { fp = stdin; } /* Otherwise read from file. Get allocation size from file size. */ else { /* Get the file size */ if (stat(filename, &statbuf) >= 0) { size = statbuf.st_size + 1; } /* Open the file */ if ((fp=fopen(filename, "r")) == NULL) { (void) fprintf(stderr, "Unable to open expression file \"%s\"\n", filename); exit(EXIT_FAILURE); } } /* Make sure that we are going to allocate something */ if (size == 0) size = ALLOC_SIZE; /* Get space */ expression = malloc(size * sizeof(*expression)); /* Read the expression */ ichar = 0; beginning_of_line = TRUE; in_comment = FALSE; while ((ch = getc(fp)) != EOF) { /* Check for newline to end comments */ if (ch == '\n') { beginning_of_line = TRUE; in_comment = FALSE; } /* Check for comment character as first non-whitespace char of line */ else if (beginning_of_line && (ch == '#')) { in_comment = TRUE; beginning_of_line = FALSE; } /* Check for first non-whitespace char of line */ else if (!isspace(ch)) { beginning_of_line = FALSE; } /* If not in a comment, then save the character */ if (!in_comment) { /* Check whether we need more space */ if (ichar >= size-1) { size += ALLOC_SIZE; expression = realloc(expression, size * sizeof(expression)); } /* Save the character */ expression[ichar] = (char) ch; ichar++; } } expression[ichar] = '\0'; /* Close the file */ if (fp != stdin) { (void) fclose(fp); } /* Return the expression */ return expression; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_list_option @INPUT : dst - client data passed by ParseArgv key - matching key in argv argc - number of arguments passed in argv - argument list @OUTPUT : (none) @RETURNS : Number of arguments left in argv list. @DESCRIPTION: Gets arguments from the command line and appends them to a list, chosen based on key. @METHOD : @GLOBALS : @CALLS : @CREATED : May 3, 2001 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_list_option(char *dst, char *key, int argc, char **argv) /* ARGSUSED */ { enum {OPT_OUTPUT_SYMBOL} option_type; void **list; size_t entry_size; int *list_size, *list_alloc, index; int num_args, iarg; /* Check the key */ list = (void **) dst; if (strcmp(key, "-outfile") == 0) { option_type = OPT_OUTPUT_SYMBOL; list_size = &Output_list_size; list_alloc = &Output_list_alloc; entry_size = sizeof(Output_list[0]); num_args = 2; } else { (void) fprintf(stderr, "Internal error - unrecognized key in get_list_option\n"); exit(EXIT_FAILURE); } /* Check for following arguments */ if (argc < num_args) { (void) fprintf(stderr, "\"%s\" option requires %d additional arguments\n", key, num_args); exit(EXIT_FAILURE); } /* Get more space */ (*list_size)++; if (*list_size > *list_alloc) { *list_alloc += 10; if (*list == NULL) { *list = malloc(*list_alloc * entry_size); } else { *list = realloc(*list, *list_alloc * entry_size); } } index = *list_size - 1; /* Save the values */ if (option_type == OPT_OUTPUT_SYMBOL) { Output_list[index].symbol = argv[0]; Output_list[index].file = argv[1]; } /* Modify the argument list */ if (num_args > 0) { for (iarg=0; iarg < (argc - num_args); iarg++) { argv[iarg] = argv[iarg + num_args]; } } return argc - num_args; } minc-2.2.00/progs/minccalc/gram.y0000644000265600003100000002671212027132662013473 00000000000000%{ #include #include #include #include #include #include "node.h" #define INVALID_VALUE (-DBL_MAX) /* Avoid problems with conflicting declarations */ void yyerror(const char *msg); %} %union{ int pos; node_t node; double real; ident_t ident; } %token NAN %token IN TO IDENT REAL AVG PROD SUM LET NEG LEN MAX MIN IMAX IMIN %token ISNAN SQRT ABS EXP LOG SIN COS TAN ASIN ACOS ATAN CLAMP SEGMENT %token LT LE GT GE EQ NE NOT AND OR %token IF ELSE FOR %type IDENT %type REAL %type IN TO AVG SUM PROD LET NEG LEN IF ELSE FOR %type ISNAN SQRT ABS MAX MIN IMAX IMIN EXP LOG SIN COS TAN ASIN ACOS ATAN %type CLAMP SEGMENT %type NOT LT LE GT GE EQ NE AND OR %type '+' '-' '*' '/' '(' ')' '[' ']' '.' '=' '^' '{' '}' ',' '|' ';' %type ':' '?' %type exprlist expr letexpr vector %right '=' %right LET %right '?' %left OR %left AND %left EQ NE %left LT LE GT GE %left '-' '+' %left '*' '/' %right NEG NOT %right '^' %right AVG SUM PROD LEN ISNAN SQRT ABS MAX MIN IMAX IMIN EXP LOG SIN COS TAN ASIN ACOS ATAN %% top : exprlist { root = $1; } ; exprlist : expr ';' exprlist { $$ = new_node(2, node_is_scalar($3)); $$->type = NODETYPE_EXPRLIST; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr ';' { $$ = $1; } | expr { $$ = $1; } ; expr : '(' expr ')' { $$ = $2; } | '{' exprlist '}' { $$ = $2; } | '[' vector ']' { $$ = $2; } | '{' IDENT IN expr '|' expr '}' { $$ = new_vector_node(2); $$->type = NODETYPE_GEN; $$->pos = $7; $$->ident = $2; $$->expr[0] = $4; $$->expr[1] = $6; } | '(' expr ':' expr ')' { $$ = new_vector_node(2); $$->type = NODETYPE_RANGE; $$->flags = 0; $$->pos = $5; $$->expr[0] = $2; $$->expr[1] = $4; } | '(' expr ':' expr ']' { $$ = new_vector_node(2); $$->type = NODETYPE_RANGE; $$->flags = RANGE_EXACT_UPPER; $$->pos = $5; $$->expr[0] = $2; $$->expr[1] = $4; } | '[' expr ':' expr ')' { $$ = new_vector_node(2); $$->type = NODETYPE_RANGE; $$->flags = RANGE_EXACT_LOWER; $$->pos = $5; $$->expr[0] = $2; $$->expr[1] = $4; } | '[' expr ':' expr ']' { $$ = new_vector_node(2); $$->type = NODETYPE_RANGE; $$->flags = RANGE_EXACT_UPPER | RANGE_EXACT_LOWER; $$->pos = $5; $$->expr[0] = $2; $$->expr[1] = $4; } | expr '+' expr { $$ = new_scalar_node(2); $$->type = NODETYPE_ADD; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr '-' expr { $$ = new_scalar_node(2); $$->type = NODETYPE_SUB; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | '-' expr %prec NEG { $$ = new_scalar_node(2); $$->type = NODETYPE_SUB; $$->pos = $1; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = new_scalar_node(0); $$->expr[0]->type = NODETYPE_REAL; $$->expr[0]->real = 0.0; $$->expr[1] = $2; } | expr '*' expr { $$ = new_scalar_node(2); $$->pos = $2; $$->type = NODETYPE_MUL; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $1; $$->expr[1] = $3; } | expr '/' expr { $$ = new_scalar_node(2); $$->pos = $2; $$->type = NODETYPE_DIV; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $1; $$->expr[1] = $3; } | expr '^' expr { $$ = new_scalar_node(2); $$->pos = $2; $$->type = NODETYPE_POW; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $1; $$->expr[1] = $3; } | expr LT expr { $$ = new_scalar_node(2); $$->type = NODETYPE_LT; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr LE expr { $$ = new_scalar_node(2); $$->type = NODETYPE_LE; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr GT expr { $$ = new_scalar_node(2); $$->type = NODETYPE_GT; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr GE expr { $$ = new_scalar_node(2); $$->type = NODETYPE_GE; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr EQ expr { $$ = new_scalar_node(2); $$->type = NODETYPE_EQ; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr NE expr { $$ = new_scalar_node(2); $$->type = NODETYPE_NE; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr AND expr { $$ = new_scalar_node(2); $$->type = NODETYPE_AND; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr OR expr { $$ = new_scalar_node(2); $$->type = NODETYPE_OR; $$->flags |= ALLARGS_SCALAR; $$->pos = $2; $$->expr[0] = $1; $$->expr[1] = $3; } | expr '[' expr ']' { $$ = new_scalar_node(2); $$->type = NODETYPE_INDEX; $$->pos = $4; $$->expr[0] = $1; $$->expr[1] = $3; } | IDENT '=' expr { $$ = new_node(1, node_is_scalar($3)); $$->type = NODETYPE_ASSIGN; $$->pos = $2; $$->ident = $1; $$->expr[0] = $3; } | LET letexpr { $$ = $2; } | NOT expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_NOT; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | SUM expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_SUM; $$->expr[0] = $2; } | PROD expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_PROD; $$->expr[0] = $2; } | AVG expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_AVG; $$->expr[0] = $2; } | LEN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_LEN; $$->expr[0] = $2; } | MAX expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_MAX; $$->expr[0] = $2; } | MIN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_MIN; $$->expr[0] = $2; } | IMAX expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_IMAX; $$->expr[0] = $2; } | IMIN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_IMIN; $$->expr[0] = $2; } | ISNAN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_ISNAN; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | SQRT expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_SQRT; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | ABS expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_ABS; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | EXP expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_EXP; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | LOG expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_LOG; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | SIN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_SIN; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | COS expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_COS; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | TAN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_TAN; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | ASIN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_ASIN; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | ACOS expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_ACOS; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | ATAN expr { $$ = new_scalar_node(1); $$->pos = $1; $$->type = NODETYPE_ATAN; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $2; } | CLAMP '(' expr ',' expr ',' expr ')' { $$ = new_scalar_node(3); $$->pos = $1; $$->type = NODETYPE_CLAMP; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $3; $$->expr[1] = $5; $$->expr[2] = $7; } | SEGMENT '(' expr ',' expr ',' expr ')' { $$ = new_scalar_node(3); $$->pos = $1; $$->type = NODETYPE_SEGMENT; $$->flags |= ALLARGS_SCALAR; $$->expr[0] = $3; $$->expr[1] = $5; $$->expr[2] = $7; } | expr '?' expr ':' expr { $$ = new_node(3, node_is_scalar($3)); $$->pos = $2; $$->type = NODETYPE_IFELSE; $$->expr[0] = $1; $$->expr[1] = $3; $$->expr[2] = $5; } | IF '(' expr ')' expr ELSE expr { $$ = new_node(3, node_is_scalar($5)); $$->pos = $1; $$->type = NODETYPE_IFELSE; $$->expr[0] = $3; $$->expr[1] = $5; $$->expr[2] = $7; } | IF '(' expr ')' expr { $$ = new_node(2, node_is_scalar($5)); $$->pos = $1; $$->type = NODETYPE_IFELSE; $$->expr[0] = $3; $$->expr[1] = $5; } | FOR '{' IDENT IN expr '}' expr { $$ = new_scalar_node(2); $$->pos = $1; $$->type = NODETYPE_FOR; $$->ident = $3; $$->expr[0] = $5; $$->expr[1] = $7; } | IDENT { $$ = new_node(0, ident_is_scalar($1)); $$->type = NODETYPE_IDENT; $$->pos = -1; $$->ident = $1; } | REAL { $$ = new_scalar_node(0); $$->pos = -1; $$->type = NODETYPE_REAL; $$->real = $1; } | NAN { $$ = new_scalar_node(0); $$->pos = -1; $$->type = NODETYPE_REAL; $$->real = INVALID_VALUE; } ; letexpr : IDENT '=' expr ',' letexpr { $$ = new_scalar_node(2); $$->type = NODETYPE_LET; $$->pos = $2; $$->ident = $1; $$->expr[0] = $3; $$->expr[1] = $5; } | IDENT '=' expr IN expr { $$ = new_scalar_node(2); $$->pos = $2; $$->type = NODETYPE_LET; $$->ident = $1; $$->expr[0] = $3; $$->expr[1] = $5; } ; vector : expr { $$ = new_vector_node(1); $$->pos = $1->pos; $$->type = NODETYPE_VEC1; $$->expr[0] = $1; } | vector ',' expr { $$ = new_vector_node(2); $$->pos = $2; $$->type = NODETYPE_VEC2; $$->expr[0] = $1; $$->expr[1] = $3; } ; %% node_t root; void yyerror(msg) const char *msg; { extern int lexpos; show_error(lexpos, msg); } minc-2.2.00/progs/minccalc/eval.c0000644000265600003100000006166612027132662013455 00000000000000/* Copyright David Leonard & Andrew Janke, 2000. All rights reserved. */ #include #include #include #include #include #include "node.h" #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #define INVALID_VALUE -DBL_MAX scalar_t eval_index(int, int *, node_t, vector_t, scalar_t); scalar_t eval_sum(int, int *, node_t, vector_t); scalar_t eval_prod(int, int *, node_t, vector_t); scalar_t eval_max(int, int *, node_t, vector_t, double, int); vector_t eval_vector(int, int *, node_t, sym_t); vector_t gen_vector(int, int *, node_t, sym_t); vector_t gen_range(int, int *, node_t, sym_t); scalar_t for_loop(int, int *, node_t n, sym_t sym); extern int debug; extern int propagate_nan; extern double value_for_illegal_operations; void eval_error(node_t n, const char *msg){ int pos = n->pos; show_error(pos, msg); } void show_error(int pos, const char *msg){ extern const char *expression; const char *c; int thisline, ichar, linenum; if (pos != -1) { thisline = 0; linenum=1; for (ichar=0; ichar < pos; ichar++) { if (expression[ichar] == '\n') { thisline = ichar+1; linenum++; } } pos -= thisline; fprintf(stderr, "\nLine %d:\n", linenum); for (c = &expression[thisline]; *c && *c != '\n'; c++) { (void) putc((int) *c, stderr); } (void) putc((int) '\n', stderr); for (c = &expression[thisline]; *c; c++) { if (pos-- == 0) break; if (*c == '\t') fprintf(stderr, "\t"); else fprintf(stderr, " "); } fprintf(stderr, "^\n"); } fprintf(stderr, "%s\n", msg); exit(1); } /* Try to evaluate an expression in a scalar context */ scalar_t eval_scalar(int width, int *eval_flags, node_t n, sym_t sym){ vector_t v; scalar_t s, s2, result; scalar_t args[3]; double vals[3]; int *eval_flags2, *isnan_flags; int found_invalid, all_true, all_false; int iarg, ivalue; /* Check that node is of correct type */ if (!node_is_scalar(n)) { eval_error(n, "Expression is not a scalar"); } /* Check special case where all arguments are scalar and we can test for invalid values in a general way */ if (n->flags & ALLARGS_SCALAR) { /* Check that we don't have too many arguments */ if (n->numargs > (int) sizeof(args)/sizeof(args[0])) { eval_error(n, "Internal error: too many arguments"); } /* Evaluate each argument and save the result. */ for (iarg=0; iarg < n->numargs; iarg++) { args[iarg] = eval_scalar(width, eval_flags, n->expr[iarg], sym); } /* Set up the result scalar. We re-use the first argument if no one else is using it. */ if (n->numargs > 0 && args[0]->refcnt == 1) { result = args[0]; scalar_incr_ref(result); } else { result = new_scalar(width); } /* Loop over all values in scalar */ for (ivalue=0; ivalue < width; ivalue++) { /* Check the eval flag */ if (eval_flags != NULL && !eval_flags[ivalue]) continue; /* Get the values, checking for invalid values. */ found_invalid = FALSE; for (iarg=0; iarg < n->numargs; iarg++) { vals[iarg] = args[iarg]->vals[ivalue]; if (vals[iarg] == INVALID_VALUE) { found_invalid = TRUE; } } /* Debug */ if (debug) { (void) fprintf(stderr, "scalar %s:", node_name(n)); for (iarg=0; iarg < n->numargs; iarg++) (void) fprintf(stderr, " %g", vals[iarg]); (void) fprintf(stderr, "\n"); } /* Check for an invalid value. If we are testing for them, return 1.0, otherwise return an invalid value. */ if (found_invalid) { result->vals[ivalue] = ( (n->type == NODETYPE_ISNAN) ? 1.0 : INVALID_VALUE ); continue; } /* Do the operation */ switch (n->type) { case NODETYPE_ADD: result->vals[ivalue] = vals[0] + vals[1]; break; case NODETYPE_SUB: result->vals[ivalue] = vals[0] - vals[1]; break; case NODETYPE_MUL: result->vals[ivalue] = vals[0] * vals[1]; break; case NODETYPE_DIV: if (vals[1] == 0.0) result->vals[ivalue] = value_for_illegal_operations; else result->vals[ivalue] = vals[0] / vals[1]; break; case NODETYPE_LT: result->vals[ivalue] = vals[0] < vals[1]; break; case NODETYPE_LE: result->vals[ivalue] = vals[0] <= vals[1]; break; case NODETYPE_GT: result->vals[ivalue] = vals[0] > vals[1]; break; case NODETYPE_GE: result->vals[ivalue] = vals[0] >= vals[1]; break; case NODETYPE_EQ: result->vals[ivalue] = vals[0] == vals[1]; break; case NODETYPE_NE: result->vals[ivalue] = vals[0] != vals[1]; break; case NODETYPE_NOT: result->vals[ivalue] = (vals[0] == 0.0); break; case NODETYPE_AND: result->vals[ivalue] = (vals[0] != 0.0) && (vals[1] != 0.0); break; case NODETYPE_OR: result->vals[ivalue] = (vals[0] != 0.0) || (vals[1] != 0.0); break; case NODETYPE_ISNAN: /* We only get here if the value is valid */ result->vals[ivalue] = 0.0; break; case NODETYPE_POW: result->vals[ivalue] = pow(vals[0], vals[1]); break; case NODETYPE_SQRT: if (vals[0] < 0.0) result->vals[ivalue] = value_for_illegal_operations; else result->vals[ivalue] = sqrt(vals[0]); break; case NODETYPE_ABS: result->vals[ivalue] = fabs(vals[0]); break; case NODETYPE_EXP: result->vals[ivalue] = exp(vals[0]); break; case NODETYPE_LOG: if (vals[0] <= 0.0) result->vals[ivalue] = value_for_illegal_operations; else result->vals[ivalue] = log(vals[0]); break; case NODETYPE_SIN: result->vals[ivalue] = sin(vals[0]); break; case NODETYPE_COS: result->vals[ivalue] = cos(vals[0]); break; case NODETYPE_TAN: result->vals[ivalue] = tan(vals[0]); break; case NODETYPE_ASIN: result->vals[ivalue] = asin(vals[0]); break; case NODETYPE_ACOS: result->vals[ivalue] = acos(vals[0]); break; case NODETYPE_ATAN: result->vals[ivalue] = atan(vals[0]); break; case NODETYPE_CLAMP: if (vals[0] < vals[1]) result->vals[ivalue] = vals[1]; else if (vals[0] > vals[2]) result->vals[ivalue] = vals[2]; else result->vals[ivalue] = vals[0]; break; case NODETYPE_SEGMENT: result->vals[ivalue] = ( (vals[0] >= vals[1] && vals[0] <= vals[2]) ? 1.0 : 0.0); break; } /* switch on type */ } /* Loop over values of scalar */ /* Free the intermediate results */ for (iarg=0; iarg < n->numargs; iarg++) { scalar_free(args[iarg]); } /* Return the result vector */ return result; } /* If all args are scalar */ /* If we get here then we are not doing a simple scalar operation and we have to handle invalid values on a case-by-case basis. */ switch (n->type) { case NODETYPE_EXPRLIST: if (node_is_scalar(n->expr[0])) { s = eval_scalar(width, eval_flags, n->expr[0], sym); scalar_free(s); } else { v = eval_vector(width, eval_flags, n->expr[0], sym); vector_free(v); } return eval_scalar(width, eval_flags, n->expr[1], sym); case NODETYPE_INDEX: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_scalar(width, eval_flags, n->expr[1], sym); result = eval_index(width, eval_flags, n, v, s); vector_free(v); scalar_free(s); return result; case NODETYPE_SUM: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_sum(width, eval_flags, n, v); vector_free(v); return s; case NODETYPE_PROD: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_prod(width, eval_flags, n, v); vector_free(v); return s; case NODETYPE_AVG: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_sum(width, eval_flags, n, v); for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; if (s->vals[ivalue] != INVALID_VALUE) s->vals[ivalue] /= (double) v->len; } vector_free(v); return s; case NODETYPE_LEN: v = eval_vector(width, eval_flags, n->expr[0], sym); s = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; s->vals[ivalue] = (double) v->len; } if (debug) { (void) fprintf(stderr, "len : %d\n", v->len); } vector_free(v); return s; case NODETYPE_MAX: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_max(width, eval_flags, n, v, 1.0, 0); vector_free(v); return s; case NODETYPE_MIN: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_max(width, eval_flags, n, v, -1.0, 0); vector_free(v); return s; case NODETYPE_IMAX: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_max(width, eval_flags, n, v, 1.0, 1); vector_free(v); return s; case NODETYPE_IMIN: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_max(width, eval_flags, n, v, -1.0, 1); vector_free(v); return s; case NODETYPE_FOR: return for_loop(width, eval_flags, n, sym); case NODETYPE_IDENT: s = sym_lookup_scalar(n->ident, sym); if (s) { scalar_incr_ref(s); } return s; case NODETYPE_REAL: s = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) { s->vals[ivalue] = n->real; } return s; case NODETYPE_ASSIGN: s = eval_scalar(width, eval_flags, n->expr[0], sym); sym_set_scalar(width, eval_flags, s, n->ident, sym); return s; case NODETYPE_LET: if (ident_is_scalar(n->ident)) { s = eval_scalar(width, eval_flags, n->expr[0], sym); sym_set_scalar(width, eval_flags, s, n->ident, sym); scalar_free(s); } else { v = eval_vector(width, eval_flags, n->expr[0], sym); sym_set_vector(width, eval_flags, v, n->ident, sym); vector_free(v); } s = eval_scalar(width, eval_flags, n->expr[1], sym); return s; case NODETYPE_IFELSE: /* Do the test */ s = eval_scalar(width, eval_flags, n->expr[0], sym); /* Set the eval flags based on the results. Keep track of invalid data in the expression - we will not evaluate either part in that case. */ eval_flags2 = malloc(sizeof(eval_flags[0]) * width); isnan_flags = malloc(sizeof(eval_flags[0]) * width); all_true = TRUE; all_false = TRUE; for (ivalue=0; ivalue < width; ivalue++) { isnan_flags[ivalue] = (s->vals[ivalue] == INVALID_VALUE); eval_flags2[ivalue] = ((eval_flags == NULL ? 1 : eval_flags[ivalue]) && (s->vals[ivalue] != 0.0) && (!isnan_flags[ivalue])); if (eval_flags2[ivalue]) all_false = FALSE; else all_true = FALSE; } scalar_free(s); if (all_true || all_false) { free(eval_flags2); eval_flags2 = NULL; } /* Evaluate the then part */ s = NULL; if (!all_false) { s = eval_scalar(width, eval_flags2, n->expr[1], sym); } /* Evaluate the else part if needed - remember to invert the flags */ s2 = NULL; if (!all_true && n->numargs > 2) { if (eval_flags2 != NULL) { for (ivalue=0; ivalue < width; ivalue++) eval_flags2[ivalue] = !eval_flags2[ivalue] && !isnan_flags[ivalue]; } s2 = eval_scalar(width, eval_flags2, n->expr[2], sym); if (eval_flags2 != NULL) { for (ivalue=0; ivalue < width; ivalue++) eval_flags2[ivalue] = !eval_flags2[ivalue] && !isnan_flags[ivalue]; } } /* Make sure that we have an answer */ if (s == NULL) { if (s2 != NULL) { s = s2; s2 = NULL; } else { s = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) s->vals[ivalue] = 0.0; } } /* Merge the results */ if (eval_flags2 != NULL) { for (ivalue=0; ivalue < width; ivalue++) { if (!eval_flags2[ivalue]) { s->vals[ivalue] = (n->numargs > 2 ? s2->vals[ivalue] : 0.0); } } } /* Mark appropriate invalid values */ for (ivalue=0; ivalue < width; ivalue++) { if (isnan_flags[ivalue]) { s->vals[ivalue] = value_for_illegal_operations; } } /* Free things and return */ if (s2 != NULL) scalar_free(s2); if (eval_flags2 != NULL) free(eval_flags2); if (isnan_flags != NULL) free(isnan_flags); return s; default: eval_error(n, "expected a scalar value"); /* NOTREACHED */ return 0; } } /* Index into a vector */ scalar_t eval_index(int width, int *eval_flags, node_t n, vector_t v, scalar_t i){ scalar_t s; int idx; int ivalue; s = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; idx = SCALAR_ROUND(i->vals[ivalue]); if (idx < 0 || idx >= v->len) eval_error(n, "index out of bounds"); s->vals[ivalue] = v->el[idx]->vals[ivalue]; if (debug) (void) fprintf(stderr, "Index [%d] = %g\n", idx, s->vals[ivalue]); } return s; } /* Perform a sum over the arguments */ scalar_t eval_sum(int width, int *eval_flags, node_t n, vector_t v) { int i, ivalue; scalar_t result; double value; int found_invalid, found_valid; result = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; result->vals[ivalue] = 0.0; found_invalid = found_valid = FALSE; for (i = 0; i < v->len; i++) { value = v->el[i]->vals[ivalue]; if (value == INVALID_VALUE) found_invalid = TRUE; else { result->vals[ivalue] += value; found_valid = TRUE; } } if ((found_invalid && propagate_nan) || !found_valid) { result->vals[ivalue] = value_for_illegal_operations; } } return result; } /* Perform a product over the arguments */ scalar_t eval_prod(int width, int *eval_flags, node_t n, vector_t v) { int i, ivalue; scalar_t result; double value; int found_invalid, found_valid; result = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; result->vals[ivalue] = 1.0; found_invalid = found_valid = FALSE; for (i = 0; i < v->len; i++) { value = v->el[i]->vals[ivalue]; if (value == INVALID_VALUE) found_invalid = TRUE; else { result->vals[ivalue] *= value; found_valid = TRUE; } } if ((found_invalid && propagate_nan) || !found_valid) { result->vals[ivalue] = value_for_illegal_operations; } } return result; } /* Find the maximum of a vector. Sign should be +1.0 for maxima search and -1.0 for minima search. type should be 0 for value and 1 for index */ scalar_t eval_max(int width, int *eval_flags, node_t n, vector_t v, double sign, int type) { int i, ivalue; scalar_t result; double value, max, idx; result = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; result->vals[ivalue] = max = INVALID_VALUE; for (i = 0; i < v->len; i++) { value = v->el[i]->vals[ivalue]; if (value != INVALID_VALUE) { if (max == INVALID_VALUE || (sign*(value-max) > 0.0)) { max = value; idx = (double)i; } } } result->vals[ivalue] = (type == 0) ? max : idx; } return result; } /* Evaluate an expression in a vector context */ vector_t eval_vector(int width, int *eval_flags, node_t n, sym_t sym){ vector_t v, v2; scalar_t s; int ivalue, iel; int *eval_flags2, *isnan_flags; int all_true, all_false; /* Check that node is of correct type */ if (node_is_scalar(n)) { eval_error(n, "Expression is not a vector"); } switch (n->type) { case NODETYPE_EXPRLIST: if (node_is_scalar(n->expr[0])) { s = eval_scalar(width, eval_flags, n->expr[0], sym); scalar_free(s); } else { v = eval_vector(width, eval_flags, n->expr[0], sym); vector_free(v); } return eval_vector(width, eval_flags, n->expr[1], sym); case NODETYPE_ASSIGN: v = eval_vector(width, eval_flags, n->expr[0], sym); sym_set_vector(width, eval_flags, v, n->ident, sym); return v; case NODETYPE_LET: if (ident_is_scalar(n->ident)) { s = eval_scalar(width, eval_flags, n->expr[0], sym); sym_set_scalar(width, eval_flags, s, n->ident, sym); scalar_free(s); } else { v = eval_vector(width, eval_flags, n->expr[0], sym); sym_set_vector(width, eval_flags, v, n->ident, sym); vector_free(v); } v = eval_vector(width, eval_flags, n->expr[1], sym); return v; case NODETYPE_VEC2: v = eval_vector(width, eval_flags, n->expr[0], sym); s = eval_scalar(width, eval_flags, n->expr[1], sym); vector_append(v, s); scalar_free(s); return v; case NODETYPE_VEC1: s = eval_scalar(width, eval_flags, n->expr[0], sym); v = new_vector(); vector_append(v, s); scalar_free(s); return v; case NODETYPE_GEN: return gen_vector(width, eval_flags, n, sym); case NODETYPE_RANGE: return gen_range(width, eval_flags, n, sym); case NODETYPE_IFELSE: /* Do the test */ s = eval_scalar(width, eval_flags, n->expr[0], sym); /* Set the eval flags based on the results */ eval_flags2 = malloc(sizeof(eval_flags[0]) * width); isnan_flags = malloc(sizeof(eval_flags[0]) * width); all_true = TRUE; all_false = TRUE; for (ivalue=0; ivalue < width; ivalue++) { isnan_flags[ivalue] = (s->vals[ivalue] == INVALID_VALUE); eval_flags2[ivalue] = ((eval_flags == NULL ? 1 : eval_flags[ivalue]) && (s->vals[ivalue] != 0.0) && (!isnan_flags[ivalue])); if (eval_flags2[ivalue]) all_false = FALSE; else all_true = FALSE; } scalar_free(s); if (all_true || all_false) { free(eval_flags2); eval_flags2 = NULL; } /* Evaluate the then part */ v = NULL; if (!all_false) { v = eval_vector(width, eval_flags2, n->expr[1], sym); } /* Evaluate the else part if needed - remember to invert the flags */ v2 = NULL; if (!all_true && n->numargs > 2) { if (eval_flags2 != NULL) { for (ivalue=0; ivalue < width; ivalue++) eval_flags2[ivalue] = !eval_flags2[ivalue] && !isnan_flags[ivalue]; } v2 = eval_vector(width, eval_flags2, n->expr[2], sym); if (eval_flags2 != NULL) { for (ivalue=0; ivalue < width; ivalue++) eval_flags2[ivalue] = !eval_flags2[ivalue] && !isnan_flags[ivalue]; } } /* Make sure that we have an answer */ if (v == NULL) { if (v2 != NULL) { v = v2; v2 = NULL; } else { v = new_vector(); } } /* Merge the results */ if (v2 != NULL && v->len != v2->len) { eval_error(n, "Vector expressions in if-else do not have the same length"); } if (eval_flags2 != NULL) { for (ivalue=0; ivalue < width; ivalue++) { if (!eval_flags2[ivalue]) { for (iel=0; iel < v->len; iel++) { v->el[iel]->vals[ivalue] = (n->numargs > 2 ? v2->el[iel]->vals[ivalue] : 0.0); } } } } /* Mark appropriate invalid values */ for (ivalue=0; ivalue < width; ivalue++) { if (isnan_flags[ivalue]) { for (iel=0; iel < v->len; iel++) { v->el[iel]->vals[ivalue] = value_for_illegal_operations; } } } /* Free things and return */ if (v2 != NULL) vector_free(v2); if (eval_flags2 != NULL) free(eval_flags2); if (isnan_flags != NULL) free(isnan_flags); return v; case NODETYPE_IDENT: v = sym_lookup_vector(n->ident, sym); if (v) { vector_incr_ref(v); return v; } /* fallthrough */ default: /* XXX coerce scalar to vector! */ v = new_vector(); s = eval_scalar(width, eval_flags, n, sym); vector_append(v, s); scalar_free(s); return v; } } /* Generate a vector */ vector_t gen_vector(int width, int *eval_flags, node_t n, sym_t sym){ int i; scalar_t value; ident_t ident; node_t expr; vector_t v; vector_t els; ident = n->ident; if (!ident_is_scalar(ident)) eval_error(n, "expected scalar (lowercase) index as 1st arg"); els = eval_vector(width, eval_flags, n->expr[0], sym); expr = n->expr[1]; v = new_vector(); for (i = 0; i < els->len; i++) { value = els->el[i]; scalar_incr_ref(value); sym_set_scalar(width, eval_flags, value, ident, sym); scalar_free(value); value = eval_scalar(width, eval_flags, expr, sym); vector_append(v, value); scalar_free(value); } vector_free(els); return v; } /* Implement a for loop */ scalar_t for_loop(int width, int *eval_flags, node_t n, sym_t sym){ int i, ivalue; scalar_t value; ident_t ident; node_t expr; vector_t els; ident = n->ident; if (!ident_is_scalar(ident)) eval_error(n, "expected scalar (lowercase) index as 1st arg"); els = eval_vector(width, eval_flags, n->expr[0], sym); expr = n->expr[1]; for (i = 0; i < els->len; i++) { if (debug) { (void) fprintf(stderr, "For loop iteration %d\n", i); } value = els->el[i]; scalar_incr_ref(value); sym_set_scalar(width, eval_flags, value, ident, sym); scalar_free(value); value = eval_scalar(width, eval_flags, expr, sym); scalar_free(value); } vector_free(els); value = new_scalar(width); for (ivalue=0; ivalue < width; ivalue++) { value->vals[ivalue] = (double) i; } return value; } vector_t gen_range(int width, int *eval_flags, node_t n, sym_t sym){ int i, ivalue; scalar_t start; scalar_t stop; vector_t v; int length; v = new_vector(); start = eval_scalar(width, eval_flags, n->expr[0], sym); stop = eval_scalar(width, eval_flags, n->expr[1], sym); for (ivalue = 0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; start->vals[ivalue] = SCALAR_ROUND(start->vals[ivalue]); stop->vals[ivalue] = SCALAR_ROUND(stop->vals[ivalue]); if (!(n->flags & RANGE_EXACT_LOWER)) start->vals[ivalue]++; if (!(n->flags & RANGE_EXACT_UPPER)) stop->vals[ivalue]--; if (ivalue == 0) { length = stop->vals[ivalue] - start->vals[ivalue]; } else if (length != (int) (stop->vals[ivalue] - start->vals[ivalue])) { eval_error(n, "Vectors must have same size in vector generator"); } } length++; scalar_free(stop); for (i = 0; i < length ; i++) { stop = new_scalar(width); for (ivalue = 0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; stop->vals[ivalue] = start->vals[ivalue] + i; if (debug) { (void) fprintf(stderr, "Range %d -> %d\n", i, (int) stop->vals[ivalue]); } } vector_append(v, stop); scalar_free(stop); } scalar_free(start); return v; } minc-2.2.00/progs/minccalc/ident.c0000644000265600003100000000237712027132662013623 00000000000000/* Copyright David Leonard & Andrew Janke, 2000. All rights reserved. */ #define _GNU_SOURCE 1 #include #include #include #include #include "node.h" struct intern { const char *s; int id; struct intern *next; int is_scalar; }; static struct intern *head = NULL; static ident_t nextid = 0; ident_t new_ident(const char *s){ struct intern *i; for (i = head; i; i = i->next) if (strcmp(i->s, s) == 0) return i->id; i = malloc(sizeof *i); i->id = nextid++; i->s = strdup(s); i->next = head; i->is_scalar = islower(s[0]); head = i; return i->id; } const char *ident_str(ident_t id){ struct intern *i; for (i = head; i; i = i->next) if (i->id == id) return i->s; return "?"; } int ident_is_scalar(ident_t id){ struct intern *i; for (i = head; i; i = i->next) if (i->id == id) return i->is_scalar; /* errx(1, "ident_is_scalar: no such ident %d", id); */ fprintf(stderr, "ident_is_scalar: no such ident %d\n", id); exit(1); return 0; } ident_t ident_lookup(char *string) { struct intern *i; for (i = head; i; i = i->next) { if (strcmp(i->s, string) == 0) { return i->id; } } return -1; } minc-2.2.00/progs/minccalc/lex.l0000644000265600003100000000407312027132662013314 00000000000000%{ #include #include "node.h" #include "gram.h" int lexpos = 0; #define setpos() yylval.pos = lexpos; lexpos += yyleng %} %% avg setpos(); return AVG; sum setpos(); return SUM; prod setpos(); return PROD; let setpos(); return LET; len setpos(); return LEN; isnan setpos(); return ISNAN; sqrt setpos(); return SQRT; abs setpos(); return ABS; max setpos(); return MAX; min setpos(); return MIN; imax setpos(); return IMAX; imin setpos(); return IMIN; exp setpos(); return EXP; log setpos(); return LOG; sin setpos(); return SIN; cos setpos(); return COS; tan setpos(); return TAN; asin setpos(); return ASIN; acos setpos(); return ACOS; atan setpos(); return ATAN; clamp setpos(); return CLAMP; segment setpos(); return SEGMENT; in setpos(); return IN; to setpos(); return TO; if setpos(); return IF; else setpos(); return ELSE; for setpos(); return FOR; NaN setpos(); return NAN; \< setpos(); return LT; \<= setpos(); return LE; \> setpos(); return GT; \>= setpos(); return GE; == setpos(); return EQ; \!= setpos(); return NE; \! setpos(); return NOT; && setpos(); return AND; \|\| setpos(); return OR; [a-zA-Z][_a-zA-Z0-9]* { setpos(); yylval.ident = new_ident(yytext); return IDENT; } [0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)? { setpos(); yylval.real = atof(yytext);; return REAL; } [ \t\n\f]+ setpos(); . setpos(); return yytext[0]; %% static YY_BUFFER_STATE lex_state; void lex_init(const char *s){ lex_state = yy_scan_string(s); } void lex_finalize(){ yy_delete_buffer(lex_state); } int yywrap(){ return 1; } minc-2.2.00/progs/minccalc/node.c0000644000265600003100000000511512027132662013436 00000000000000/* Copyright David Leonard and Andrew Janke, 2000. All rights reserved. */ #include #include "node.h" struct nodename { enum nodetype type; const char *name; } nodenames[] = { { NODETYPE_ADD, "add" }, { NODETYPE_SUB, "sub" }, { NODETYPE_MUL, "mul" }, { NODETYPE_DIV, "div" }, { NODETYPE_POW, "pow" }, { NODETYPE_INDEX, "index" }, { NODETYPE_SUM, "sum" }, { NODETYPE_PROD, "prod" }, { NODETYPE_AVG, "avg" }, { NODETYPE_LEN, "len" }, { NODETYPE_MAX, "max" }, { NODETYPE_MIN, "min" }, { NODETYPE_IMAX, "imax" }, { NODETYPE_IMIN, "imin" }, { NODETYPE_IDENT, "ident" }, { NODETYPE_REAL, "real" }, { NODETYPE_LET, "let" }, { NODETYPE_VEC1, "vec1" }, { NODETYPE_VEC2, "vec2" }, { NODETYPE_GEN, "gen" }, { NODETYPE_RANGE, "range" }, { NODETYPE_LT, "lt" }, { NODETYPE_LE, "le" }, { NODETYPE_GT, "gt" }, { NODETYPE_GE, "ge" }, { NODETYPE_EQ, "eq" }, { NODETYPE_NE, "ne" }, { NODETYPE_NOT, "not" }, { NODETYPE_AND, "and" }, { NODETYPE_OR, "or" }, { NODETYPE_ISNAN, "isnan" }, { NODETYPE_SQRT, "sqrt" }, { NODETYPE_ABS, "abs" }, { NODETYPE_EXP, "exp" }, { NODETYPE_LOG, "log" }, { NODETYPE_SIN, "sin" }, { NODETYPE_COS, "cos" }, { NODETYPE_TAN, "tan" }, { NODETYPE_ASIN, "asin" }, { NODETYPE_ACOS, "acos" }, { NODETYPE_ATAN, "atan" }, { NODETYPE_CLAMP, "clamp" }, { NODETYPE_SEGMENT, "segment" }, { NODETYPE_EXPRLIST, "exprlist" }, { NODETYPE_ASSIGN, "assign" }, { NODETYPE_IFELSE, "ifelse" }, { NODETYPE_FOR, "for" }, { (enum nodetype) 0, NULL } }; node_t new_node(int numargs, int is_scalar) { node_t n; n = malloc(sizeof *n); n->numargs = numargs; n->flags = 0; if (is_scalar) { n->flags |= NODE_IS_SCALAR; } return n; } node_t new_scalar_node(int numargs) { return new_node(numargs, 1); } node_t new_vector_node(int numargs) { return new_node(numargs, 0); } const char *node_name(node_t n){ struct nodename *p; for (p = nodenames; p->name; p++) if (p->type == n->type) return p->name; return "unknown"; } int node_is_scalar(node_t n) { return (n->flags & NODE_IS_SCALAR); } minc-2.2.00/progs/minccalc/optim.c0000644000265600003100000000010312027132662013631 00000000000000#include "node.h" node_t optimize(node_t root){ return root; } minc-2.2.00/progs/minccalc/scalar.c0000644000265600003100000000116512027132662013757 00000000000000/* Copyright David Leonard and Andrew Janke, 2000. All rights reserved. */ #include #include #include "node.h" #define INIT_SIZE 20 scalar_t new_scalar(int width){ scalar_t s; s = malloc(sizeof *s); s->width = width; s->vals = malloc(width * sizeof(s->vals[0])); s->refcnt = 1; return s; } void scalar_incr_ref(scalar_t s) { s->refcnt++; } void scalar_free(scalar_t s){ if (s->refcnt <= 0) { (void) fprintf(stderr, "Internal error: scalar freed too often\n"); exit(1); } if (--s->refcnt == 0) { free(s->vals); s->vals = NULL; free(s); } } minc-2.2.00/progs/minccalc/sym.c0000644000265600003100000001231212027132662013316 00000000000000/* Copyright David Leonard and Andrew Janke, 2000. All rights reserved. */ #include #include #include "node.h" #define NEW_SCOPE (-1) typedef enum {SYM_UNKNOWN, SYM_SCALAR, SYM_VECTOR} sym_type_t; struct sym { ident_t ident; sym_type_t type; scalar_t scalar; vector_t vector; sym_t next; }; static sym_t new_sym(ident_t id, sym_t sym){ sym_t newsym; newsym = malloc(sizeof *newsym); newsym->ident = id; newsym->type = SYM_UNKNOWN; /* We put new scope nodes at the head of the list. For regular symbols, we add the symbol to the head of the list only in the case where the head of the current symbol table is not a new scope. */ if ((id == NEW_SCOPE) || (sym==NULL) || (sym->ident != NEW_SCOPE)) { newsym->next = sym; } /* Usually for regular symbols, we add the symbol to an existing scope, so we put it as the second element of the list and return the head of the list. */ else { newsym->next = sym->next; sym->next = newsym; } return newsym; } sym_t sym_enter_scope(sym_t sym) { sym_t newsym = new_sym(NEW_SCOPE, sym); return newsym; } void sym_leave_scope(sym_t sym) { sym_t osym; if (sym==NULL) return; do { osym = sym->next; if (sym->type == SYM_VECTOR) { vector_free(sym->vector); } free(sym); sym = osym; } while ((sym != NULL) && (sym->ident != NEW_SCOPE)); return; } void sym_declare_ident(ident_t id, sym_t sym) { (void) new_sym(id, sym); return; } static sym_t sym_lookup(ident_t id, sym_t sym){ while (sym) { if (sym->ident == id) break; sym = sym->next; } return sym; } void sym_set_scalar(int width, int *eval_flags, scalar_t sc, ident_t id, sym_t sym){ int ivalue; /* Find the symbol - it is does not exist make a new one */ sym_t newsym = sym_lookup(id, sym); if (newsym == NULL) { newsym = new_sym(id, sym); } /* Make sure that any existing one is of the right type */ if (newsym->type == SYM_VECTOR) { /* errx(1, "%s is not a scalar", ident_str(id)); */ fprintf(stderr, "%s is not a scalar(lowercase)\n", ident_str(id)); exit(1); } /* Create a new scalar if needed */ if (newsym->type == SYM_UNKNOWN || newsym->scalar->width < width) { if (newsym->type == SYM_SCALAR) scalar_free(newsym->scalar); newsym->type = SYM_SCALAR; newsym->scalar = new_scalar(width); } /* Copy in the values */ for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; newsym->scalar->vals[ivalue] = sc->vals[ivalue]; } return; } void sym_set_vector(int width, int *eval_flags, vector_t v, ident_t id, sym_t sym){ int ivalue, iel; scalar_t sc; /* Find the symbol - it is does not exist make a new one */ sym_t newsym = sym_lookup(id, sym); if (newsym == NULL) { newsym = new_sym(id, sym); } /* Make sure that any existing one is of the right type */ if (newsym->type == SYM_SCALAR) { /* errx(1, "%s is not a vector", ident_str(id)); */ fprintf(stderr, "%s is not a vector\n", ident_str(id)); exit(1); } /* Create a new vector if needed - either it does not exist or the length is changing or the width is increasing*/ if (newsym->type == SYM_UNKNOWN || newsym->vector->len != v->len || (newsym->vector->len > 0 && newsym->vector->el[0]->width < width) ) { /* Free an existing vector. If eval_flags is set, then we cannot change the length of the vector */ if (newsym->type == SYM_VECTOR) { if (eval_flags != NULL && newsym->vector->len != v->len) { /* errx(1, "assigned vector must match length of %s in if", ident_str(id)); */ fprintf(stderr, "assigned vector must match length of %s in if", ident_str(id)); exit(1); } vector_free(newsym->vector); } newsym->type = SYM_VECTOR; newsym->vector = new_vector(); for (iel=0; iel < v->len; iel++) { sc = new_scalar(width); vector_append(newsym->vector, sc); scalar_free(sc); } } /* Copy in the values */ for (ivalue=0; ivalue < width; ivalue++) { if (eval_flags != NULL && !eval_flags[ivalue]) continue; for (iel=0; iel < v->len; iel++) { newsym->vector->el[iel]->vals[ivalue] = v->el[iel]->vals[ivalue]; } } return; } scalar_t sym_lookup_scalar(ident_t id, sym_t sym){ sym_t s = sym_lookup(id, sym); if (!s) { /* errx(1, "%s undefined", ident_str(id)); */ fprintf(stderr, "%s undefined\n", ident_str(id)); exit(1); } if (s->type != SYM_SCALAR) { /* errx(1, "%s is not scalar (lowercase)", ident_str(id)); */ fprintf(stderr, "%s is not scalar (lowercase)\n", ident_str(id)); exit(1); } return s->scalar; } vector_t sym_lookup_vector(ident_t id, sym_t sym){ sym_t s = sym_lookup(id, sym); if (!s) { /* errx(1, "%s undefined", ident_str(id)); */ fprintf(stderr, "%s undefined\n", ident_str(id)); exit(1); } if (s->type != SYM_VECTOR) return NULL; return s->vector; } minc-2.2.00/progs/minccalc/vector.c0000644000265600003100000000164712027132662014021 00000000000000/* Copyright David Leonard and Andrew Janke, 2000. All rights reserved. */ #include #include #include "node.h" #define INIT_SIZE 20 vector_t new_vector(){ vector_t v; v = malloc(sizeof *v); v->maxlen = INIT_SIZE; v->el = malloc(INIT_SIZE * sizeof v->el[0]); v->len = 0; v->refcnt = 1; return v; } void vector_incr_ref(vector_t v) { v->refcnt++; } void vector_append(vector_t v, scalar_t s){ if (v->len + 1 == v->maxlen) { v->maxlen *= 2; v->el = realloc(v->el, v->maxlen * sizeof v->el[0]); } v->el[v->len++] = s; scalar_incr_ref(s); } void vector_free(vector_t v){ int i; if (v->refcnt <= 0) { (void) fprintf(stderr, "Internal error: vector freed too often\n"); exit(1); } if (--v->refcnt == 0) { for (i=0; i < v->len; i++) { scalar_free(v->el[i]); } free(v->el); v->el = NULL; free(v); } } minc-2.2.00/progs/minccmp/0000755000265600003100000000000012030114723012270 500000000000000minc-2.2.00/progs/minccmp/minccmp.man10000644000265600003100000000676012027132662014435 00000000000000.\" Copyright 2010 Andrew Janke .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author makes no .\" representations about the suitability of this software .\" for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" .TH MINCCMP 1 "$Date: 2010-03-02 12:12:20 $" "" "MINC User's Guide" .SH NAME minccmp - compare one or more minc file using comparator operators .SH SYNOPSIS .B minccmp [] [ ...] .SH DESCRIPTION \fIminccmp\fR will calculate simple statistical measures between two minc files or more by comparing all subsequent files to the first. The results for each subseqent file are then returned in order. By default all statistics are calculated. If specifitc statistics are requested via a command-line option, then only the requested statistics are printed. A very useful feature of this program is the ability to restrict the set of voxels included in the statistic calculation, either by restricting the range of included values (-floor, -ceil or -range), or by using a mask file (-mask) with a restricted range. The comparison statistics available in minccmp are given below. Note that two of these (-xcorr and -zscore) are a very close approximation to what is used in minctracc. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-debug\fR Dump a lot of extra information (for when things go haywire). .TP \fB\-verbose\fR Print out extra information (more than the default). .TP \fB\-quiet\fR Print out only the requested numbers .TP \fB\-max_buffer_size_in_kb\fR\ \fIsize\fR Specify the maximum size of the internal buffers (in kbytes). Default is 4 MB. .TP \fB\-check_dimensions\fR Check that all input files have matching sampling in world dimensions (default). .TP \fB\-nocheck_dimensions\fR Ignore any differences in world dimensions sampling for input files . .SH Volume range options .TP \fB\-floor\fR\ \fImin\fR A lower bound for ranges of data to include in statistic calculations. .TP \fB\-ceil\fR\ \fImax\fR An upper bound for ranges of data to include in statistic calculations. .TP \fB\-range\fR\ \fImin\fR,\fImax\fR A lower and upper bound for the ranges of data to include in statistics. .TP \fB\-mask\fR\ \fIfilename.mnc\fR Name of file to be used for masking data included in statistic calculations. .SH Basic statistics .TP \fB\-all\fR Compute all statistical measures. This is the default. .TP \fB\-ssq\fR Print the Sum Squared Difference between two input files SSQ = Sum( (A-B)^2 ) .TP \fB\-rmse\fR Print the Root Mean Squared Error between two input files RMSE = sqrt( 1/n * Sum((A-B)^2)) .TP \fB\-xcorr\fR Print the Cross Correlation between two input files XCORR = Sum((A*B)^2) / (sqrt(Sum(A^2)) * sqrt(Sum(B^2)) .TP \fB\-zscore\fR Print the z-score difference between two input files ZSCORE = Sum( |((A - mean(A)) / stdev(A)) - ((B - mean(B)) / stdev(B))| ) / n .SH Generic options for all commands: .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Andrew Janke .SH COPYRIGHTS .P Copyright \(co 2010 by Andrew Janke minc-2.2.00/progs/minccmp/minccmp.c0000644000265600003100000004001512027132662014012 00000000000000/* minccmp.c */ /* */ /* Copyright Andrew Janke - a.janke@gmail.com */ /* Permission to use, copy, modify, and distribute this software and its */ /* documentation for any purpose and without fee is hereby granted, */ /* provided that the above copyright notice appear in all copies. The */ /* author makes no representations about the */ /* suitability of this software for any purpose. It is provided "as is" */ /* without express or implied warranty. */ /* */ /* calculates measures of similarity/difference between 2 or more volumes */ /* */ /* Measures used (sum(x) denotes the sum of x over a volume): */ /* RMSE - Root Mean Squared Error */ /* = sqrt( 1/n * sum((a-b)^2)) */ /* xcorr - Cross Correlation */ /* = sum((a*b)^2) / (sqrt(sum(a^2)) * sqrt(sum(b^2)) */ /* zscore - z-score differences */ /* = sum( |((a - mean(a)) / stdev(a)) - */ /* ((b - mean(b)) / stdev(b))| ) / nvox */ /* */ /* Tue Jun 17 11:31:10 EST 2003 - initial version inspired by voldiff and */ /* peter's compare_volumes */ #include #include #include #include #include #include #include #ifndef FALSE # define FALSE 0 #endif #ifndef TRUE # define TRUE 1 #endif #define SQR2(x) ((x) * (x)) typedef struct { double nvox; double sum; /* sum of valid voxels */ double ssum; /* squared sum of valid voxels */ double min; double max; double mean; double var; double sd; double sum_prd0; /* sum of product of file[x] with file[0] */ double ssum_add0; /* squared sum of addition of file[x] with file[0] */ double ssum_dif0; /* squared sum of difference of file[x] with file[0] */ double ssum_prd0; /* squared sum of product of file[x] with file[0] */ double sum_zdif0; /* sum of zscore differences of file[x] and file[0] */ /* result stores */ double rmse; double xcorr; double zscore; double vratio; } Vol_Data; typedef struct { int n_datafiles; int mask; int mask_idx; /* individual volume data */ Vol_Data *vd; } Loop_Data; /* Function prototypes */ void pass_0(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info); void pass_1(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info); void print_result(char *title, double result); void dump_stats(Loop_Data * ld); void do_int_calcs(Loop_Data * ld); void do_final_calcs(Loop_Data * ld); /* Argument variables and table */ static int verbose = FALSE; static int debug = FALSE; static int quiet = FALSE; static int clobber = FALSE; static int max_buffer_size_in_kb = 4 * 1024; static int check_dim_info = TRUE; static char *mask_fname = NULL; static double valid_range[2] = { -DBL_MAX, DBL_MAX }; static int do_all = FALSE; static int do_ssq = FALSE; static int do_rmse = FALSE; static int do_xcorr = FALSE; static int do_zscore = FALSE; static int do_vratio = FALSE; ArgvInfo argTable[] = { {"-verbose", ARGV_CONSTANT, (char *)TRUE, (char *)&verbose, "be verbose"}, {"-debug", ARGV_CONSTANT, (char *)TRUE, (char *)&debug, "dump all stats info"}, {"-quiet", ARGV_CONSTANT, (char *)TRUE, (char *)&quiet, "print requested values only"}, {"-clobber", ARGV_CONSTANT, (char *)TRUE, (char *)&clobber, "clobber existing files"}, {"-max_buffer_size_in_kb", ARGV_INT, (char *)1, (char *)&max_buffer_size_in_kb, "maximum size of internal buffers."}, {"-check_dimensions", ARGV_CONSTANT, (char *) TRUE, (char *) &check_dim_info, "Check that files have matching dimensions (default)."}, {"-nocheck_dimensions", ARGV_CONSTANT, (char *) FALSE, (char *) &check_dim_info, "Do not check that files have matching dimensions."}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nVoxel selection options (applies to first volume ONLY):"}, {"-floor", ARGV_FLOAT, (char *)1, (char *)&valid_range[0], "Ignore voxels below this value. (incl)"}, {"-ceil", ARGV_FLOAT, (char *)1, (char *)&valid_range[1], "Ignore voxels above this value. (incl)"}, {"-range", ARGV_FLOAT, (char *)2, (char *)&valid_range, "Ignore voxels outside the range. (incl)"}, {"-mask", ARGV_STRING, (char *)1, (char *)&mask_fname, "Use for calculations."}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nImage Statistics (printed in this order)"}, {"-all", ARGV_CONSTANT, (char *)TRUE, (char *)&do_all, "all statistics (default)."}, {"-ssq", ARGV_CONSTANT, (char *)TRUE, (char *)&do_ssq, "sum of squared difference (2 volumes)"}, {"-rmse", ARGV_CONSTANT, (char *)TRUE, (char *)&do_rmse, "root mean squared error (2 volumes)"}, {"-xcorr", ARGV_CONSTANT, (char *)TRUE, (char *)&do_xcorr, "cross correlation (2 volumes)"}, {"-zscore", ARGV_CONSTANT, (char *)TRUE, (char *)&do_zscore, "z-score (2 volumes)"}, // {"-vr", ARGV_CONSTANT, (char *)TRUE, (char *)&do_vratio, // "variance ratio (2 volumes)"}, // {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, // "\nBinary Image Only Statistics"}, // {"-kappa", ARGV_CONSTANT, (char *)TRUE, (char *)&do_kappa, // "all statistics (default)."}, {NULL, ARGV_HELP, NULL, NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char *argv[]){ char **infiles; int n_infiles; Loop_Options *loop_opt; Loop_Data ld; int i; /* Get arguments */ if(ParseArgv(&argc, argv, argTable, 0) || (argc < 3)){ fprintf(stderr, "\nUsage: %s [options] []\n", argv[0]); fprintf(stderr, " %s -help\n\n", argv[0]); return (EXIT_FAILURE); } n_infiles = argc - 1; infiles = &argv[1]; /* check arguments */ if(!do_rmse && !do_xcorr && !do_zscore && !do_vratio){ do_all = TRUE; } if(do_all){ do_ssq = do_rmse = do_xcorr = do_zscore = do_vratio = TRUE; } /* check for infiles */ if(verbose){ fprintf(stderr, "\n+++ infiles +++\n"); } for(i = 0; i < n_infiles; i++){ if(verbose){ fprintf(stderr, " | [%02d]: %s\n", i, infiles[i]); } if(access(infiles[i], F_OK) != 0){ fprintf(stderr, "%s: Couldn't find %s\n", argv[0], infiles[i]); exit(EXIT_FAILURE); } } /* set up Loop_Data struct and mask file */ ld.n_datafiles = n_infiles; if(mask_fname != NULL){ if(verbose){ fprintf(stderr, " | mask: %s\n", mask_fname); } if(access(mask_fname, F_OK) != 0){ fprintf(stderr, "%s: Couldn't find mask file: %s\n", argv[0], mask_fname); exit(EXIT_FAILURE); } ld.mask = TRUE; ld.mask_idx = n_infiles; infiles[n_infiles] = mask_fname; n_infiles++; } else { ld.mask = FALSE; ld.mask_idx = 0; } /* allocate space and initialise volume stats data */ ld.vd = (Vol_Data *) malloc(sizeof(Vol_Data) * ld.n_datafiles); for(i = 0; i < ld.n_datafiles; i++){ ld.vd[i].nvox = 0; ld.vd[i].sum = 0; ld.vd[i].ssum = 0; ld.vd[i].min = DBL_MAX; ld.vd[i].max = -DBL_MAX; ld.vd[i].sum_prd0 = 0; ld.vd[i].ssum_add0 = 0; ld.vd[i].ssum_dif0 = 0; ld.vd[i].ssum_prd0 = 0; ld.vd[i].mean = 0; ld.vd[i].var = 0; ld.vd[i].sd = 0; ld.vd[i].rmse = 0.0; ld.vd[i].xcorr = 0.0; ld.vd[i].zscore = 0.0; ld.vd[i].vratio = 0.0; } /* set up and do voxel_loop(s) */ loop_opt = create_loop_options(); set_loop_verbose(loop_opt, verbose); set_loop_buffer_size(loop_opt, (long)1024 * max_buffer_size_in_kb); set_loop_check_dim_info(loop_opt, check_dim_info); /* first pass */ voxel_loop(n_infiles, infiles, 0, NULL, NULL, loop_opt, pass_0, (void *)&ld); /* intermediate calculations */ do_int_calcs(&ld); /* run the second pass if we have to */ if(do_zscore){ voxel_loop(n_infiles, infiles, 0, NULL, NULL, loop_opt, pass_1, (void *)&ld); } /* final calculations */ do_final_calcs(&ld); free_loop_options(loop_opt); if(debug){ dump_stats(&ld); } /* calculate and print result(s) */ if(do_all && !quiet){ fprintf(stdout, "file[0]: %s\n", infiles[0]); fprintf(stdout, "file[1]: %s\n", infiles[1]); fprintf(stdout, "mask file: %s\n", mask_fname); } if(do_ssq){ print_result("ssq: ", ld.vd[1].ssum_dif0); } if(do_rmse){ print_result("rmse: ", ld.vd[1].rmse); } if(do_xcorr){ print_result("xcorr: ", ld.vd[1].xcorr); } if(do_zscore){ print_result("zscore: ", ld.vd[1].zscore); } if(!quiet){ fprintf(stdout, "\n"); } return EXIT_SUCCESS; } /* voxel loop function for first pass through data */ void pass_0(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info){ long ivox; double valuei, value0; int i; /* get pointer to loop data */ Loop_Data *ld = (Loop_Data *)caller_data; /* shut the compiler up - yes I _know_ I don't use these */ (void)output_num_buffers; (void)output_vector_length; (void)output_data; (void)loop_info; /* sanity check */ if((input_num_buffers < 2) || (output_num_buffers != 0)){ fprintf(stderr, "Bad arguments to pass_0\n"); exit(EXIT_FAILURE); } /* for each voxel */ for(ivox = num_voxels * input_vector_length; ivox--;){ /* skip voxels out of the mask region */ if(ld->mask && !(int)input_data[ld->mask_idx][ivox]){ continue; } value0 = input_data[0][ivox]; if(value0 >= valid_range[0] && value0 <= valid_range[1]){ /* for each volume */ for(i = 0; i < ld->n_datafiles; i++){ valuei = input_data[i][ivox]; /* various voxel sums */ ld->vd[i].nvox++; ld->vd[i].sum += valuei; ld->vd[i].ssum += SQR2(valuei); if(i != 0){ ld->vd[i].sum_prd0 += valuei * value0; ld->vd[i].ssum_add0 += SQR2(valuei + value0); ld->vd[i].ssum_dif0 += SQR2(valuei - value0); ld->vd[i].ssum_prd0 += SQR2(valuei * value0); } /* min and max */ if(valuei < ld->vd[i].min){ ld->vd[i].min = valuei; } else if(valuei > ld->vd[i].max){ ld->vd[i].max = valuei; } } } } return; } /* intermediate calculations */ void do_int_calcs(Loop_Data * ld){ int i; double denom; for(i = 0; i < ld->n_datafiles; i++){ /* mean */ ld->vd[i].mean = ld->vd[i].sum / ld->vd[i].nvox; /* variance */ ld->vd[i].var = ((ld->vd[i].nvox * ld->vd[i].ssum) - SQR2(ld->vd[i].sum)) / (ld->vd[i].nvox * (ld->vd[i].nvox - 1)); /* sd */ ld->vd[i].sd = sqrt(ld->vd[i].var); /* RMSE */ ld->vd[i].rmse = sqrt((1.0 / ld->vd[0].nvox) * ld->vd[i].ssum_dif0); /* xcorr */ denom = sqrt(ld->vd[0].ssum * ld->vd[i].ssum); ld->vd[i].xcorr = (denom == 0.0) ? 0.0 : ld->vd[i].sum_prd0 / denom; } } /* voxel loop function for second pass through data */ void pass_1(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info){ long ivox; double valuei, value0; int i; /* get pointer to loop data */ Loop_Data *ld = (Loop_Data *)caller_data; /* shut the compiler up - yes I _know_ I don't use these */ (void)output_num_buffers; (void)output_vector_length; (void)output_data; (void)loop_info; /* sanity check */ if((input_num_buffers < 2) || (output_num_buffers != 0)){ fprintf(stderr, "Bad arguments to pass_1\n"); exit(EXIT_FAILURE); } /* for each voxel */ for(ivox = num_voxels * input_vector_length; ivox--;){ /* skip voxels out of the mask region */ if(ld->mask && !(int)input_data[ld->mask_idx][ivox]){ continue; } value0 = input_data[0][ivox]; if(value0 >= valid_range[0] && value0 <= valid_range[1]){ /* for each volume */ for(i = 0; i < ld->n_datafiles; i++){ valuei = input_data[i][ivox]; if(i != 0){ /* zscore total */ ld->vd[i].sum_zdif0 += fabs(((value0 - ld->vd[0].mean) / ld->vd[0].sd) - ((valuei - ld->vd[i].mean) / ld->vd[i].sd)); } } } } return; } /* final calculations */ void do_final_calcs(Loop_Data * ld){ int i; for(i = 0; i < ld->n_datafiles; i++){ /* zscore */ ld->vd[i].zscore = ld->vd[i].sum_zdif0 / ld->vd[i].nvox; } } /* dirty little function to print out results */ void print_result(char *title, double result){ if(!quiet){ fprintf(stdout, "%s", title); } fprintf(stdout, "%.10g\n", result); } /* debug function to dump stats structure */ void dump_stats(Loop_Data * ld){ int i; fprintf(stdout, " + Main Loop data structure\n"); fprintf(stdout, " | n_datafiles %d\n", ld->n_datafiles); fprintf(stdout, " | mask %d\n", ld->mask); fprintf(stdout, " | mask_idx %d\n", ld->mask_idx); fprintf(stdout, " +++ volume data stats\n"); for(i = 0; i < ld->n_datafiles; i++){ fprintf(stdout, " |---------------------------------\n"); fprintf(stdout, " | [%02d] nvox %10g\n", i, ld->vd[i].nvox); fprintf(stdout, " | [%02d] sum %.10g\n", i, ld->vd[i].sum); fprintf(stdout, " | [%02d] ssum %.10g\n", i, ld->vd[i].ssum); fprintf(stdout, " | [%02d] min %.10g\n", i, ld->vd[i].min); fprintf(stdout, " | [%02d] max %.10g\n", i, ld->vd[i].max); fprintf(stdout, " | [%02d] mean %.10g\n", i, ld->vd[i].mean); fprintf(stdout, " | [%02d] var %.10g\n", i, ld->vd[i].var); fprintf(stdout, " | [%02d] sd %.10g\n", i, ld->vd[i].sd); fprintf(stdout, " | [%02d] sum_prd0 %.10g\n", i, ld->vd[i].sum_prd0); fprintf(stdout, " | [%02d] ssum_add0 %.10g\n", i, ld->vd[i].ssum_add0); fprintf(stdout, " | [%02d] ssum_dif0 %.10g\n", i, ld->vd[i].ssum_dif0); fprintf(stdout, " | [%02d] ssum_prd0 %.10g\n", i, ld->vd[i].ssum_prd0); fprintf(stdout, " | [%02d] sum_zdif0 %.10g\n", i, ld->vd[i].sum_zdif0); fprintf(stdout, " | [%02d] rmse %.10g\n", i, ld->vd[i].rmse); fprintf(stdout, " | [%02d] xcorr %.10g\n", i, ld->vd[i].xcorr); fprintf(stdout, " | [%02d] zscore %.10g\n", i, ld->vd[i].zscore); fprintf(stdout, " | [%02d] vratio %.10g\n", i, ld->vd[i].vratio); } } minc-2.2.00/progs/minccomplete/0000755000265600003100000000000012030114721013317 500000000000000minc-2.2.00/progs/minccomplete/minccomplete.man10000644000265600003100000001332612030102322016473 00000000000000.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MINCCOMPLETE 1" .TH MINCCOMPLETE 1 "2012-09-24" "perl v5.10.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" \&\fBminccomplete\fR \- checks if a \s-1MINC\s0 file is complete .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBminccomplete\fR [options] .PP minccomplete is designed as a \s-1QC\s0 tool that you can use to check if \s-1MINC\s0 or xfm files have been completely written. .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBminccomplete\fR will check if a file exists and is completely written. The reasons for non-completion are varied but typically caused when a process writing a \s-1MINC\s0 or xfm file is interrupted. A zero will be returned if the file is complete and a \-1 if it isn't. .PP Examples: .PP .Vb 4 \& $ minccomplete in.mnc \& 0 \& $ minccomplete in.xfm \& 0 .Ve .PP A \s-1MINC\s0 file is returned as complete if the image attribute image:complete is set. ie: .PP .Vb 1 \& mincinfo \-attvalue image:complete infile.mnc .Ve .PP A xfm file is deemed complete if xfm2param can parse the file. The associated exit codes will also be set as part of this so that minccomplete can be used in scripts. .PP An entirely simplistic example: .PP .Vb 1 \& #! /bin/sh \& \& infile=$1 \& \& if [ \`minccomplete ${infile}\` ] \& then \& echo "Yes!" \& else \& echo "Nope, try again" \& fi .Ve .PP Problems or comments should be sent to: a.janke@gmail.com .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-v\fR, \fB\-\-verbose\fR" 4 .IX Item "-v, --verbose" Be noisy when doing things .IP "\fB\-\-version\fR" 4 .IX Item "--version" Print version number and exit .IP "\fB\-h\fR, \fB\-\-help\fR" 4 .IX Item "-h, --help" Dump some quick help output .IP "\fB\-\-man\fR" 4 .IX Item "--man" Dump a man page .IP "\fB\-e\fR, \fB\-\-error_string\fR" 4 .IX Item "-e, --error_string" Don't die on errors (eg: file not found) and print the supplied value instead .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fImincheader\fR\|(1) \fImincinfo\fR\|(1) \fIxfm2param\fR\|(1) .SH "AUTHOR" .IX Header "AUTHOR" Andrew Janke \- a.janke@gmail.com .SH "COPYRIGHTS" .IX Header "COPYRIGHTS" Copyright 2000 by Andrew L Janke minc-2.2.00/progs/minccomplete/minccomplete.in0000755000265600003100000001071712027132662016271 00000000000000#! /usr/bin/env perl # # Checks if a MINC file is complete # # Copyright Andrew Janke a.janke@gmail.com # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies. The # author makes no representations about the suitability of this software # for any purpose. It is provided "as is" without express or implied warranty. use strict; use warnings "all"; use Getopt::Long; use Pod::Usage; use File::Basename; my($me, %opt, $dump, $infile, $error); $me = basename($0); %opt = ( 'help' => 0, 'man' => 0, 'verbose' => 0, 'error_string' => undef, ); # Check arguments &GetOptions( 'help|?' => \$opt{'help'}, 'man' => \$opt{'man'}, 'v|verbose' => \$opt{'verbose'}, 'version' => sub { &print_version_info }, 'e|error_string=s' => \$opt{'error_string'}, ) or pod2usage(-verbose => 1) && exit; # handle -man, -help or missing args pod2usage(-verbose => 1) if $opt{'help'}; pod2usage(-exitstatus => 0, -verbose => 2) if $opt{'man'}; pod2usage(-verbose => 0) && exit if ($#ARGV != 0); $infile = $ARGV[0]; # check if the file in question exists if(!-e $infile){ if(defined($opt{error_string})){ print STDOUT "$opt{error_string}\n"; exit(-1); } else{ die "$me: Couldn't find $infile\n\n"; } } # figure out what we have here if($infile =~ m/\.mnc(\.gz|)$/){ my($version); print STDOUT "Checking a MINC file ($infile)\n" if $opt{'verbose'}; # first check that the header is "valid" if(system("mincdump -h $infile 2> /dev/null 1>&2") == 0){ $error = 0; } else{ $error = -1; } # if good, check if the image is complete for MINC2 if($error == 0){ chomp($version = `mincinfo -minc_version $infile 2> /dev/null`); if($version =~ m/HDF5/){ print STDOUT "File is $version\n" if $opt{'verbose'}; chomp($dump = `mincinfo -attvalue image:complete $infile 2> /dev/null`); $error = -1 if ($dump ne 'true_'); } } } elsif($infile =~ m/\.xfm$/){ print STDOUT "Checking a XFM file ($infile)\n" if $opt{'verbose'}; if(system("xfm2param $infile 2> /dev/null 1>&2") == 0){ $error = 0; } else{ $error = -1; } } # now output the status if($error){ if(defined($opt{'error_string'})){ print STDOUT "$opt{'error_string'}\n"; } else{ print STDOUT "$error\n"; } } else{ print STDOUT "$error\n"; } exit($error); # print version information sub print_version_info { my $PACKAGE = '@PACKAGE_NAME@'; my $VERSION = '@PACKAGE_VERSION@'; my $PACKAGE_BUGREPORT = '@PACKAGE_BUGREPORT@'; print STDOUT "\n$PACKAGE version $VERSION\n". "Comments to $PACKAGE_BUGREPORT\n\n"; exit 0; } __END__ =head1 NAME B - checks if a MINC file is complete =head1 SYNOPSIS B [options] minccomplete is designed as a QC tool that you can use to check if MINC or xfm files have been completely written. =head1 DESCRIPTION B will check if a file exists and is completely written. The reasons for non-completion are varied but typically caused when a process writing a MINC or xfm file is interrupted. A zero will be returned if the file is complete and a -1 if it isn't. Examples: $ minccomplete in.mnc 0 $ minccomplete in.xfm 0 A MINC file is returned as complete if the image attribute image:complete is set. ie: mincinfo -attvalue image:complete infile.mnc A xfm file is deemed complete if xfm2param can parse the file. The associated exit codes will also be set as part of this so that minccomplete can be used in scripts. An entirely simplistic example: #! /bin/sh infile=$1 if [ `minccomplete ${infile}` ] then echo "Yes!" else echo "Nope, try again" fi Problems or comments should be sent to: a.janke@gmail.com =head1 OPTIONS =over 4 =item B<-v>, B<--verbose> Be noisy when doing things =item B<--version> Print version number and exit =item B<-h>, B<--help> Dump some quick help output =item B<--man> Dump a man page =item B<-e>, B<--error_string> Don't die on errors (eg: file not found) and print the supplied value instead =back =head1 SEE ALSO mincheader(1) mincinfo(1) xfm2param(1) =head1 AUTHOR Andrew Janke - a.janke@gmail.com =head1 COPYRIGHTS Copyright 2000 by Andrew L Janke =cut minc-2.2.00/progs/mincconcat/0000755000265600003100000000000012030114723012760 500000000000000minc-2.2.00/progs/mincconcat/mincconcat.man10000644000265600003100000001321112027132662015602 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincconcat/mincconcat.man1,v 6.4 2005-07-15 17:38:08 bert Exp $ .\" .TH MINCCONCAT 1 "$Date: 2005-07-15 17:38:08 $" "" "MINC User's Guide" .SH NAME mincconcat - concatenate minc files along a specific dimension .SH SYNOPSIS .B mincconcat [] .mnc [.mnc ...] .mnc .SH DESCRIPTION \fIMincconcat\fR will concatenate a number of minc files together, producing a single output file. The concatenation is done along a specified dimension, with the slices being sorted into ascending order. The concatenation dimension can either be a dimension in the file, in which case coordinates for sorting are taken directly from the input files, or it can be a new dimension and the coordinates are specified with a command-line option. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create a MINC 2.0 format output file. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-verbose\fR Print out progress information for each chunk of data copied (default). .TP \fB\-quiet\fR Do not print out progress information. .TP \fB\-max_chunk_size_in_kb\fR \fIsize\fR Specify the maximum size of the copy buffer (in kbytes). Default is 4096 kbytes. .TP \fB\-filelist\fR \fIfilename\fR Specify a file containing a list of input file names. If "-" is given, then file names are read from stdin. If this option is given, then there should be no input file names specified on the command line. Empty lines in the input file are ignored. .SH Output type options .TP \fB\-filetype\fR Don't do any type conversion (default). .TP \fB\-byte\fR Write out 8-bit integer voxels. .TP \fB\-short\fR Write out 16-bit integer voxels. .TP \fB-int\fR Write out 32-bit integer voxels. .TP \fB\-long\fR Superseded by -int. .TP \fB\-float\fR Write out single-precision floating point values. .TP \fB\-double\fR Write out double-precision floating point values. .TP \fB\-signed\fR Write out values as signed integers (default for short and long). Ignored for floating point types. .TP \fB\-unsigned\fR Write out values as unsigned integers (default for byte). Ignored for floating point types. .TP \fB\-valid_range\fR \fImin max\fR Specifies the valid range of output voxel values in their integer representation. Default is the full range for the type and sign. This option is ignored for floating point values. .SH Concatenation options .TP \fB\-concat_dimension\fR \fIname\fR Specifies the name of concatenation dimension. If the dimension exists in the input files, then coordinates are taken from those files. If not, then a new dimension is created and the coordinate for each input file is taken from command-line options. The default is to use the slowest varying dimension of the first file. .TP \fB\-start\fR \fIstart\fR Specifies the starting coordinate for the new dimension (default = 0.0). .TP \fB\-step\fR \fIstep\fR Specifies the separation between voxels for the new dimension (default = 1.0). .TP \fB\-width\fR \fIwidth\fR Specifies the (constant) width of each sample along the new dimension (default = none). .TP \fB\-coordlist\fR \fIc1,c2,...\fR Specifies a comma-separated list of coordinates along the new dimension. .TP \fB\-widthlist\fR \fIw1,w2,...\fR Specifies a comma-separated list of widths along the new dimension. .TP \fB\-filestarts\fR \fIs1,s2,...\fR Specifies a comma-separated list of offsets to the coordinate origins for each of the files listed on the command line. This option is useful for concatenating files along an existing dimension, for example for concatenating multiple functional runs along a .B time dimension. .TP \fB\-check_dimensions\fR Check that all input files have matching sampling in world dimensions (default). .TP \fB\-nocheck_dimensions\fR Ignore any differences between input files in world dimensions sampling. .TP \fB\-ascending\fR Sort coordinates in ascending order (default). .TP \fB\-descending\fR Sort coordinates in descending order. .TP \fB\-interleaved\fR Sort slabs by their dimension coordinate, interleaving if necessary (default). .TP \fB\-sequential\fR Don't sort slabs, just concatenate them together. WARNING - this will destroy the dimension information along the concatenating dimension, replacing the start and step with zero and one. .SH Generic options for all commands: .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES To concatenate two volumes with dimensions zspace, yspace, xspace, having interleaved slices along zspace, we can simply use mincconcat input1.mnc input2.mnc output.mnc If we have a bunch of compressed (yspace, xspace) images that we wish to concatenate into an evenly spaced volume, then we can type mincconcat input1.mnc.gz input2.mnc.gz input3.mnc.gz \\ input4.mnc.gz output.mnc \\ -concat_dimension zspace -start -23 -step 2 .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1995 by Peter Neelin minc-2.2.00/progs/mincconcat/mincconcat.c0000644000265600003100000014774512027132662015214 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincconcat @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : error status @DESCRIPTION: Program to allow concatentation of multiple minc files, either adding a new dimension, or expanding a dimension of size 1. @METHOD : @GLOBALS : @CALLS : @CREATED : March 7, 1995 (Peter Neelin) @MODIFIED : * $Log: mincconcat.c,v $ * Revision 6.15 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.14 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.13 2005/08/26 21:07:17 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.12 2005/07/15 17:38:08 bert * Add -filestarts option * * Revision 6.11 2004/12/14 23:52:08 bert * Get rid of compilation warnings w/c99 * * Revision 6.10 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.9 2004/04/27 15:37:13 bert * Added -2 flag * * Revision 6.8 2001/09/18 15:32:39 neelin * Create image variable last to allow big images and to fix compatibility * problems with 2.3 and 3.x. * * Revision 6.7 2001/08/16 16:41:33 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.6 2001/08/16 13:32:33 neelin * Partial fix for valid_range of different type from image (problems * arising from double to float conversion/rounding). NOT COMPLETE. * * Revision 6.5 2001/04/24 13:38:42 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.4 2001/04/17 18:40:17 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.3 2000/07/07 13:33:34 neelin * Added option -filelist to read file names from a file. This gets around * command-line length limits. * * Revision 6.2 1999/10/19 14:45:19 neelin * Fixed Log subsitutions for CVS * * Revision 6.1 1998/08/13 19:34:37 neelin * Always create concatenation coordinate variable subscription by * dimension. * * Revision 6.0 1997/09/12 13:24:15 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:13 neelin * Release of minc version 0.5 * * Revision 4.1 1997/06/03 14:57:23 neelin * Really fixed dimension width name suffixes. * * Revision 4.0 1997/05/07 20:01:54 neelin * Release of minc version 0.4 * * Revision 3.4 1997/04/21 20:28:45 neelin * Changed width suffix from _width to -width. * * Revision 3.3 1996/04/11 19:31:43 neelin * Added -sequential and -interleaved options. * * Revision 3.2 1995/11/16 13:18:16 neelin * Added include of math.h to get declaration of strtod under SunOs * * Revision 3.1 1995/09/29 12:59:06 neelin * Fixed bug in handling of image-min/max when these variables are not * present in the input file. * * Revision 3.0 1995/05/15 19:32:40 neelin * Release of minc version 0.3 * * Revision 1.1 1995/05/11 12:35:53 neelin * Initial revision * @COPYRIGHT : Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include #include "read_file_names.h" /* Constants */ #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #define COORD_EPSILON (100.0 * FLT_EPSILON) #define DIM_WIDTH_SUFFIX "-width" /* Default ncopts values for error handling */ #define NC_OPTS_VAL NC_VERBOSE | NC_FATAL /* Macros */ #define ABS(x) ( ((x) > 0) ? (x) : (-(x)) ) /* Double_Array structure */ typedef struct { int numvalues; double *values; } Double_Array; /* Concat_info structure */ typedef struct { char *output_file; int num_input_files; char *history; int cflags; int verbose; nc_type output_datatype; int output_is_signed; double output_valid_range[2]; char *dimension_name; int *num_file_coords; int **file_to_dim_order; double **file_coords; double **file_widths; /* Array of NULL pointers if no widths */ double *file_offsets; /* Per-file offsets from start of dimension */ int coords_specified; int dimension_in_input_file; int concat_dimension_length; int regular_spacing; int constant_width; int have_widths; double dim_step; double dim_start; int output_mincid, output_icvid; int is_floating_type; double global_minimum; double global_maximum; long max_memory_use_in_kb; int check_dim_info; } Concat_Info; /* Sort structure */ typedef struct { double coord; int curfile; int curcoord; } Sort_Element; /* Function prototypes */ static void get_arginfo(int argc, char *argv[], int *num_input_files, char ***input_files, Concat_Info *concat_info); static int get_double_list(char *dst, char *key, char *nextarg); static void get_concat_dim_name(Concat_Info *concat_info, char *first_filename, int *first_mincid); static void get_input_file_info(void *caller_data, int input_mincid, int input_curfile, Loop_Info *loop_info); static int get_image_dimension_id(int input_mincid, char *dimension_name); static void do_concat(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void sort_coords(Concat_Info *concat_info); static int sort_function(const void *value1, const void *value2); static void create_concat_file(int inmincid, Concat_Info *concat_info); static void update_history(int mincid, char *arg_string); /* Globals */ static int Sort_ascending = TRUE; static int Sort_sequential = FALSE; /* Main program */ int main(int argc, char *argv[]) { Concat_Info *concat_info; Loop_Options *loop_options; int num_input_files; char **input_files; int first_mincid, imgid; double valid_range[2]; /* Allocate the concat_info structure */ concat_info = malloc(sizeof(*concat_info)); /* Get argument information */ get_arginfo(argc, argv, &num_input_files, &input_files, concat_info); /* Look for the dimension in the input file */ get_concat_dim_name(concat_info, input_files[0], &first_mincid); /* Set up loop options */ loop_options = create_loop_options(); set_loop_verbose(loop_options, concat_info->verbose); set_loop_first_input_mincid(loop_options, first_mincid); set_loop_input_file_function(loop_options, get_input_file_info); set_loop_accumulate(loop_options, TRUE, 0, NULL, NULL); if (concat_info->dimension_in_input_file) { set_loop_dimension(loop_options, concat_info->dimension_name); } set_loop_buffer_size(loop_options, 1024 * concat_info->max_memory_use_in_kb); set_loop_check_dim_info(loop_options, concat_info->check_dim_info); /* Initialize global min and max */ concat_info->global_minimum = DBL_MAX; concat_info->global_maximum = -DBL_MAX; /* Loop over files */ voxel_loop(num_input_files, input_files, 0, NULL, NULL, loop_options, do_concat, concat_info); /* Close the output file */ imgid = ncvarid(concat_info->output_mincid, MIimage); (void) miattputstr(concat_info->output_mincid, imgid, MIcomplete, MI_TRUE); if (concat_info->is_floating_type) { if ((concat_info->global_minimum == DBL_MAX) && (concat_info->global_maximum == -DBL_MAX)) { concat_info->global_minimum = 0.0; concat_info->global_maximum = 1.0; } valid_range[0] = concat_info->global_minimum; valid_range[1] = concat_info->global_maximum; (void) miset_valid_range(concat_info->output_mincid, imgid, valid_range); } (void) miclose(concat_info->output_mincid); (void) miicv_free(concat_info->output_icvid); /* Free stuff */ free_loop_options(loop_options); free(concat_info); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_arginfo @INPUT : argc - number of command-line arguments argv - command-line arguments @OUTPUT : num_input_files - number of input files input_files - array of strings containing input file names concat_info - information for concatenating files @RETURNS : (nothing) @DESCRIPTION: Routine to get information from arguments about input and output files and concatenation. @METHOD : @GLOBALS : @CALLS : @CREATED : March 11, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_arginfo(int argc, char *argv[], int *num_input_files, char ***input_files, Concat_Info *concat_info) { /* Argument variables */ static int clobber = FALSE; #if MINC2 static int minc2_format = FALSE; #endif /* MINC2 */ static int verbose = TRUE; static nc_type datatype = MI_ORIGINAL_TYPE; static int is_signed = INT_MIN; static double valid_range[2] = {0.0, 0.0}; static char *dimension_name = NULL; static double dimension_start = DBL_MAX; static double dimension_step = DBL_MAX; static double dimension_width = DBL_MAX; static Double_Array dimension_coords = {0, NULL}; static Double_Array dimension_widths = {0, NULL}; static Double_Array file_offsets = {0, NULL}; static int max_chunk_size_in_kb = 4 * 1024; static int check_dim_info = TRUE; static char *filelist = NULL; /* Argument table */ static ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "General options:"}, #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &minc2_format, "Produce a MINC 2.0 format output file"}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Do not overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages as processing is being done (default).\n"}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out any log messages."}, {"-max_chunk_size_in_kb", ARGV_INT, (char *) 1, (char *) &max_chunk_size_in_kb, "Specify the maximum size of the copy buffer (in kbytes)."}, {"-filelist", ARGV_STRING, (char *) 1, (char *) &filelist, "Specify the name of a file containing input file names (- for stdin)."}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Output type options:"}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Don't do any type conversion (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Convert to byte data"}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Convert to short integer data"}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Convert to 32-bit integer data"}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int"}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Convert to single-precision floating-point data"}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Convert to double-precision floating-point data"}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Convert to signed integer data"}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Convert to unsigned integer data"}, {"-valid_range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data (pixel values)"}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Concatenation options:"}, {"-concat_dimension", ARGV_STRING, (char *) 1, (char *) &dimension_name, "Concatenate along a given dimension."}, {"-start", ARGV_FLOAT, (char *) 1, (char *) &dimension_start, "Starting coordinate for new dimension."}, {"-step", ARGV_FLOAT, (char *) 1, (char *) &dimension_step, "Step size for new dimension."}, {"-width", ARGV_FLOAT, (char *) 1, (char *) &dimension_width, "Sample width for new dimension."}, {"-coordlist", ARGV_FUNC, (char *) get_double_list, (char *) &dimension_coords, "Specify the dimension coordinates (\",,...\")."}, {"-widthlist", ARGV_FUNC, (char *) get_double_list, (char *) &dimension_widths, "Specify the dimension widths (\",,...\")."}, {"-filestarts", ARGV_FUNC, (char *) get_double_list, (char *) &file_offsets, "Specify the start offset of each file (\",...\")."}, {"-check_dimensions", ARGV_CONSTANT, (char *) TRUE, (char *) &check_dim_info, "Check that files have matching dimensions (default)."}, {"-nocheck_dimensions", ARGV_CONSTANT, (char *) FALSE, (char *) &check_dim_info, "Do not check that files have matching dimensions."}, {"-ascending", ARGV_CONSTANT, (char *) TRUE, (char *) &Sort_ascending, "Sort coordinates in ascending order (default)."}, {"-descending", ARGV_CONSTANT, (char *) FALSE, (char *) &Sort_ascending, "Sort coordinates in descending order."}, {"-interleaved", ARGV_CONSTANT, (char *) FALSE, (char *) &Sort_sequential, "Sort coordinates in coordinate order, interleaving if necessary (default)."}, {"-sequential", ARGV_CONSTANT, (char *) TRUE, (char *) &Sort_sequential, "Sort coordinates in sequential file order."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Local variables */ char *output_file; char *history; char *pname; char **infiles; int nfiles; int ifile; /* Get the history information and program name */ history = time_stamp(argc, argv); pname = argv[0]; /* Call ParseArgv */ if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) { (void) fprintf(stderr, "\nUsage: %s [] [ ...] \n", pname); (void) fprintf(stderr, " %s [-help]\n\n", pname); exit(EXIT_FAILURE); } output_file = argv[argc-1]; /* Get the list of input files either from the command line or from a file, or report an error if both are specified */ nfiles = argc - 2; if (filelist == NULL) { infiles = &argv[1]; } else if (nfiles <= 0) { infiles = read_file_names(filelist, &nfiles); if (infiles == NULL) { (void) fprintf(stderr, "Error reading in file names from file \"%s\"\n", filelist); exit(EXIT_FAILURE); } } else { (void) fprintf(stderr, "Do not specify both -filelist and input file names\n"); exit(EXIT_FAILURE); } /* Make sure that we have something to process */ if (nfiles == 0) { (void) fprintf(stderr, "No input files specified\n"); exit(EXIT_FAILURE); } /* Save the input file names */ *num_input_files = nfiles; *input_files = infiles; /* Check that a dimension name was given if coords are specified */ concat_info->coords_specified = ((dimension_start != DBL_MAX) || (dimension_step != DBL_MAX) || (dimension_width != DBL_MAX) || (dimension_coords.numvalues > 0) || (dimension_widths.numvalues > 0)); if ((dimension_name == NULL) && concat_info->coords_specified) { (void) fprintf(stderr, "A dimension name must be specified if dimension coords are given.\n"); exit(EXIT_FAILURE); } /* Check that step and start are given */ if (((dimension_start != DBL_MAX) && (dimension_step == DBL_MAX)) || ((dimension_start == DBL_MAX) && (dimension_step != DBL_MAX))) { (void) fprintf(stderr, "Both dimension start and step must be given.\n"); exit(EXIT_FAILURE); } /* Check for either regular or irregular spacing of coords */ if ((dimension_step != DBL_MAX) && (dimension_coords.numvalues > 0)) { (void) fprintf(stderr, "Specify either dimension step or coords.\n"); exit(EXIT_FAILURE); } /* Check for either regular or irregular widths */ if ((dimension_width != DBL_MAX) && (dimension_widths.numvalues > 0)) { (void) fprintf(stderr, "Specify either dimension width or width list.\n"); exit(EXIT_FAILURE); } /* Check that we have the same number of coords and widths */ if ((dimension_coords.numvalues > 0) && (dimension_widths.numvalues > 0) && (dimension_coords.numvalues != dimension_widths.numvalues)) { (void) fprintf(stderr, "Specify the same number of coordinates and widths.\n"); exit(EXIT_FAILURE); } /* Check that we have the same number of coordinates and files */ if ((dimension_coords.numvalues > 0) && (dimension_coords.numvalues != *num_input_files)) { (void) fprintf(stderr, "Number of coordinates does not match number of input files.\n"); exit(EXIT_FAILURE); } if ((file_offsets.numvalues > 0) && (file_offsets.numvalues != *num_input_files)) { (void) fprintf(stderr, "Number of file offsets does not match number of input files.\n"); exit(EXIT_FAILURE); } /* Set defaults for start and step */ if (dimension_start == DBL_MAX) dimension_start = 0; if (dimension_step == DBL_MAX) dimension_step = 1; /* Save the appropriate values in the concat_info structure */ concat_info->output_file = output_file; concat_info->num_input_files = *num_input_files; concat_info->history = history; if (clobber) { concat_info->cflags = NC_CLOBBER; } else { concat_info->cflags = NC_NOCLOBBER; } #if MINC2 if (minc2_format) { concat_info->cflags |= MI2_CREATE_V2; } #endif /* MINC2 */ concat_info->verbose = verbose; concat_info->max_memory_use_in_kb = max_chunk_size_in_kb; concat_info->check_dim_info = check_dim_info; concat_info->output_datatype = datatype; concat_info->output_is_signed = is_signed; concat_info->output_valid_range[0] = valid_range[0]; concat_info->output_valid_range[1] = valid_range[1]; if (dimension_name != NULL) concat_info->dimension_name = strdup(dimension_name); else concat_info->dimension_name = NULL; concat_info->output_mincid = MI_ERROR; concat_info->output_icvid = MI_ERROR; /* Fill in coordinate info. We allocate space even if coordinates aren't specified just in case we can't get the info from the files. */ concat_info->num_file_coords = malloc(sizeof(int) * (*num_input_files)); concat_info->file_coords = malloc(sizeof(void *) * (*num_input_files)); concat_info->file_widths = malloc(sizeof(void *) * (*num_input_files)); concat_info->file_offsets = malloc(sizeof(double) * (*num_input_files)); for (ifile=0; ifile < *num_input_files; ifile++) { concat_info->num_file_coords[ifile] = 1; concat_info->file_coords[ifile] = malloc(sizeof(double)); concat_info->file_coords[ifile][0] = ((dimension_coords.numvalues > 0) ? dimension_coords.values[ifile] : dimension_start + dimension_step * ifile); if ((dimension_widths.numvalues > 0) || (dimension_width != DBL_MAX)) { concat_info->file_widths[ifile] = malloc(sizeof(double)); concat_info->file_widths[ifile][0] = ((dimension_widths.numvalues > 0) ? dimension_widths.values[ifile] : dimension_width); } else concat_info->file_widths[ifile] = NULL; concat_info->file_offsets[ifile] = (ifile < file_offsets.numvalues) ? file_offsets.values[ifile] : 0.0; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_double_list @INPUT : dst - client data passed by ParseArgv key - matching key in argv nextarg - argument following key in argv @OUTPUT : (none) @RETURNS : TRUE since nextarg is used. @DESCRIPTION: Gets a list (array) of double values. @METHOD : @GLOBALS : @CALLS : @CREATED : March 8, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_double_list(char *dst, char *key, char *nextarg) { #define VECTOR_SEPARATOR ',' int num_elements; int num_alloc; double *double_list; double dvalue; char *cur, *end, *prev; Double_Array *double_array; /* Check for a following argument */ if (nextarg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get pointers to array variables */ double_array = (Double_Array *) dst; /* Set up pointers to end of string and first non-space character */ end = nextarg + strlen(nextarg); cur = nextarg; while (isspace(*cur)) cur++; num_elements = 0; num_alloc = 0; double_list = NULL; /* Loop through string looking for doubles */ while (cur!=end) { /* Get double */ prev = cur; dvalue = strtod(prev, &cur); if (cur == prev) { (void) fprintf(stderr, "expected vector of doubles for \"%s\", but got \"%s\"\n", key, nextarg); exit(EXIT_FAILURE); } /* Add the value to the list */ num_elements++; if (num_elements > num_alloc) { num_alloc += 20; if (double_list == NULL) { double_list = malloc(num_alloc * sizeof(*double_list)); } else { double_list = realloc(double_list, num_alloc * sizeof(*double_list)); } } double_list[num_elements-1] = dvalue; /* Skip any spaces */ while (isspace(*cur)) cur++; /* Skip an optional comma */ if (*cur == VECTOR_SEPARATOR) cur++; } /* Update the global variables */ double_array->numvalues = num_elements; if (double_array->values != NULL) { free(double_array->values); } double_array->values = double_list; return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_concat_dim_name @INPUT : concat_info - concatenation information first_filename - name of first input file @OUTPUT : first_mincid - mincid for first input file @RETURNS : (nothing) @DESCRIPTION: Routine to get the name of the concatenation dimension, if necessary. @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_concat_dim_name(Concat_Info *concat_info, char *first_filename, int *first_mincid) { char *filename; int created_tempfile; int input_mincid, imgid, dimid; int ndims, dim[MAX_VAR_DIMS], min_ndims; char dimname[MAX_NC_NAME]; /* Expand the file header and open the file */ filename = miexpand_file(first_filename, NULL, TRUE, &created_tempfile); input_mincid = miopen(filename, NC_NOWRITE); if (created_tempfile) { (void) remove(filename); } free(filename); *first_mincid = input_mincid; /* Do we have to get the dimension name from the file? */ if (concat_info->dimension_name == NULL) { concat_info->dimension_in_input_file = TRUE; imgid = ncvarid(input_mincid, MIimage); (void) ncvarinq(input_mincid, imgid, NULL, NULL, &ndims, dim, NULL); min_ndims = 3; if (ndims > 0) { (void) ncdiminq(input_mincid, dim[ndims-1], dimname, NULL); if (strcmp(dimname, MIvector_dimension) == 0) min_ndims++; } if (ndims < min_ndims) { (void) fprintf(stderr, "Cannot concatentate along image dimensions.\n"); exit(EXIT_FAILURE); } (void) ncdiminq(input_mincid, dim[0], dimname, NULL); concat_info->dimension_name = strdup(dimname); } /* If the dimension name is given, then check the file */ else { dimid = get_image_dimension_id(input_mincid, concat_info->dimension_name); concat_info->dimension_in_input_file = (dimid != MI_ERROR); } /* If the dimension is in the file, then check that no coordinate info was given on the command line */ if (concat_info->dimension_in_input_file && concat_info->coords_specified) { (void) fprintf(stderr, "Do not specify coordinates for a dimension in the input files.\n"); exit(EXIT_SUCCESS); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_input_file_info @INPUT : caller_data - pointer to concat_info structure input_mincid - id of input minc file input_curfile - number of current input file loop_info - pointer to structure containing loop information @OUTPUT : caller_data - updated concat_info structure @RETURNS : (nothing) @DESCRIPTION: Routine to get information from each input file. @METHOD : @GLOBALS : @CALLS : @CREATED : March 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_input_file_info(void *caller_data, int input_mincid, int input_curfile, Loop_Info *loop_info) { Concat_Info *concat_info; int varid, dimid; int ndims, dim[MAX_VAR_DIMS]; char dimname[MAX_NC_NAME], string[MI_MAX_ATTSTR_LEN]; long dimlength; int regular; double dimstart, dimstep, dimwidth; long index; /* Get the concat_info structure pointer */ concat_info = (Concat_Info *) caller_data; /* Check that the concatenation dimension is present */ dimid = get_image_dimension_id(input_mincid, concat_info->dimension_name); if ((concat_info->dimension_in_input_file && (dimid == MI_ERROR)) || (!concat_info->dimension_in_input_file && (dimid != MI_ERROR))) { (void) fprintf(stderr, "Concatenation dimension is not present in all files.\n"); exit(EXIT_FAILURE); } /* Get information on the concatenation dimension coordinates */ if (concat_info->dimension_in_input_file) { /* Allocate the arrays */ (void) ncdiminq(input_mincid, dimid, dimname, &dimlength); concat_info->num_file_coords[input_curfile] = dimlength; free(concat_info->file_coords[input_curfile]); concat_info->file_coords[input_curfile] = malloc(sizeof(double) * dimlength); /* Set defaults */ if (!Sort_sequential || (input_curfile < 1)) { dimstart = 0; } else { index = concat_info->num_file_coords[input_curfile-1] - 1; dimstart = concat_info->file_coords[input_curfile-1][index] + 1; } dimstep = 1; regular = TRUE; /* Look for dimension variable */ ncopts = 0; varid = ncvarid(input_mincid, dimname); if (!Sort_sequential && (varid != MI_ERROR)) { /* Find out if its regular or irregular */ (void) ncvarinq(input_mincid, varid, NULL, NULL, &ndims, dim, NULL); regular = !((ndims == 1) && (dim[0] = dimid)); if (miattgetstr(input_mincid, varid, MIspacing, sizeof(string), string) != NULL) { if (strcmp(string, MI_IRREGULAR) == 0) regular = FALSE; else if (strcmp(string, MI_REGULAR) == 0) regular = TRUE; } /* Expand whole file if irregular dimension */ if (!regular) { ncopts = NC_OPTS_VAL; input_mincid = get_info_whole_file(loop_info); ncopts = 0; } /* Otherwise just get start and step */ else { (void) miattget1(input_mincid, varid, MIstart, NC_DOUBLE, &dimstart); (void) miattget1(input_mincid, varid, MIstep, NC_DOUBLE, &dimstep); } } /* If dimension variable exists */ /* Loop through indices, getting values */ for (index=0; index < dimlength; index++) { concat_info->file_coords[input_curfile][index] = dimstart + dimstep * index; if (!regular) { (void) mivarget1(input_mincid, varid, &index, NC_DOUBLE, NULL, &concat_info->file_coords[input_curfile][index]); } concat_info->file_coords[input_curfile][index] += concat_info->file_offsets[input_curfile]; } /* Look for dimension width variable */ (void) strcat(dimname, DIM_WIDTH_SUFFIX); varid = ncvarid(input_mincid, dimname); if (varid != MI_ERROR) { /* Set default width */ dimwidth = dimstep; /* Find out if its regular or irregular */ (void) ncvarinq(input_mincid, varid, NULL, NULL, &ndims, dim, NULL); regular = !((ndims == 1) && (dim[0] = dimid)); if (miattgetstr(input_mincid, varid, MIspacing, sizeof(string), string) != NULL) { if (strcmp(string, MI_IRREGULAR) == 0) regular = FALSE; else if (strcmp(string, MI_REGULAR) == 0) regular = TRUE; } /* Expand whole file if irregular dimension */ if (!regular) { ncopts = NC_OPTS_VAL; input_mincid = get_info_whole_file(loop_info); ncopts = 0; } /* Otherwise just get width */ else { (void) miattget1(input_mincid, varid, MIwidth, NC_DOUBLE, &dimwidth); } /* Allocate space for widths */ concat_info->file_widths[input_curfile] = malloc(sizeof(double) * dimlength); /* Loop through indices, getting values */ for (index=0; index < dimlength; index++) { concat_info->file_widths[input_curfile][index] = dimwidth; if (!regular) { (void) mivarget1(input_mincid, varid, &index, NC_DOUBLE, NULL, &concat_info->file_widths[input_curfile][index]); } } } /* If dimension width variable exists */ ncopts = NC_OPTS_VAL; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_image_dimension_id @INPUT : input_mincid - id of input minc file dimension_name - name of dimension @OUTPUT : (none) @RETURNS : id of dimension in image variable or MI_ERROR if dimension does not subscript the image. @DESCRIPTION: Routine to get the id of a dimension in a minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : March 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_image_dimension_id(int input_mincid, char *dimension_name) { int dimid, ndims, dim[MAX_VAR_DIMS], idim; int found; ncopts = 0; dimid = ncdimid(input_mincid, dimension_name); ncopts = NC_OPTS_VAL; if (dimid == MI_ERROR) return MI_ERROR; /* Get image variable info */ (void) ncvarinq(input_mincid, ncvarid(input_mincid, MIimage), NULL, NULL, &ndims, dim, NULL); /* Check to see if the dimension subscripts the image */ found = FALSE; for (idim=0; idim < ndims; idim++) { if (dimid == dim[idim]) found = TRUE; } /* Return appropriate value */ if (found) return dimid; else return MI_ERROR; } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_concat @INPUT : caller_data - pointer to concat_info structure num_voxels - number of voxels to handle input_num_buffers - number of input buffers input_vector_length - number of input vector elements to handle input_data - array of pointers to input buffers output_num_buffers - number of output buffers output_vector_length - number of output vector elements to handle loop_info - pointer to loop info structure @OUTPUT : output_data - array of pointers to output buffers @RETURNS : (nothing) @DESCRIPTION: Routine to do the concatenation work @METHOD : @GLOBALS : @CALLS : @CREATED : March 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_concat(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Concat_Info *concat_info; int input_mincid, output_mincid, outimgid, inimgid, varid, invarid; int ifile; int icoord; long mindex; char dimname[MAX_NC_NAME]; long instart[MAX_VAR_DIMS], incount[MAX_VAR_DIMS]; long outstart[MAX_VAR_DIMS], outcount[MAX_VAR_DIMS]; long mmstart[MAX_VAR_DIMS]; int inndims, indim[MAX_VAR_DIMS], dimid; int idim, odim, imm; char *varname; double value; /* Check that the arguments are as expected */ if ((input_num_buffers != 1) || (output_num_buffers != 0)) { (void) fprintf(stderr, "Unexpected arguments to do_concat!!!\n"); exit(EXIT_FAILURE); } /* Cast caller_data into concat_info pointer */ concat_info = (Concat_Info *) caller_data; /* Get the mincid for the current input file */ input_mincid = get_info_current_mincid(loop_info); ifile = get_info_current_file(loop_info); icoord = get_info_current_index(loop_info); inimgid = ncvarid(input_mincid, MIimage); /* Check if output file has been created */ if (concat_info->output_mincid == MI_ERROR) { /* Sort the coords */ sort_coords(concat_info); /* Create the output file */ create_concat_file(input_mincid, concat_info); } /* Get output file info */ output_mincid = concat_info->output_mincid; mindex = concat_info->file_to_dim_order[ifile][icoord]; outimgid = ncvarid(output_mincid, MIimage); /* Write out the coordinates info */ varid = ncvarid(output_mincid, concat_info->dimension_name); (void) mivarput1(output_mincid, varid, &mindex, NC_DOUBLE, NULL, &concat_info->file_coords[ifile][icoord]); if (concat_info->have_widths) { (void) strcat(strcpy(dimname, concat_info->dimension_name), DIM_WIDTH_SUFFIX); varid = ncvarid(output_mincid, dimname); (void) mivarput1(output_mincid, varid, &mindex, NC_DOUBLE, NULL, &concat_info->file_widths[ifile][icoord]); } /* Convert the input shape info into output shape info */ get_info_shape(loop_info, MAX_VAR_DIMS, instart, incount); outstart[0] = mindex; outcount[0] = 1; odim = 1; (void) ncvarinq(input_mincid, inimgid, NULL, NULL, &inndims, indim, NULL); if (concat_info->dimension_in_input_file) dimid = ncdimid(input_mincid, concat_info->dimension_name); else dimid = MI_ERROR; for (idim=0; idim < inndims; idim++) { if (indim[idim] != dimid) { outstart[odim] = instart[idim]; outcount[odim] = incount[idim]; odim++; } } /* Copy the image max and min info from the input file */ for (imm=0; imm < 2; imm++) { if (imm == 0) { varname = MIimagemin; value = 0.0; } else { varname = MIimagemax; value = 1.0; } ncopts = 0; invarid = ncvarid(input_mincid, varname); ncopts = NC_OPTS_VAL; if (invarid != MI_ERROR) { (void) mitranslate_coords(input_mincid, inimgid, instart, invarid, mmstart); (void) mivarget1(input_mincid, invarid, mmstart, NC_DOUBLE, NULL, &value); } varid = ncvarid(output_mincid, varname); (void) mitranslate_coords(output_mincid, outimgid, outstart, varid, mmstart); (void) mivarput1(output_mincid, varid, mmstart, NC_DOUBLE, NULL, &value); /* Save global min and max */ if (value < concat_info->global_minimum) concat_info->global_minimum = value; if (value > concat_info->global_maximum) concat_info->global_maximum = value; } /* Copy the data */ (void) miicv_put(concat_info->output_icvid, outstart, outcount, input_data[0]); } /* ----------------------------- MNI Header ----------------------------------- @NAME : sort_coords @INPUT : concat_info - pointer to structure containing concat info @OUTPUT : concat_info - ordering information initialized (file_to_dim_order) @RETURNS : (nothing) @DESCRIPTION: Routine to do sort the coordinates and store the appropriate information. @METHOD : @GLOBALS : @CALLS : @CREATED : March 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void sort_coords(Concat_Info *concat_info) { int ifile; Sort_Element *sort_list; int concat_dimension_length; int index, icoord; double mean_step, mean_width, diff; int regular_spacing, constant_width, have_widths; /* Allocate space for the ordering information */ concat_info->file_to_dim_order = malloc(sizeof(void *) * (concat_info->num_input_files)); concat_dimension_length = 0; for (ifile=0; ifile < concat_info->num_input_files; ifile++) { concat_dimension_length += concat_info->num_file_coords[ifile]; concat_info->file_to_dim_order[ifile] = malloc(sizeof(int) * concat_info->num_file_coords[ifile]); } concat_info->concat_dimension_length = concat_dimension_length; /* Set up sorting stuff */ sort_list = malloc(sizeof(Sort_Element) * concat_dimension_length); index = 0; for (ifile=0; ifile < concat_info->num_input_files; ifile++) { for (icoord=0; icoord < concat_info->num_file_coords[ifile]; icoord++) { sort_list[index].coord = concat_info->file_coords[ifile][icoord]; sort_list[index].curfile = ifile; sort_list[index].curcoord = icoord; index++; } } /* Do sort */ qsort(sort_list, (size_t) concat_dimension_length, sizeof(Sort_Element), sort_function); /* Store results of sort and figure out whether we have a regular spacing and a constant width */ if (concat_dimension_length > 1) { mean_step = (sort_list[concat_dimension_length-1].coord - sort_list[0].coord) / (double) (concat_dimension_length - 1); } else { mean_step = 1; } if (concat_info->file_widths[0] != NULL) mean_width = concat_info->file_widths[0][0]; regular_spacing = TRUE; constant_width = TRUE; have_widths = TRUE; for (index=0; index < concat_dimension_length; index++) { ifile = sort_list[index].curfile; icoord = sort_list[index].curcoord; if ((ifile < 0) || (ifile >= concat_info->num_input_files) || (icoord < 0) || (icoord >= concat_info->num_file_coords[ifile])) { (void) fprintf(stderr, "Serious sorting bug!!!!\n"); exit(EXIT_FAILURE); } concat_info->file_to_dim_order[ifile][icoord] = index; if (concat_info->file_widths[ifile] == NULL) have_widths = FALSE; if (index > 0) { diff = (sort_list[index].coord - sort_list[index-1].coord) - mean_step; if (mean_step != 0) diff = diff / mean_step; diff = ABS(diff); if (diff > COORD_EPSILON) regular_spacing = FALSE; if (have_widths) { diff = (concat_info->file_widths[ifile][icoord] - mean_width); if (mean_width != 0) diff = diff / mean_width; diff = ABS(diff); if (diff > COORD_EPSILON) constant_width = FALSE; } } } concat_info->regular_spacing = regular_spacing; concat_info->constant_width = constant_width; concat_info->have_widths = have_widths; concat_info->dim_step = mean_step; concat_info->dim_start = sort_list[0].coord; } /* ----------------------------- MNI Header ----------------------------------- @NAME : sort_function @INPUT : value1, value2 - two values to compare @OUTPUT : (none) @RETURNS : -1, 0, 1 for value1 <, ==, > value2 @DESCRIPTION: Routine to do do comparisons of Sort_Elements for qsort. @METHOD : @GLOBALS : @CALLS : @CREATED : March 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int sort_function(const void *value1, const void *value2) { Sort_Element *element1, *element2; int return_value; element1 = (Sort_Element *) value1; element2 = (Sort_Element *) value2; if (element1->coord < element2->coord) return_value = -1; else if (element1->coord > element2->coord) return_value = 1; else if (element1->curfile < element2->curfile) return_value = -1; else if (element1->curfile > element2->curfile) return_value = 1; else if (element1->curcoord < element2->curcoord) return_value = -1; else if (element1->curcoord > element2->curcoord) return_value = 1; else return_value = 0; if (!Sort_ascending) return_value *= -1; return return_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_concat_file @INPUT : inmincid - id of sample input file concat_info - pointer to structure containing concat info @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to create the output concatentated minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : March 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void create_concat_file(int inmincid, Concat_Info *concat_info) { int outmincid, outimgid, inimgid, coordid, widthid, invarid; int maxid, minid, icvid; int in_ndims, indim[MAX_VAR_DIMS], idim; int out_ndims, outdim[MAX_VAR_DIMS], out_nimgdims; int nexcluded, excluded_vars[20]; nc_type datatype; char dimname[MAX_NC_NAME]; long dimlength; double valid_range[2]; /* Create the file */ outmincid = micreate(concat_info->output_file, concat_info->cflags); /* Get image variable id for input file */ inimgid = ncvarid(inmincid, MIimage); /* Get the list of dimensions subscripting the image variable */ (void) ncvarinq(inmincid, inimgid, NULL, &datatype, &in_ndims, indim, NULL); /* Figure out how many image dimensions we have */ out_nimgdims = 2; if (in_ndims < out_nimgdims) { (void) fprintf(stderr, "Not enough dimensions in input file.\n"); exit(EXIT_FAILURE); } (void) ncdiminq(inmincid, indim[in_ndims-1], dimname, NULL); if (strcmp(dimname, MIvector_dimension) == 0) out_nimgdims++; /* Set up the output minc file */ /* Create the concatenation dimension */ out_ndims = 0; outdim[out_ndims] = ncdimdef(outmincid, concat_info->dimension_name, (long) concat_info->concat_dimension_length); ncopts = 0; coordid = micreate_std_variable(outmincid, concat_info->dimension_name, NC_DOUBLE, 1, &outdim[out_ndims]); ncopts = NC_OPTS_VAL; if (coordid == MI_ERROR) coordid = ncvardef(outmincid, concat_info->dimension_name, NC_DOUBLE, 1, &outdim[out_ndims]); ncopts = 0; invarid = ncvarid(inmincid, concat_info->dimension_name); if (invarid != MI_ERROR) (void) micopy_all_atts(inmincid, invarid, outmincid, coordid); ncopts = NC_OPTS_VAL; (void) miattputstr(outmincid, coordid, MIspacing, (concat_info->regular_spacing ? MI_REGULAR : MI_IRREGULAR)); (void) miattputdbl(outmincid, coordid, MIstart, concat_info->dim_start); (void) miattputdbl(outmincid, coordid, MIstep, concat_info->dim_step); if (concat_info->have_widths) { (void) strcat(strcpy(dimname, concat_info->dimension_name), DIM_WIDTH_SUFFIX); ncopts = 0; widthid = micreate_std_variable(outmincid, dimname, NC_DOUBLE, 1, &outdim[out_ndims]); ncopts = NC_OPTS_VAL; if (widthid == MI_ERROR) widthid = ncvardef(outmincid, dimname, NC_DOUBLE, 1, &outdim[out_ndims]); ncopts = 0; invarid = ncvarid(inmincid, dimname); if (invarid != MI_ERROR) (void) micopy_all_atts(inmincid, invarid, outmincid, widthid); (void) ncattdel(outmincid, widthid, MIwidth); ncopts = NC_OPTS_VAL; (void) miattputstr(outmincid, widthid, MIspacing, (concat_info->constant_width ? MI_REGULAR : MI_IRREGULAR)); if (concat_info->constant_width) (void) miattputdbl(outmincid, widthid, MIwidth, concat_info->file_widths[0][0]); } out_ndims++; /* Loop, creating output dimensions */ for (idim=0; idim < in_ndims; idim++) { /* Get the dimension info from the input file */ (void) ncdiminq(inmincid, indim[idim], dimname, &dimlength); /* Check that this is not the concat dimension */ if (strcmp(dimname, concat_info->dimension_name) != 0) { /* Copy the dimension */ outdim[out_ndims] = ncdimdef(outmincid, dimname, dimlength); out_ndims++; } } /* Copy other variables in file */ nexcluded = 0; ncopts = 0; excluded_vars[nexcluded] = inimgid; if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; excluded_vars[nexcluded] = ncvarid(inmincid, MIimagemax); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; excluded_vars[nexcluded] = ncvarid(inmincid, MIimagemin); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; (void) strcpy(dimname, concat_info->dimension_name); excluded_vars[nexcluded] = ncvarid(inmincid, dimname); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; (void) strcat(dimname, DIM_WIDTH_SUFFIX); excluded_vars[nexcluded] = ncvarid(inmincid, dimname); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; (void) micopy_all_var_defs(inmincid, outmincid, nexcluded, excluded_vars); ncopts = NC_OPTS_VAL; /* Add the time stamp to the history */ update_history(outmincid, concat_info->history); /* Create the image-min/max variables */ maxid = micreate_std_variable(outmincid, MIimagemax, NC_DOUBLE, out_ndims-out_nimgdims, outdim); minid = micreate_std_variable(outmincid, MIimagemin, NC_DOUBLE, out_ndims-out_nimgdims, outdim); ncopts = 0; (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemax), outmincid, maxid); (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemin), outmincid, minid); ncopts = NC_OPTS_VAL; /* Create the image variable */ if (concat_info->output_datatype != MI_ORIGINAL_TYPE) { datatype = concat_info->output_datatype; } concat_info->is_floating_type = ((datatype == NC_FLOAT) || (datatype == NC_DOUBLE)); outimgid = micreate_std_variable(outmincid, MIimage, datatype, out_ndims, outdim); (void) micopy_all_atts(inmincid, inimgid, outmincid, outimgid); if (concat_info->is_floating_type) { ncopts = 0; (void) ncattdel(outmincid, outimgid, MIsigntype); ncopts = NC_OPTS_VAL; valid_range[0] = 0; valid_range[1] = 1; (void) miset_valid_range(outmincid, outimgid, valid_range); } if (concat_info->output_datatype != MI_ORIGINAL_TYPE) { if (concat_info->output_is_signed) (void) miattputstr(outmincid, outimgid, MIsigntype, MI_SIGNED); else (void) miattputstr(outmincid, outimgid, MIsigntype, MI_UNSIGNED); if (concat_info->output_valid_range[1] > concat_info->output_valid_range[0]) { (void) miset_valid_range(outmincid, outimgid, concat_info->output_valid_range); } else { ncopts = 0; (void) ncattdel(outmincid, outimgid, MIvalid_range); ncopts = NC_OPTS_VAL; } } (void) miattputstr(outmincid, outimgid, MIcomplete, MI_FALSE); /* Put the file in data mode */ (void) ncsetfill(outmincid, NC_NOFILL); (void) ncendef(outmincid); /* Copy over variable values */ ncopts = 0; (void) micopy_all_var_values(inmincid, outmincid, nexcluded, excluded_vars); ncopts = NC_OPTS_VAL; /* Create the icv and attach it */ icvid = miicv_create(); (void) miicv_setint(icvid, MI_ICV_TYPE, NC_DOUBLE); (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); (void) miicv_attach(icvid, outmincid, outimgid); /* Return the file and icv id's */ concat_info->output_mincid = outmincid; concat_info->output_icvid = icvid; } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_history @INPUT : mincid - id of output minc file arg_string - string giving list of arguments @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to update the history global variable in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void update_history(int mincid, char *arg_string) { nc_type datatype; int att_length; char *string; /* Get the history attribute length */ ncopts=0; if ((ncattinq(mincid, NC_GLOBAL, MIhistory, &datatype, &att_length) == MI_ERROR) || (datatype != NC_CHAR)) att_length = 0; att_length += strlen(arg_string) + 1; /* Allocate a string and get the old history */ string = malloc(att_length); string[0] = '\0'; (void) miattgetstr(mincid, NC_GLOBAL, MIhistory, att_length, string); ncopts = NC_OPTS_VAL; /* Add the new command and put the new history. */ (void) strcat(string, arg_string); (void) miattputstr(mincid, NC_GLOBAL, MIhistory, string); free(string); } minc-2.2.00/progs/mincconvert/0000755000265600003100000000000012030114723013171 500000000000000minc-2.2.00/progs/mincconvert/mincconvert.man10000644000265600003100000000367312027132662016237 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MINCCONVERT 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincconvert \- convert between MINC 1 to MINC 2 format. .SH SYNOPSIS .B mincconvert .BI [-clobber] .BI [-2] .BI infile .BI outfile .P .B mincconvert .BI -help .SH DESCRIPTION \fImincconvert\fR copies the input file to the output file, possibly converting the file from MINC 1 to MINC 2 format, or vice versa. With the \fB\-template\fR flag, \fImincconvert\fR creates a "template" volume from the input MINC volume. The template volume preserves all of the structure (dimensions, variables, and attributes) of the input MINC volume but omits all data. Any attempt to read data will return zeroes. The resulting file is typically much shorter than a normal MINC volume, and may be useful for scripts which want to carry such structural information forward into their output files. As a hint to future programmers and users, this program places a special global attribute in the file, with the name \fBclass\fR and the value \fBtemplate\fR. .SH OPTIONS .TP \fB\-2\fR Create a MINC 2 format file .TP \fB\-clobber\fR Overwrite a pre-existing output file. \fB\-help\fR Print a summary of command line options and exit .TP \fB\-template\fR Create a template file. .TP \fB-compress\fR \fIN\fR Compress file with compression level \fIN\fR. Valid compression levels are 0 for no compression to 9 for maximum compression. The option has no effect if the output file is a MINC 1 file. .TP \fB\-chunk\fR \fIM\fR Store file in a block-structured arrangement, using hypercubes of edge length \fIM\fR. The option has no effect if the output file is a MINC 1 file. .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Bert Vincent - bert@bic.mni.mcgill.ca .SH COPYRIGHTS Copyright \(co 2003 by Robert Vincent and the Montreal Neurological Institute. minc-2.2.00/progs/mincconvert/mincconvert.c0000644000265600003100000001475112027132662015624 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincconvert @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to convert between MINC 1.0 and MINC 2.0 formats. @METHOD : @GLOBALS : @CALLS : @CREATED : 2003-12-17 @MODIFIED : * $Log: mincconvert.c,v $ * Revision 1.10 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 1.9 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 1.8 2007/12/10 13:25:12 rotor * * few more fixes for CMake build * * started adding static to globals for a wierd zlib bug * * Revision 1.7 2007/08/09 17:05:25 rotor * * added some fixes of Claudes for chunking and internal compression * * Revision 1.6 2006/07/28 16:49:55 baghdadi * added message to disallow conversion to itself and exit with success * * Revision 1.6 2006/06/21 11:30:00 Leila * added return value for main function * Revision 1.5 2006/04/10 11:30:00 Leila * check the version of file and Abort if converting to itself! * Revision 1.4 2005/08/26 21:07:17 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 1.3 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 1.2 2004/09/09 19:25:32 bert * Force V1 file format creation if -2 not specified * * Revision 1.1 2004/04/27 15:27:57 bert * Initial checkin, MINC 1 <-> MINC 2 converter * * @COPYRIGHT : Copyright 2003 Robert Vincent, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include static int clobber = 0; static int v2format = 0; static int do_template = 0; static int compress = -1; static int chunking = -1; ArgvInfo argTable[] = { {"-clobber", ARGV_CONSTANT, (char *) 1, (char *) &clobber, "Overwrite existing file."}, {"-2", ARGV_CONSTANT, (char *) 1, (char *) &v2format, "Create a MINC 2 output file."}, {"-template", ARGV_CONSTANT, (char *) 1, (char *)&do_template, "Create a template file."}, {"-compress", ARGV_INT, (char *) 1, (char *)&compress, "Set the compression level, from 0 (disabled) to 9 (maximum)."}, {"-chunk", ARGV_INT, (char *) 1, (char *)&chunking, "Set the target block size for chunking (-1 unknown, 0 default, >1 block size)."}, {NULL, ARGV_END, NULL, NULL, NULL} }; int micopy(int old_fd, int new_fd, char *new_history, int is_template) { if (is_template) { /* Tell NetCDF that we don't want to allocate the data until written. */ ncsetfill(new_fd, NC_NOFILL); } /* Copy all variable definitions (and global attributes). */ micopy_all_var_defs(old_fd, new_fd, 0, NULL); /* Append the updated history. */ miappend_history(new_fd, new_history); if (!is_template) { ncendef(new_fd); micopy_all_var_values(old_fd, new_fd, 0, NULL); } else { /* This isn't really standard, but flag this as a template file. */ miattputstr(new_fd, NC_GLOBAL, "class", "template"); } return (MI_NOERROR); } /* Main program */ int main(int argc, char **argv) { char *old_fname; char *new_fname; int old_fd; int new_fd; int flags; #if MINC2 struct mi2opts opts; #endif /* MINC2 */ char *new_history = time_stamp(argc, argv); /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc != 3)) { fprintf(stderr, "\nUsage: %s [] \n", argv[0]); fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } old_fname = argv[1]; new_fname = argv[2]; old_fd = miopen(old_fname, NC_NOWRITE); if (old_fd < 0) { perror(old_fname); exit(EXIT_FAILURE); } /* check the version of file and Abort if converting to itself */ if (MI2_ISH5OBJ(old_fd)) { if (v2format && compress <= 0 ) { /* If already a minc2 file, allow to do compression if requested by the user. Ideally, one should call the HDF5 function H5Pget_deflate to query the compression level of the input image, but this function does not seem to be supported anymore in HDF5. */ fprintf(stderr,"Abort: Converting Version 2 (HDF5) to itself!! \n"); exit(EXIT_FAILURE); } } else { if (!v2format) { fprintf(stderr,"Abort: Converting Version 1 (netCDF) to itself!! \n"); exit(EXIT_FAILURE); } } flags = 0; if (clobber) { flags |= NC_CLOBBER; } else { flags |= NC_NOCLOBBER; } #if MINC2 if (v2format) { flags |= MI2_CREATE_V2; } else { flags |= MI2_CREATE_V1; /* Force V1 format */ } opts.struct_version = MI2_OPTS_V1; if (compress == -1) { opts.comp_type = MI2_COMP_UNKNOWN; } else if (compress == 0) { opts.comp_type = MI2_COMP_NONE; } else { opts.comp_type = MI2_COMP_ZLIB; opts.comp_param = compress; } if (chunking == -1) { opts.chunk_type = MI2_CHUNK_UNKNOWN; } else if (chunking == 0) { opts.chunk_type = MI2_CHUNK_OFF; } else { opts.chunk_type = MI2_CHUNK_ON; opts.chunk_param = chunking; } new_fd = micreatex(new_fname, flags, &opts); if (new_fd < 0) { perror(new_fname); exit(EXIT_FAILURE); } #else new_fd = micreate(new_fname, flags); #endif /* not MINC2 */ micopy(old_fd, new_fd, new_history, do_template); miclose(old_fd); miclose(new_fd); free(new_history); exit(EXIT_SUCCESS); } minc-2.2.00/progs/minccopy/0000755000265600003100000000000012030114723012463 500000000000000minc-2.2.00/progs/minccopy/minccopy.man10000644000265600003100000000225012027132662015011 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MINCCOPY 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME minccopy \- copy minc image values from one minc file to another .SH SYNOPSIS .B minccopy .BI [-pixel_values] .BI [-real_values] .BI infile .BI outfile .SH DESCRIPTION \fIminccopy\fR copies image values from one minc file to another. Both the input and output files must exist, and the images in both files must have an equal number dimensions and equal dimension lengths. By default the \fIreal\fR value of each pixel is copied. Use the \fB\-pixel_values\fR to copy the pixel values instead. \fBNOTE\fR: This program is intended primarily for use with scripts such as \fBmincedit\fR. It does not follow the typical design rules of most MINC command-line tools and therefore should be used only with caution. .SH OPTIONS .TP \fB\-pixel_values\fR Copy voxel values in raw mode. .TP \fB\-real_values\fR Copy voxel intensities (default). .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print version number of program and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 by Peter Neelin minc-2.2.00/progs/minccopy/minccopy.c0000644000265600003100000001601212027132662014400 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minccopy @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to copy minc image values from one minc file to another (both files must exist). @METHOD : @GLOBALS : @CALLS : @CREATED : May 13, 1993 (Peter Neelin) @MODIFIED : * $Log: minccopy.c,v $ * Revision 6.6 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.5 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.4 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.3 2006/05/19 00:35:58 bert * Add config.h to several files that might need it * * Revision 6.2 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.1 1999/10/19 14:45:20 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:34 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:34 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:35 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:08 neelin * Release of minc version 0.3 * * Revision 2.1 1995/01/23 12:42:00 neelin * Change ncopen, ncclose to miopen, miclose. * * Revision 2.0 94/09/28 10:33:54 neelin * Release of minc version 0.2 * * Revision 1.7 94/09/28 10:33:51 neelin * Pre-release * * Revision 1.6 93/08/11 15:18:00 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Variables used for argument parsing */ static int copy_pixel_values = FALSE; /* Argument table */ ArgvInfo argTable[] = { {"-pixel_values", ARGV_CONSTANT, (char *) TRUE, (char *) ©_pixel_values, "Copy pixel values as is."}, {"-real_values", ARGV_CONSTANT, (char *) FALSE, (char *) ©_pixel_values, "Copy real pixel intensities (default)."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *infilename, *outfilename; int inminc, outminc, inimg, outimg, inicv, outicv; int ndims, outndims, indims[MAX_VAR_DIMS], outdims[MAX_VAR_DIMS]; nc_type indatatype, outdatatype; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS], end[MAX_VAR_DIMS]; long length, size; int idim; void *data; /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc != 3)) { (void) fprintf(stderr, "\nUsage: %s [] \n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } infilename = argv[1]; outfilename = argv[2]; /* Open the files */ inminc = miopen(infilename, NC_NOWRITE); outminc = miopen(outfilename, NC_WRITE); /* Inquire about the image variables */ inimg = ncvarid(inminc, MIimage); outimg = ncvarid(outminc, MIimage); (void) ncvarinq(inminc, inimg, NULL, &indatatype, &ndims, indims, NULL); (void) ncvarinq(outminc, outimg, NULL, &outdatatype, &outndims, outdims, NULL); /* If copying pixel values as is, then check that types are the same */ if (copy_pixel_values && (indatatype != outdatatype)) { (void) fprintf(stderr, "%s: Input and output datatypes must be the same for exact pixel copies.\n", argv[0]); exit(EXIT_FAILURE); } /* Check number of dimensions */ if (ndims != outndims) { (void) fprintf(stderr, "%s: Input and output files have different number of image dimensions.\n", argv[0]); exit(EXIT_FAILURE); } /* Set input file start, count and end vectors for reading a slice at a time. Check dimension sizes */ for (idim=0; idim < ndims; idim++) { (void) ncdiminq(inminc, indims[idim], NULL, &end[idim]); (void) ncdiminq(outminc, outdims[idim], NULL, &length); if (end[idim] != length) { (void) fprintf(stderr, "%s: Input and output files have different image dimensions\n", argv[0]); exit(EXIT_FAILURE); } } (void) miset_coords(ndims, (long) 0, start); (void) miset_coords(ndims, (long) 1, count); if (copy_pixel_values) size = nctypelen(indatatype); else size = nctypelen(NC_DOUBLE); for (idim=ndims-2; idim < ndims; idim++) { count[idim] = end[idim]; size *= count[idim]; } /* Allocate space */ data = malloc(size); /* Set up image conversion */ if (!copy_pixel_values) { inicv = miicv_create(); (void) miicv_setint(inicv, MI_ICV_TYPE, NC_DOUBLE); (void) miicv_setint(inicv, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(inicv, MI_ICV_USER_NORM, TRUE); (void) miicv_attach(inicv, inminc, inimg); outicv = miicv_create(); (void) miicv_setint(outicv, MI_ICV_TYPE, NC_DOUBLE); (void) miicv_setint(outicv, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(outicv, MI_ICV_USER_NORM, TRUE); (void) miicv_attach(outicv, outminc, outimg); } /* Loop over input slices */ while (start[0] < end[0]) { /* Read and write slice */ if (copy_pixel_values) { (void) ncvarget(inminc, inimg, start, count, data); (void) ncvarput(outminc, outimg, start, count, data); } else { (void) miicv_get(inicv, start, count, data); (void) miicv_put(outicv, start, count, data); } /* Increment start counter */ idim = ndims-1; start[idim] += count[idim]; while ( (idim>0) && (start[idim] >= end[idim])) { start[idim] = 0; idim--; start[idim] += count[idim]; } } /* End loop over slices */ /* Clean up */ (void) miclose(outminc); (void) miclose(inminc); if (!copy_pixel_values) { (void) miicv_free(outicv); (void) miicv_free(inicv); } free(data); exit(EXIT_SUCCESS); } minc-2.2.00/progs/mincdiff/0000755000265600003100000000000012030114721012417 500000000000000minc-2.2.00/progs/mincdiff/mincdiff0000755000265600003100000000605012027132662014057 00000000000000#! /bin/sh # # Script to find differences between minc files # # Usage: mincdiff [-l] [diff options] # # Modifications: # $Log: mincdiff,v $ # Revision 6.3 2000-09-12 15:22:06 neelin # Removed copyright notice. # # Revision 6.2 2000/09/12 15:11:04 neelin # Rewrite in Bourne shell by Steve Robbins. Addition of -header and -body # options, plus allowing of diff options. # # Revision 6.1 1999/10/19 14:45:20 neelin # Fixed Log subsitutions for CVS # # Revision 6.0 1997/09/12 13:23:46 neelin # Release of minc version 0.6 # # Revision 5.0 1997/08/21 13:24:47 neelin # Release of minc version 0.5 # # Revision 4.0 1997/05/07 20:01:01 neelin # Release of minc version 0.4 # # Revision 3.0 1995/05/15 19:31:40 neelin # Release of minc version 0.3 # # Revision 2.1 1995/01/24 09:12:29 neelin # Added support for compressed minc files. # # Revision 2.0 94/09/28 10:34:46 neelin # Release of minc version 0.2 # # Revision 1.4 94/09/28 10:34:44 neelin # Pre-release # # Revision 1.3 94/07/18 10:41:26 neelin # Added -nonormalize option to mincextract for comparing image data. # # Revision 1.2 93/11/01 16:50:03 neelin # Some fixes. # die () { echo >&2 $@ exit 1 } header_diff=yes header_diff_opt= body_cmp=yes body_cmp_opt= while test $# -gt 2; do case $1 in -header) header_diff=yes; body_cmp=no ;; -body) header_diff=no; body_cmp=yes ;; -l) body_cmp_opt=-l ;; -*) header_diff_opt="$header_diff_opt $1" ;; *) break; esac shift done test $# -eq 2 || die "Usage: $0 [-header|-body] [-l] [diff options] " if test x$TMPDIR = x; then for TMPDIR in /usr/tmp /var/tmp /tmp; do test -d $TMPDIR && break; done fi test -d $TMPDIR || die "TMPDIR $TMPDIR does not exist." # Files created tmp1="$TMPDIR/mincdiff-$$-tmp1" tmp2="$TMPDIR/mincdiff-$$-tmp2" header1="$TMPDIR/mincdiff-$$-header1" header2="$TMPDIR/mincdiff-$$-header2" body1="$TMPDIR/mincdiff-$$-body1" body2="$TMPDIR/mincdiff-$$-body2" # Clean up upon exit trap "/bin/rm -f $tmp1 $tmp2 $header1 $header2 $body1 $body2" 0 1 2 15 # Expand the files dumpfile1=`mincexpand $1 $tmp1 -name_only` dumpfile2=`mincexpand $2 $tmp2 -name_only` # Dump the headers and compare them if test $header_diff = yes; then mincheader $dumpfile1 > $header1 || exit 1 mincheader $dumpfile2 > $header2 || exit 1 diff $header_diff_opt $header1 $header2 diff_status=$? else diff_status=0 fi # Dump the raw data and compare them if test $body_cmp = yes; then echo "Binary image comparison:" mincextract -nonormalize -file $dumpfile1 > $body1 \ || die "Error extracting image data from $dumpfile1" mincextract -nonormalize -file $dumpfile2 > $body2 \ || die "Error extracting image data from $dumpfile2" cmp $body_cmp_opt $body1 $body2 \ && echo "Images are identical." cmp_status=$? else cmp_status=0 fi # Exit with SUCCESS if and only if the parts (header and/or body) # that we compared are identical. test $diff_status -eq 0 -a $cmp_status -eq 0 minc-2.2.00/progs/mincdiff/mincdiff.man10000644000265600003100000000216712027132662014714 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MINCDIFF 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincdiff \- report differences between minc files .SH SYNOPSIS .B mincdiff .BI [-header|-body] .BI [-l] .BI [diff\ options] .BI file1 .BI file2 .SH DESCRIPTION The \fImincdiff\fR shell script compares two minc files by running \fBdiff(1)\fR on the headers of the two minc files, and \fBcmp(1)\fR on the image variable. You can view only the header differences using \fB\-header\fR or only the body (image variable) differences using \fB\-body\fR. The option \fB\-l\fR is passed on to \fBcmp\fR of the image variable. Any unrecognized options (e.g. -u) are passed verbatim to the \fBdiff\fR of the headers. .SH OPTIONS .TP \fB\-header\fR Compare only the headers of the two files. .TP \fB\-body\fR Compare only the image data of the two files. .TP \fB\-l\fR Print the byte offset in decimal and the byte value in octal for each difference encountered in the image variable. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 by Peter Neelin .SH "SEE ALSO" .IR diff (1), .IR cmp (1). minc-2.2.00/progs/mincdump/0000755000265600003100000000000012030114723012456 500000000000000minc-2.2.00/progs/mincdump/mincdump.h0000644000265600003100000000435412027132662014401 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincdump/mincdump.h,v 1.1 2004-04-27 15:35:15 bert Exp $ *********************************************************************/ /* error checking macro */ #define NC_CHECK(status) {\ int nc_status = status;\ if(nc_status < 0)\ error(nc_strerror(nc_status));\ } #define Printf (void) printf typedef int boolean; enum {false=0, true=1}; struct ncdim { /* dimension */ char name[NC_MAX_NAME]; long size; }; struct ncvar { /* variable */ char name[NC_MAX_NAME]; nc_type type; int ndims; int dims[MAX_VAR_DIMS]; int natts; boolean has_fillval; double fillval; }; struct ncatt { /* attribute */ int var; char name[NC_MAX_NAME]; nc_type type; int len; char *string; /* for text attributes (type = NC_CHAR) */ double *vals; /* for numeric attributes of all types */ }; typedef enum {LANG_C, LANG_F} Nclang; struct fspec { /* specification for how to format dump */ char *name; /* name specified with -n or derived from * file name */ boolean header_only; /* if true, don't print any variable data */ boolean coord_vals; /* if true, print header and coordinate * dimension values (values of variables * that are also dimensions), but no other * variable data */ boolean brief_data_cmnts; /* if true, put // comments in data section * identifying variable and indices, useful * for navigating through large * multi-dimensional data lists. */ boolean full_data_cmnts; /* if true, put // comments in data section * identifying every value, useful for * navigating through large * multi-dimensional data lists. */ Nclang data_lang; /* Specifies index conventions used in data * comments, either LANG_C (C, 0-based, * column major) or LANG_F (Fortran, * 1-based, row major) */ int nlvars; /* Number of variables specified with -v * option on command line */ char** lvars; /* list of variable names specified with -v * option on command line */ }; minc-2.2.00/progs/mincdump/dumplib.h0000644000265600003100000000410112027132662014207 00000000000000/********************************************************************* * Copyright 1993, University Corporation for Atmospheric Research * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincdump/dumplib.h,v 1.1 2004-04-27 15:35:15 bert Exp $ *********************************************************************/ extern char *progname; /* for error messages */ #define NO_NETCDF_2 /* assert we aren't using any netcdf-2 stuff */ #ifndef EXIT_FAILURE #ifndef vms #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 #else #define EXIT_SUCCESS 1 #define EXIT_FAILURE 0 #endif #endif #define FLT_DIGITS 7 /* default sig. digits for float data */ #define DBL_DIGITS 15 /* default sig. digits for double data */ extern int float_precision_specified; /* -p option specified float precision */ extern int double_precision_specified; /* -p option specified double precision */ extern char float_var_fmt[]; extern char double_var_fmt[]; extern char float_att_fmt[]; extern char double_att_fmt[]; #ifdef __cplusplus extern "C" { #endif /* Print error message to stderr and exit */ extern void error ( const char *fmt, ... ); /* set position in line before lput() calls */ extern void set_indent ( int indent ); /* set maximum line length */ extern void set_max_len ( int len ); /* splits lines to keep them short */ extern void lput ( const char *string ); /* In case different formats specified with -d option, set them here. */ extern void set_formats ( int flt_digs, int dbl_digs ); /* Determine print format to use for each value for this variable. */ char * get_fmt ( int ncid, int varid, nc_type type ); /* structure for list of variables specified with -v option */ struct vnode { struct vnode* next; int id; }; typedef struct vnode vnode; /* Get new variable list */ extern vnode* newvlist ( void ); /* Add a variable id to variable list */ extern void varadd ( vnode* vlist, int varid ); /* Test if a variable id is in variable list */ extern int varmember ( const vnode* vlist, int varid ); #ifdef __cplusplus } #endif minc-2.2.00/progs/mincdump/vardata.h0000644000265600003100000000166612027132662014212 00000000000000/********************************************************************* * Copyright 1993, University Corporation for Atmospheric Research * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincdump/vardata.h,v 1.1 2004-04-27 15:35:15 bert Exp $ *********************************************************************/ extern char *progname; /* for error messages */ /* Display for user-defined fill values and default floating-point fill values; should match what ncgen looks for in ../ncgen/ncgen.l */ #define FILL_STRING "_" #ifdef __cplusplus extern "C" { #endif /* Output the data for a single variable, in CDL syntax. */ extern int vardata ( const struct ncvar*, /* variable */ long [], /* variable dimension lengths */ int, /* netcdf id */ int, /* variable id */ const struct fspec* /* formatting specs */ ); #ifdef __cplusplus } #endif minc-2.2.00/progs/mincdump/mincdump.c0000644000265600003100000004563712027132662014405 00000000000000/********************************************************************* * Copyright 1993, University Corporation for Atmospheric Research * See netcdf/README file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincdump/mincdump.c,v 1.10 2008-01-11 07:17:08 stever Exp $ *********************************************************************/ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "mincdump.h" #include "dumplib.h" #include "vardata.h" static void usage(void); static char* name_path(const char* path); static char* type_name(nc_type type); static void tztrim(char* ss); static void pr_att_string(long len, const char* string); static void pr_att_vals(nc_type type, long len, const void * vals); static void pr_att(int ncid, int varid, const char *varname, int ia); static void do_ncdump(char* path, struct fspec* specp); int main(int argc, char** argv); #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) char *progname; static void usage(void) { #define USAGE "\ [-c] Coordinate variable data and header information\n\ [-h] Header information only, no data\n\ [-v var1[,...]] Data for variable(s) ,... only\n\ [-b [c|f]] Brief annotations for C or Fortran indices in data\n\ [-f [c|f]] Full annotations for C or Fortran indices in data\n\ [-l len] Line length maximum in data section (default 80)\n\ [-n name] Name for netCDF (default derived from file name)\n\ [-p n[,n]] Display floating-point values with less precision\n\ file File name of input netCDF file\n" (void) fprintf(stderr, "%s [-c|-h] [-v ...] [[-b|-f] [c|f]] [-l len] [-n name] [-p n[,n]] file\n%s", progname, USAGE); (void) fprintf(stderr, "netcdf library version %s\n", nc_inq_libvers()); exit(EXIT_FAILURE); } /* * convert pathname of netcdf file into name for cdl unit, by taking * last component of path and stripping off any extension. */ static char * name_path(const char *path) { const char *cp; char *new; char *sp; #ifdef vms #define FILE_DELIMITER ']' #endif #ifdef MSDOS #define FILE_DELIMITER '\\' #endif #ifndef FILE_DELIMITER /* default to unix */ #define FILE_DELIMITER '/' #endif cp = strrchr(path, FILE_DELIMITER); if (cp == 0) /* no delimiter */ cp = path; else /* skip delimeter */ cp++; new = (char *) malloc((unsigned) (strlen(cp)+1)); if (new == 0) { error("out of memory!"); } (void) strcpy(new, cp); /* copy last component of path */ if ((sp = strrchr(new, '.')) != NULL) *sp = '\0'; /* strip off any extension */ return new; } static char * type_name(nc_type type) { switch (type) { case NC_BYTE: return "byte"; case NC_CHAR: return "char"; case NC_SHORT: return "short"; case NC_INT: return "int"; case NC_FLOAT: return "float"; case NC_DOUBLE: return "double"; default: error("type_name: bad type %d", type); return "bogus"; } } /* * Remove trailing zeros (after decimal point) but not trailing decimal * point from ss, a string representation of a floating-point number that * might include an exponent part. */ static void tztrim(char *ss) { char *cp, *ep; cp = ss; if (*cp == '-') cp++; while(isdigit((int)*cp) || *cp == '.') cp++; if (*--cp == '.') return; ep = cp+1; while (*cp == '0') cp--; cp++; if (cp == ep) return; while (*ep) *cp++ = *ep++; *cp = '\0'; return; } /* * Print attribute string, for text attributes. */ static void pr_att_string( long len, const char *string ) { int iel; const char *cp; const char *sp; unsigned char uc; cp = string; Printf ("\""); /* adjust len so trailing nulls don't get printed */ sp = cp + len - 1; while (len != 0 && *sp-- == '\0') len--; for (iel = 0; iel < len; iel++) switch (uc = *cp++ & 0377) { case '\b': Printf ("\\b"); break; case '\f': Printf ("\\f"); break; case '\n': /* generate linebreaks after new-lines */ Printf ("\\n\",\n\t\t\t\""); break; case '\r': Printf ("\\r"); break; case '\t': Printf ("\\t"); break; case '\v': Printf ("\\v"); break; case '\\': Printf ("\\\\"); break; case '\'': Printf ("\\'"); break; case '\"': Printf ("\\\""); break; default: Printf ("%c",uc); break; } Printf ("\""); } /* * Print list of attribute values, for numeric attributes. Attribute values * must be printed with explicit type tags, because CDL doesn't have explicit * syntax to declare an attribute type. */ static void pr_att_vals( nc_type type, long len, const void *vals ) { int iel; signed char sc; short ss; int ii; char gps[30]; float ff; double dd; /* See if we would prefer to handle this as a string. */ if (type == NC_BYTE && len > 2) { int isstring = 1; int ch; ch = ((signed char *)vals)[len-1]; if (isprint(ch) || ch == '\0' || ch == '\n') { for (iel = 0; iel < len-1; iel++) { ch = ((signed char *)vals)[iel]; if (!isprint(ch) && ch != '\n') { isstring = 0; break; } } if (isstring) { pr_att_string(len, vals); return; } } } if (len == 0) return; for (iel = 0; iel < len-1; iel++) { switch (type) { case NC_BYTE: sc = ((signed char *) vals)[iel] & 0377; Printf ("%db, ", sc); break; case NC_SHORT: ss = ((short *)vals)[iel]; Printf ("%ds, ", ss); break; case NC_INT: ii = ((int *)vals)[iel]; Printf ("%d, ", ii); break; case NC_FLOAT: ff = ((float *)vals)[iel]; (void) sprintf(gps, float_att_fmt, ff); tztrim(gps); /* trim trailing 0's after '.' */ Printf ("%s, ", gps); break; case NC_DOUBLE: dd = ((double *)vals)[iel]; (void) sprintf(gps, double_att_fmt, dd); tztrim(gps); Printf ("%s, ", gps); break; default: error("pr_att_vals: bad type"); } } switch (type) { case NC_BYTE: sc = ((signed char *) vals)[iel] & 0377; Printf ("%db", sc); break; case NC_SHORT: ss = ((short *)vals)[iel]; Printf ("%ds", ss); break; case NC_INT: ii = ((int *)vals)[iel]; Printf ("%d", ii); break; case NC_FLOAT: ff = ((float *)vals)[iel]; (void) sprintf(gps, float_att_fmt, ff); tztrim(gps); Printf ("%s", gps); break; case NC_DOUBLE: dd = ((double *)vals)[iel]; (void) sprintf(gps, double_att_fmt, dd); tztrim(gps); Printf ("%s", gps); break; default: error("pr_att_vals: bad type"); } } static void pr_att( int ncid, int varid, const char *varname, int ia ) { struct ncatt att; /* attribute */ ncattname(ncid, varid, ia, att.name); Printf ("\t\t%s:%s = ", varname, att.name); ncattinq(ncid, varid, att.name, &att.type, &att.len); if (att.len == 0) { /* show 0-length attributes as empty strings */ att.type = NC_CHAR; /* att.len = 1; */ } switch (att.type) { case NC_CHAR: att.string = (char *) malloc(att.len + 1); /* + 1 for null byte */ if (!att.string) { error("Out of memory!"); NC_CHECK( ncclose(ncid) ); return; } *att.string = '\0'; /* Initialize in case att.len == 0 */ ncattget(ncid, varid, att.name, att.string ); pr_att_string(att.len, att.string); free(att.string); break; default: att.vals = (double *) malloc(att.len * sizeof(double)); if (!att.vals) { error("Out of memory!"); NC_CHECK( ncclose(ncid) ); return; } ncattget(ncid, varid, att.name, att.vals ); pr_att_vals(att.type, att.len, att.vals); free(att.vals); break; } Printf (" ;\n"); } static void do_ncdump(char *path, struct fspec* specp) { int ndims; /* number of dimensions */ int nvars; /* number of variables */ int ngatts; /* number of global attributes */ int xdimid; /* id of unlimited dimension */ int dimid; /* dimension id */ int varid; /* variable id */ struct ncdim dims[NC_MAX_DIMS]; /* dimensions */ long vdims[NC_MAX_DIMS]; /* dimension sizes for a single variable */ struct ncvar var; /* variable */ struct ncatt att; /* attribute */ int id; /* dimension number per variable */ int ia; /* attribute number */ int iv; /* variable number */ int is_coord; /* true if variable is a coordinate variable */ int ncid; /* netCDF id */ vnode* vlist = 0; /* list for vars specified with -v option */ int nc_status; int old_nc_opts; ncid = miopen(path, NC_NOWRITE); if (ncid < 0) { error("%s: can't open\n", path); } /* * If any vars were specified with -v option, get list of associated * variable ids */ if (specp->nlvars > 0) { vlist = newvlist(); /* list for vars specified with -v option */ for (iv=0; iv < specp->nlvars; iv++) { varid = ncvarid(ncid, specp->lvars[iv]); varadd(vlist, varid); } } /* if name not specified, derive it from path */ if (specp->name == (char *)0) { specp->name = name_path (path); } if (MI2_ISH5OBJ(ncid)) { Printf ("hdf5 %s {\n", specp->name); } else { Printf ("netcdf %s {\n", specp->name); } /* * get number of dimensions, number of variables, number of global * atts, and dimension id of unlimited dimension, if any */ nc_status = ncinquire(ncid, &ndims, &nvars, &ngatts, &xdimid); /* get dimension info */ if (ndims > 0) Printf ("dimensions:\n"); for (dimid = 0; dimid < ndims; dimid++) { NC_CHECK(ncdiminq(ncid, dimid, dims[dimid].name, &dims[dimid].size)); if (dimid == xdimid) Printf ("\t%s = %s ; // (%ld currently)\n",dims[dimid].name, "UNLIMITED", (long)dims[dimid].size); else Printf ("\t%s = %ld ;\n", dims[dimid].name, (long)dims[dimid].size); } if (nvars > 0) Printf ("variables:\n"); /* get variable info, with variable attributes */ for (varid = 0; varid < nvars; varid++) { NC_CHECK(ncvarinq(ncid, varid, var.name, &var.type, &var.ndims, var.dims, &var.natts)); Printf ("\t%s %s", type_name(var.type), var.name); if (var.ndims > 0) Printf ("("); for (id = 0; id < var.ndims; id++) { Printf ("%s%s", dims[var.dims[id]].name, id < var.ndims-1 ? ", " : ")"); } Printf (" ;\n"); /* get variable attributes */ for (ia = 0; ia < var.natts; ia++) pr_att(ncid, varid, var.name, ia); /* print ia-th attribute */ } /* get global attributes */ if (ngatts > 0) Printf ("\n// global attributes:\n"); for (ia = 0; ia < ngatts; ia++) pr_att(ncid, NC_GLOBAL, "", ia); /* print ia-th global attribute */ if (! specp->header_only) { if (nvars > 0) { Printf ("data:\n"); } /* output variable data */ for (varid = 0; varid < nvars; varid++) { /* if var list specified, test for membership */ if (specp->nlvars > 0 && ! varmember(vlist, varid)) continue; NC_CHECK( ncvarinq(ncid, varid, var.name, &var.type, &var.ndims, var.dims, &var.natts) ); if (specp->coord_vals) { /* Find out if this is a coordinate variable */ is_coord = 0; for (dimid = 0; dimid < ndims; dimid++) { if (strcmp(dims[dimid].name, var.name) == 0 && var.ndims == 1) { is_coord = 1; break; } } if (! is_coord) /* don't get data for non-coordinate vars */ continue; } /* * Only get data for variable if it is not a record variable, * or if it is a record variable and at least one record has * been written. */ if (var.ndims == 0 || var.dims[0] != xdimid || dims[xdimid].size != 0) { /* Collect variable's dim sizes */ for (id = 0; id < var.ndims; id++) vdims[id] = dims[var.dims[id]].size; var.has_fillval = 1; /* by default, but turn off for bytes */ /* get _FillValue attribute */ old_nc_opts = ncopts; ncopts = 0; nc_status = ncattinq(ncid,varid,_FillValue,&att.type,&att.len); ncopts = old_nc_opts; if(nc_status == NC_NOERR && att.type == var.type && att.len == 1) { if(var.type == NC_CHAR) { char fillc; ncattget(ncid, varid, _FillValue, &fillc ); var.fillval = fillc; } else { ncattget(ncid, varid, _FillValue, &var.fillval); } } else { switch (var.type) { case NC_BYTE: /* don't do default fill-values for bytes, too risky */ var.has_fillval = 0; break; case NC_CHAR: var.fillval = NC_FILL_CHAR; break; case NC_SHORT: var.fillval = NC_FILL_SHORT; break; case NC_INT: var.fillval = NC_FILL_INT; break; case NC_FLOAT: var.fillval = NC_FILL_FLOAT; break; case NC_DOUBLE: var.fillval = NC_FILL_DOUBLE; break; default: break; } } if (vardata(&var, vdims, ncid, varid, specp) == -1) { error("can't output data for variable %s", var.name); NC_CHECK( miclose(ncid) ); if (vlist) free(vlist); return; } } } } Printf ("}\n"); NC_CHECK( miclose(ncid) ); if (vlist) free(vlist); } static void set_brief(struct fspec * fspecp, char *key, char *optarg) { fspecp->brief_data_cmnts = true; switch (tolower(optarg[0])) { case 'c': fspecp->data_lang = LANG_C; break; case 'f': fspecp->data_lang = LANG_F; break; default: error("invalid value for -b option: %s", optarg); } } static void set_full(struct fspec * fspecp, char *key, char *optarg) { fspecp->full_data_cmnts = true; switch (tolower(optarg[0])) { case 'c': fspecp->data_lang = LANG_C; break; case 'f': fspecp->data_lang = LANG_F; break; default: error("invalid value for -f option: %s", optarg); } } static int make_lvars(struct fspec * fspecp, char *key, char *optarg) { char *cp = optarg; int nvars = 1; char ** cpp; /* compute number of variable names in comma-delimited list */ fspecp->nlvars = 1; while (*cp++) if (*cp == ',') nvars++; fspecp->lvars = (char **) malloc(nvars * sizeof(char*)); if (!fspecp->lvars) { error("out of memory"); } cpp = fspecp->lvars; /* copy variable names into list */ for (cp = strtok(optarg, ","); cp != NULL; cp = strtok((char *) NULL, ",")) { *cpp = (char *) malloc(strlen(cp) + 1); if (!*cpp) { error("out of memory"); } strcpy(*cpp, cp); cpp++; } fspecp->nlvars = nvars; return 1; } /* * Extract the significant-digits specifiers from the -d argument on the * command-line and update the default data formats appropriately. */ static int set_sigdigs(char *dest, char *key, const char *optarg) { char *ptr1 = 0; char *ptr2 = 0; int flt_digits = FLT_DIGITS; /* default floating-point digits */ int dbl_digits = DBL_DIGITS; /* default double-precision digits */ if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',') flt_digits = (int)strtol(optarg, &ptr1, 10); if (flt_digits < 1 || flt_digits > 20) { error("unreasonable value for float significant digits: %d", flt_digits); } if (*ptr1 == ',') dbl_digits = (int)strtol(ptr1+1, &ptr2, 10); if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20) { error("unreasonable value for double significant digits: %d", dbl_digits); } set_formats(flt_digits, dbl_digits); return 1; } /* * Extract the significant-digits specifiers from the -p argument on the * command-line, set flags so we can override C_format attributes (if any), * and update the default data formats appropriately. */ static int set_precision(char *dest, char *key, const char *optarg) { char *ptr1 = 0; char *ptr2 = 0; int flt_digits = FLT_DIGITS; /* default floating-point digits */ int dbl_digits = DBL_DIGITS; /* default double-precision digits */ if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',') { flt_digits = (int)strtol(optarg, &ptr1, 10); float_precision_specified = 1; } if (flt_digits < 1 || flt_digits > 20) { error("unreasonable value for float significant digits: %d", flt_digits); } if (*ptr1 == ',') { dbl_digits = (int) strtol(ptr1+1, &ptr2, 10); double_precision_specified = 1; } if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20) { error("unreasonable value for double significant digits: %d", dbl_digits); } set_formats(flt_digits, dbl_digits); return 1; } int main(int argc, char *argv[]) { static struct fspec fspec = /* defaults, overridden on command line */ { 0, /* construct netcdf name from file name */ false, /* print header info only, no data? */ false, /* just print coord vars? */ false, /* brief comments in data section? */ false, /* full annotations in data section? */ LANG_C, /* language conventions for indices */ 0, /* if -v specified, number of variables */ 0 /* if -v specified, list of variable names */ }; int i; static int max_len = 80; /* default maximum line length */ static ArgvInfo argTable[] = { {"-b", ARGV_FUNC, (char *) set_brief, (char *) &fspec, "Brief annotations for C or Fortran indices in data" }, {"-c", ARGV_CONSTANT, (char *) true, (char *) &fspec.coord_vals, "Coordinate variable data and header information" }, {"-d", ARGV_FUNC, (char *) set_sigdigs, (char *) NULL, "Obsolete option for setting significant digits" }, {"-f", ARGV_FUNC, (char *) set_full, (char *) &fspec, "Full annotations for C or Fortran indices in data" }, {"-h", ARGV_CONSTANT, (char *) true, (char *) &fspec.header_only, "Header information only, no data" }, {"-l", ARGV_INT, (char *) 1, (char *) &max_len, "Line length maximum in data section (default 80)" }, {"-n", ARGV_STRING, (char *) 1, (char *) &fspec.name, "Name for netCDF (default derived from file name)" }, {"-p", ARGV_FUNC, (char *) set_precision, (char *) NULL, "Display floating-point values with less precision" }, {"-v", ARGV_FUNC, (char *) make_lvars, (char *) &fspec, "Data for variable(s) ,... only" }, {NULL, ARGV_END, NULL, NULL, NULL} }; progname = argv[0]; set_formats(FLT_DIGITS, DBL_DIGITS); /* default for float, double data */ if (ParseArgv(&argc, argv, argTable, 0)) { usage(); } set_max_len(max_len); argc--; argv++; i = 0; do { if (argc > 0) do_ncdump(argv[i], &fspec); } while (++i < argc); #ifdef vms exit(EXIT_SUCCESS); #else return EXIT_SUCCESS; #endif } minc-2.2.00/progs/mincdump/vardata.c0000644000265600003100000005465712027132662014215 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincdump/vardata.c,v 1.5 2009-01-20 11:58:13 rotor Exp $ *********************************************************************/ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #ifndef NO_FLOAT_H #include /* for FLT_EPSILON, DBL_EPSILON */ #endif /* NO_FLOAT_H */ #include #include "mincdump.h" #include "dumplib.h" #include "vardata.h" static float float_epsilon(void); static double double_epsilon(void); static void init_epsilons(void); static void printbval(char* sout, const char* fmt, const struct ncvar* varp, signed char val); static void printsval(char* sout, const char* fmt, const struct ncvar* varp, short val); static void printival(char* sout, const char* fmt, const struct ncvar* varp, int val); static void printfval(char* sout, const char* fmt, const struct ncvar* varp, float val); static void printdval(char* sout, const char* fmt, const struct ncvar* varp, double val); static void lastdelim(boolean more, boolean lastrow); static void annotate(const struct ncvar* vp, const struct fspec* fsp, const long* cor, long iel); static void pr_tvals(const struct ncvar *vp, long len, const char *fmt, boolean more, boolean lastrow, const char *vals, const struct fspec* fsp, const long *cor); static void pr_bvals(const struct ncvar *vp, long len, const char *fmt, boolean more, boolean lastrow, const signed char *vals, const struct fspec* fsp, const long *cor); static void pr_svals(const struct ncvar *vp, long len, const char *fmt, boolean more, boolean lastrow, const short *vals, const struct fspec* fsp, const long *cor); static void pr_ivals(const struct ncvar *vp, long len, const char *fmt, boolean more, boolean lastrow, const int *vals, const struct fspec* fsp, const long *cor); static void pr_fvals(const struct ncvar *vp, long len, const char *fmt, boolean more, boolean lastrow, const float *vals, const struct fspec* fsp, const long *cor); static void pr_dvals(const struct ncvar *vp, long len, const char *fmt, boolean more, boolean lastrow, const double *vals, const struct fspec* fsp, const long *cor); static int upcorner(const long* dims, int ndims, long* odom, const long* add); static void lastdelim2 (boolean more, boolean lastrow); #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) static float float_eps; static double double_eps; static float float_epsilon(void) { float float_eps; #ifndef NO_FLOAT_H float_eps = FLT_EPSILON; #else /* NO_FLOAT_H */ { float etop, ebot, eps; float one = 1.0; float two = 2.0; etop = 1.0; ebot = 0.0; eps = ebot + (etop - ebot)/two; while (eps != ebot && eps != etop) { float epsp1; epsp1 = one + eps; if (epsp1 > one) etop = eps; else ebot = eps; eps = ebot + (etop - ebot)/two; } float_eps = two * etop; } #endif /* NO_FLOAT_H */ return float_eps; } static double double_epsilon(void) { double double_eps; #ifndef NO_FLOAT_H double_eps = DBL_EPSILON; #else /* NO_FLOAT_H */ { double etop, ebot, eps; double one = 1.0; double two = 2.0; etop = 1.0; ebot = 0.0; eps = ebot + (etop - ebot)/two; while (eps != ebot && eps != etop) { double epsp1; epsp1 = one + eps; if (epsp1 > one) etop = eps; else ebot = eps; eps = ebot + (etop - ebot)/two; } double_eps = two * etop; } #endif /* NO_FLOAT_H */ return double_eps; } static void init_epsilons(void) { float_eps = float_epsilon(); double_eps = double_epsilon(); } /* * Output a value of a byte variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. */ static void printbval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const struct ncvar *varp, /* variable */ signed char val /* value */ ) { if (varp->has_fillval) { double fillval = varp->fillval; if(fillval == val) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } /* * Output a value of a short variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. */ static void printsval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const struct ncvar *varp, /* variable */ short val /* value */ ) { if (varp->has_fillval) { double fillval = varp->fillval; if(fillval == val) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } /* * Output a value of an int variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. */ static void printival( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const struct ncvar *varp, /* variable */ int val /* value */ ) { if (varp->has_fillval) { int fillval = (int)varp->fillval; if(fillval == val) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } #define absval(x) ( (x) < 0 ? -(x) : (x) ) /* * Output a value of a float variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. Floating-point fill values need only be within machine epsilon of * defined fill value. */ static void printfval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const struct ncvar *varp, /* variable */ float val /* value */ ) { if(varp->has_fillval) { double fillval = varp->fillval; if((val > 0) == (fillval > 0) && /* prevents potential overflow */ (absval(val - fillval) <= absval(float_eps * fillval))) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } /* * Output a value of a double variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. Floating-point fill values need only be within machine epsilon of * defined fill value. */ static void printdval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const struct ncvar *varp, /* variable */ double val /* value */ ) { if(varp->has_fillval) { double fillval = varp->fillval; if((val > 0) == (fillval > 0) && /* prevents potential overflow */ (absval(val - fillval) <= absval(double_eps * fillval))) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } /* * print last delimiter in each line before annotation (, or ;) */ static void lastdelim (boolean more, boolean lastrow) { if (more) { Printf(", "); } else { if(lastrow) { Printf(";"); } else { Printf(","); } } } /* * print last delimiter in each line before annotation (, or ;) */ static void lastdelim2 (boolean more, boolean lastrow) { if (more) { lput(", "); } else { if(lastrow) { lput(" ;"); lput("\n"); } else { lput(",\n"); lput(" "); } } } /* * Annotates a value in data section with var name and indices in comment */ static void annotate( const struct ncvar *vp, /* variable */ const struct fspec* fsp, /* formatting specs */ const long *cor, /* corner coordinates */ long iel /* which element in current row */ ) { int vrank = vp->ndims; int id; /* print indices according to data_lang */ (void) printf(" // %s(", vp->name); switch (fsp->data_lang) { case LANG_C: /* C variable indices */ for (id = 0; id < vrank-1; id++) Printf("%lu,", (unsigned long) cor[id]); Printf("%lu", (unsigned long) cor[id] + iel); break; case LANG_F: /* Fortran variable indices */ Printf("%lu", (unsigned long) cor[vrank-1] + iel + 1); for (id = vrank-2; id >=0 ; id--) { Printf(",%lu", 1 + (unsigned long) cor[id]); } break; } Printf(")\n "); } /* * Print a number of char variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_tvals( const struct ncvar *vp, /* variable */ long len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const char *vals, /* pointer to block of values */ const struct fspec* fsp, /* formatting specs */ const long *cor /* corner coordinates */ ) { long iel; const char *sp; unsigned char uc; char sout[100]; /* temporary string for each encoded output */ if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) { /* as string */ Printf("\""); /* adjust len so trailing nulls don't get printed */ sp = vals + len; while (len != 0 && *--sp == '\0') len--; for (iel = 0; iel < len; iel++) switch (uc = *vals++ & 0377) { case '\b': Printf("\\b"); break; case '\f': Printf("\\f"); break; case '\n': /* generate linebreaks after new-lines */ Printf("\\n\",\n \""); break; case '\r': Printf("\\r"); break; case '\t': Printf("\\t"); break; case '\v': Printf("\\v"); break; case '\\': Printf("\\\\"); break; case '\'': Printf("\\\'"); break; case '\"': Printf("\\\""); break; default: if (isprint(uc)) Printf("%c",uc); else Printf("\\%.3o",uc); break; } Printf("\""); if (fsp->full_data_cmnts) { lastdelim (more, lastrow); annotate (vp, fsp, (long *)cor, 0L); } } else { /* use format from C_format attribute */ for (iel = 0; iel < len-1; iel++) { if (fsp->full_data_cmnts) { Printf(fmt, *vals++); Printf(", "); annotate (vp, fsp, (long *)cor, iel); } else { (void) sprintf(sout, fmt, *vals++); (void) strcat(sout, ", "); lput(sout); } } if (fsp->full_data_cmnts) { Printf(fmt, *vals++); lastdelim (more, lastrow); annotate (vp, fsp, (long *)cor, iel); } else { (void) sprintf(sout, fmt, *vals++); lput(sout); } } if (!fsp->full_data_cmnts) { lastdelim2 (more, lastrow); } } /* * Print a number of byte variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_bvals( const struct ncvar *vp, /* variable */ long len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const signed char *vals, /* pointer to block of values */ const struct fspec* fsp, /* formatting specs */ const long *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printbval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printbval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of short variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_svals( const struct ncvar *vp, /* variable */ long len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const short *vals, /* pointer to block of values */ const struct fspec* fsp, /* formatting specs */ const long *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printsval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printsval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of int variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_ivals( const struct ncvar *vp, /* variable */ long len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const int *vals, /* pointer to block of values */ const struct fspec* fsp, /* formatting specs */ const long *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printival(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printival(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of float variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_fvals( const struct ncvar *vp, /* variable */ long len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const float *vals, /* pointer to block of values */ const struct fspec* fsp, /* formatting specs */ const long *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printfval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printfval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of double variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_dvals( const struct ncvar *vp, /* variable */ long len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const double *vals, /* pointer to block of values */ const struct fspec* fsp, /* formatting specs */ const long *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printdval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printdval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf("%s", sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Updates a vector of ints, odometer style. Returns 0 if odometer * overflowed, else 1. */ static int upcorner( const long *dims, /* The "odometer" limits for each dimension */ int ndims, /* Number of dimensions */ long * odom, /* The "odometer" vector to be updated */ const long * add /* A vector to "add" to odom on each update */ ) { int id; int ret = 1; for (id = ndims-1; id > 0; id--) { odom[id] += add[id]; if(odom[id] >= dims[id]) { odom[id-1]++; odom[id] -= dims[id]; } } odom[0] += add[0]; if (odom[0] >= dims[0]) ret = 0; return ret; } /* Output the data for a single variable, in CDL syntax. */ int vardata( const struct ncvar *vp, /* variable */ long vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid, /* variable id */ const struct fspec* fsp /* formatting specs */ ) { long cor[NC_MAX_DIMS]; /* corner coordinates */ long edg[NC_MAX_DIMS]; /* edges of hypercube */ long add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ #define VALBUFSIZ 1000 double vals[VALBUFSIZ] ; /* aligned buffer */ int gulp = VALBUFSIZ; int id; int ir; long nels; long ncols; long nrows; int vrank = vp->ndims; static int initeps = 0; /* printf format used to print each value */ char *fmt = get_fmt(ncid, varid, vp->type); if (!initeps) { /* make sure epsilons get initialized */ init_epsilons(); initeps = 1; } nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } if (vrank <= 1) { Printf("\n %s = ", vp->name); set_indent ((int)strlen(vp->name) + 4); } else { Printf("\n %s =\n ", vp->name); set_indent (2); } if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ for (ir = 0; ir < nrows; ir++) { /* * rather than just printing a whole row at once (which might exceed * the capacity of MSDOS platforms, for example), we break each row * into smaller chunks, if necessary. */ long corsav; int left = (int)ncols; boolean lastrow; if (vrank > 0) { corsav = cor[vrank-1]; if (fsp->brief_data_cmnts != false && vrank > 1 && left > 0) { /* print brief comment with indices range */ Printf("// %s(",vp->name); switch (fsp->data_lang) { case LANG_C: /* print brief comment with C variable indices */ for (id = 0; id < vrank-1; id++) Printf("%lu,", (unsigned long)cor[id]); if (vdims[vrank-1] == 1) Printf("0"); else Printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1); break; case LANG_F: /* print brief comment with Fortran variable indices */ if (vdims[vrank-1] == 1) Printf("1"); else Printf("1-%lu ", (unsigned long)vdims[vrank-1]); for (id = vrank-2; id >=0 ; id--) { Printf(",%lu", (unsigned long)(1 + cor[id])); } break; } Printf(")\n "); set_indent(4); } } lastrow = (boolean)(ir == nrows-1); while (left > 0) { long toget = left < gulp ? left : gulp; if (vrank > 0) edg[vrank-1] = toget; switch(vp->type) { case NC_CHAR: NC_CHECK( ncvarget(ncid, varid, cor, edg, (char *)vals) ); pr_tvals(vp, toget, fmt, left > toget, lastrow, (char *) vals, fsp, cor); break; case NC_BYTE: NC_CHECK( ncvarget(ncid, varid, cor, edg, (signed char *)vals) ); pr_bvals(vp, toget, fmt, left > toget, lastrow, (signed char *) vals, fsp, cor); break; case NC_SHORT: NC_CHECK( ncvarget(ncid, varid, cor, edg, (short *)vals) ); pr_svals(vp, toget, fmt, left > toget, lastrow, (short *) vals, fsp, cor); break; case NC_INT: NC_CHECK( ncvarget(ncid, varid, cor, edg, (int *)vals) ); pr_ivals(vp, toget, fmt, left > toget, lastrow, (int *) vals, fsp, cor); break; case NC_FLOAT: NC_CHECK( ncvarget(ncid, varid, cor, edg, (float *)vals) ); pr_fvals(vp, toget, fmt, left > toget, lastrow, (float *) vals, fsp, cor); break; case NC_DOUBLE: NC_CHECK( ncvarget(ncid, varid, cor, edg, (double *)vals) ); pr_dvals(vp, toget, fmt, left > toget, lastrow, (double *) vals, fsp, cor); break; default: error("vardata: bad type"); } left -= toget; if (vrank > 0) cor[vrank-1] += toget; } if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } return 0; } minc-2.2.00/progs/mincdump/dumplib.c0000644000265600003100000001150612027132662014211 00000000000000/********************************************************************* * Copyright 1993, University Corporation for Atmospheric Research * See netcdf/README file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincdump/dumplib.c,v 1.4 2008-01-12 19:08:15 stever Exp $ *********************************************************************/ #if HAVE_CONFIG_H #include "config.h" #endif /* * We potentially include before in order to obtain a * definition for va_list from the GNU C compiler. */ #include #include #include #include #include #include "dumplib.h" static char* has_c_format_att(int ncid, int varid); static vnode* newvnode(void); int float_precision_specified = 0; /* -p option specified float precision */ int double_precision_specified = 0; /* -p option specified double precision */ char float_var_fmt[] = "%.NNg"; char double_var_fmt[] = "%.NNg"; char float_att_fmt[] = "%#.NNgf"; char double_att_fmt[] = "%#.NNg"; /* * Print error message to stderr and exit */ void error(const char *fmt, ...) { va_list args ; (void) fprintf(stderr,"%s: ", progname); va_start(args, fmt) ; (void) vfprintf(stderr,fmt,args) ; va_end(args) ; (void) fprintf(stderr, "\n") ; (void) fflush(stderr); /* to ensure log files are current */ exit(EXIT_FAILURE); } #define LINEPIND " " /* indent of continued lines */ static int linep; static int max_line_len; void set_indent(int in) { linep = in; } void set_max_len(int len) { max_line_len = len-2; } void lput(const char *cp) { size_t nn = strlen(cp); if (nn+linep > max_line_len && nn > 2) { (void) fputs("\n", stdout); (void) fputs(LINEPIND, stdout); linep = (int)strlen(LINEPIND); } (void) fputs(cp,stdout); linep += nn; } /* In case different formats specified with -d option, set them here. */ void set_formats(int float_digits, int double_digits) { (void) sprintf(float_var_fmt, "%%.%dg", float_digits); (void) sprintf(double_var_fmt, "%%.%dg", double_digits); (void) sprintf(float_att_fmt, "%%#.%dgf", float_digits); (void) sprintf(double_att_fmt, "%%#.%dg", double_digits); } static char * has_c_format_att( int ncid, /* netcdf id */ int varid /* variable id */ ) { nc_type cfmt_type; int cfmt_len; #define C_FMT_NAME "C_format" /* name of C format attribute */ #define MAX_CFMT_LEN 100 /* max length of C format attribute */ static char cfmt[MAX_CFMT_LEN]; /* we expect nc_inq_att to fail if there is no "C_format" attribute */ int old_nc_opts; int nc_stat; old_nc_opts = ncopts; ncopts = 0; nc_stat = ncattinq(ncid, varid, "C_format", &cfmt_type, &cfmt_len); ncopts = old_nc_opts; if (nc_stat == -1) { return 0; } if (cfmt_type == NC_CHAR && cfmt_len != 0 && cfmt_len < MAX_CFMT_LEN) { nc_stat = ncattget(ncid, varid, "C_format", cfmt); if(nc_stat != 1) nc_advise("Getting 'C_format' attribute", nc_stat, ""); return &cfmt[0]; } return 0; } /* * Determine print format to use for each value for this variable. Use value * of attribute C_format if it exists, otherwise a sensible default. */ char * get_fmt( int ncid, /* netcdf id */ int varid, /* variable id */ nc_type type /* netCDF data type */ ) { char *c_format_att; /* float or double precision specified with -p option overrides any C_format attribute value, so check for that first. */ if (float_precision_specified && type == NC_FLOAT) return float_var_fmt; if (double_precision_specified && type == NC_DOUBLE) return double_var_fmt; /* If C_format attribute exists, return it */ c_format_att = has_c_format_att(ncid, varid); if (c_format_att) return c_format_att; /* Otherwise return sensible default. */ switch (type) { case NC_BYTE: return "%d"; case NC_CHAR: return "%s"; case NC_SHORT: return "%d"; case NC_INT: return "%d"; case NC_FLOAT: return float_var_fmt; case NC_DOUBLE: return double_var_fmt; default: error("pr_vals: bad type"); } return 0; } static vnode* newvnode(void) { vnode *newvp = (vnode*) malloc(sizeof(vnode)); if (!newvp) { error("out of memory!"); } return newvp; } /* * Get a new, empty variable list. */ vnode* newvlist(void) { vnode *vp = newvnode(); vp -> next = 0; vp -> id = -1; /* bad id */ return vp; } void varadd(vnode* vlist, int varid) { vnode *newvp = newvnode(); newvp -> next = vlist -> next; newvp -> id = varid; vlist -> next = newvp; } int varmember(const vnode* vlist, int varid) { vnode *vp = vlist -> next; for (; vp ; vp = vp->next) if (vp->id == varid) return 1; return 0; } minc-2.2.00/progs/mincedit/0000755000265600003100000000000012030114721012434 500000000000000minc-2.2.00/progs/mincedit/mincedit0000755000265600003100000001155712027132662014121 00000000000000#! /bin/sh # # Script to allow editing of minc files # # Usage: mincedit [] # # Modifications: # $Log: mincedit,v $ # Revision 6.9 2008-06-18 03:55:25 stever # Remove illegitimate escape sequences (\n) from echo statements. # See Debian bug 486048 for details. # # Revision 6.8 2008/02/05 13:48:45 rotor # * added code for checking VISUAL and EDITOR before falling back to emacs # # Revision 6.7 2008/01/16 00:45:34 rotor # * replaced mincdump -h with mincheader to preserver image ranges # # Revision 6.6 2008/01/09 14:42:24 rotor # * tidied up the man page and removed problematic errexit option # # Revision 6.5 2008/01/09 12:39:46 rotor # * added errexit option # # Revision 6.4 2008/01/09 12:31:08 rotor # * complete rewrite in sh # # Revision 6.3 2004/06/16 16:27:27 bert # Use mincgen instead of ncgen # # Revision 6.2 2000/09/12 15:43:37 neelin # Changed default TMPDIR to look for /var/tmp, /usr/tmp, /tmp. # # Revision 6.1 1999/10/19 14:45:21 neelin # Fixed Log subsitutions for CVS # # Revision 6.0 1997/09/12 13:23:34 neelin # Release of minc version 0.6 # # Revision 5.0 1997/08/21 13:24:35 neelin # Release of minc version 0.5 # # Revision 4.0 1997/05/07 20:00:36 neelin # Release of minc version 0.4 # # Revision 3.0 1995/05/15 19:31:09 neelin # Release of minc version 0.3 # # Revision 2.0 1994/09/28 10:33:58 neelin # Release of minc version 0.2 # # Revision 1.6 94/09/28 10:33:55 neelin # Pre-release # # Revision 1.5 93/08/25 11:24:48 neelin # Added checking for -h or -help options. # # Revision 1.4 93/08/11 15:19:09 neelin # Added RCS logging in source. # # # # Copyright 2008 Andrew Janke # Based upon original version of Peter Neelins (1993) # # McConnell Brain Imaging Centre, # Montreal Neurological Institute, # McGill University. # # Permission to use, copy, modify, and distribute this # software and its documentation for any purpose and without # fee is hereby granted, provided that the above copyright # notice appear in all copies. The author and McGill University # make no representations about the suitability of this # software for any purpose. It is provided "as is" without # express or implied warranty. # simple little function to emulate perl's die(); die () { echo >&2 $@ echo "" exit 1 } me=`basename $0` usage="Usage: $me []" # create tmpdir tmpdir=${TMPDIR:-/tmp}/mincedit.$$ trap 'rm -rf "$tmpdir"' 0 trap ' exit ' 0 1 2 3 15 (umask 077 && mkdir $tmpdir) || { echo "$me: Could not create temporary directory! Exiting." 1>&2 exit 1 } # check arguments case $# in 1) if [ "$1" = "-help" -o "$1" = "-h" -o "$1" = "" ] then echo $usage exit 0 fi # if no editor is specified, find a suitable one if [ -n "$VISUAL" ] then editor=${VISUAL} else if [ -n "$EDITOR" ] then editor=${EDITOR} else editor="emacs" fi fi ;; 2) editor="$2" ;; *) echo $usage exit 0 esac # only allow one input file and check for it [ $# -eq 1 -o $# -eq 2 ] || die $usage [ -f $1 ] || die "$me: no such file $1" # set up the file names infile="$1" backup_infile=`echo ${infile} | sed -e "s/\.mnc/\.bu-$$\.mnc/"` cdl_prefix=mincedit-$$ cdl_orig=${tmpdir}/${cdl_prefix}-orig.cdl cdl_edit=${tmpdir}/${cdl_prefix}-edit.cdl # dump the file mincheader $infile > $cdl_orig status=$? if [ $status -ne 0 ] then echo "${0}: Error reading file '$infile'" exit 1 fi # make a copy to fiddle with cp $cdl_orig $cdl_edit # loop until successful file generation do_edit=1 while [ $do_edit -ne 0 ] do # edit the cdl file $editor $cdl_edit status=$? if [ $status -ne 0 ] then echo "$me: Error editing with editor '$editor'" exit 1 fi do_edit=0 # compare the files for difference diff $cdl_orig $cdl_edit > /dev/null 2>&1 status=$? if [ $status -eq 0 ] then echo "$me: File $infile not modified" exit 0 fi # rename the original file and generate a new one mv "$infile" "$backup_infile" status=$? mincgen -o $infile $cdl_edit status=$? if [ $status -ne 0 ] then mv $backup_infile $infile echo -n "$me: Error generating new file. Redit the file (y/n)? (def=n):" read answer case "$answer" in y*) do_edit=1 continue ;; esac exit 0 fi # copy the data back in minccopy $backup_infile $infile status=$? if [ $status -ne 0 ] then mv $backup_infile $infile echo -n "Error copying image data. Redit the file (y/n)? (def=n):" read answer case "$answer" in y*) do_edit=1 continue ;; esac exit 0 fi done minc-2.2.00/progs/mincedit/mincedit.man10000644000265600003100000000137512027132662014746 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MINCEDIT 1 "$Date: 2008-01-09 14:42:24 $" "" "MINC User's Guide" .SH NAME mincedit \- edit a MINC file header .SH SYNOPSIS .B mincedit .BI mincfile .BI [editor] .SH DESCRIPTION \fBmincedit\fR converts the MINC file header to a text version which you can edit in your favourite editor. If any changes are made, the MINC file is regenerated and the image data is copied. The header is presented in netCDF's common data form language (CDL). .TP \fB\-help\fR Print summary of command-line options and exit. .SH AUTHOR Peter Neelin and Andrew Janke .SH COPYRIGHT Copyright \(co 1993 by Peter Neelin rewrite 2008 Andrew Janke - a.janke@gmail.com .SH "SEE ALSO" .IR mincdump (1), mincgen (1) minc-2.2.00/progs/mincexample/0000755000265600003100000000000012030114723013144 500000000000000minc-2.2.00/progs/mincexample/mincexample1.c0000644000265600003100000005423612027132662015635 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincexample1 @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Example program to load a minc file and then save it. @METHOD : @GLOBALS : @CALLS : @CREATED : August 24, 1993 (Peter Neelin) @MODIFIED : * $Log: mincexample1.c,v $ * Revision 6.7 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.6 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.5 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.4 2001/09/18 15:32:46 neelin * Create image variable last to allow big images and to fix compatibility * problems with 2.3 and 3.x. * * Revision 6.3 2001/08/16 16:41:34 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.2 2001/04/17 18:40:18 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:21 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:45 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:45 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:58 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:39 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:34:41 neelin * Release of minc version 0.2 * * Revision 1.6 94/09/28 10:34:35 neelin * Pre-release * * Revision 1.5 94/03/16 12:10:50 neelin * Changed ncopen,create,close to miopen,... * Changed setting of step and start attributes in output file. * * Revision 1.4 93/08/30 11:00:55 neelin * Added reading of dimension step and start. * Added printing of volume information in main program. * Put icv setup stuff in separate routine. * Broke up save_volume into smaller routines. * * Revision 1.3 93/08/26 12:31:17 neelin * Added define so that minc_def.h is optionally included. * * Revision 1.2 93/08/26 11:57:00 neelin * Removed include of ParseArgv stuff and added MALLOC and FREE definitions * from minc_def.h so that it is not always needed. * * Revision 1.1 93/08/26 11:45:49 neelin * Initial revision * ---------------------------------------------------------------------------- */ #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Definitions for accessing information on each dimension */ #define NUMBER_OF_DIMENSIONS 3 /* Number of dimensions of volume */ #define SLICE 0 /* Index for slice information */ #define ROW 1 /* Index for row information */ #define COLUMN 2 /* Index for column information */ /* Default ncopts values for error handling */ #define NC_OPTS_VAL NC_VERBOSE | NC_FATAL /* Types */ typedef struct { long nslices; /* Number of slices */ long nrows; /* Number of rows in image */ long ncolumns; /* Number of columns in image */ unsigned char *data; /* Pointer to volume data */ double maximum; /* Volume maximum */ double minimum; /* Volume minimum */ double step[NUMBER_OF_DIMENSIONS]; /* Step sizes for dimensions */ double start[NUMBER_OF_DIMENSIONS]; /* Start positions for dimensions */ char dimension_names[NUMBER_OF_DIMENSIONS][MAX_NC_NAME]; /* Dimension names */ } Volume; /* Function prototypes */ static void load_volume(char *infile, Volume *volume); static void get_dimension_info(char *infile, int icvid, Volume *volume); static void setup_icv(int icvid); static void read_volume_data(int icvid, Volume *volume); static void save_volume(char *infile, char *outfile, char *arg_string, Volume *volume); static void setup_variables(int inmincid, int mincid, Volume *volume, char *arg_string); static void setup_image_variables(int inmincid, int mincid, int ndims, int dim[]); static void update_history(int mincid, char *arg_string); static void write_volume_data(int icvid, Volume *volume); /* Main program */ int main(int argc, char *argv[]) { char *infile, *outfile; Volume volume; char *arg_string; /* Get arguments */ if (argc != 3) { (void) fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* Save list of arguments as string */ arg_string = time_stamp(argc, argv); /* Read in input volume */ load_volume(infile, &volume); /* Print out volume information */ (void) printf("File %s:\n", infile); (void) printf(" maximum = %10g, minimum = %10g\n", volume.maximum, volume.minimum); (void) printf(" slices = %10s: n=%3d, step=%10g, start=%10g\n", volume.dimension_names[SLICE], (int) volume.nslices, volume.step[SLICE], volume.start[SLICE]); (void) printf(" rows = %10s: n=%3d, step=%10g, start=%10g\n", volume.dimension_names[ROW], (int) volume.nrows, volume.step[ROW], volume.start[ROW]); (void) printf(" columns = %10s: n=%3d, step=%10g, start=%10g\n", volume.dimension_names[COLUMN], (int) volume.ncolumns, volume.step[COLUMN], volume.start[COLUMN]); /* Save the volume, copying information from input file */ save_volume(infile, outfile, arg_string, &volume); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : load_volume @INPUT : infile - input file name @OUTPUT : volume - input volume data @RETURNS : (nothing) @DESCRIPTION: Routine to read in a transverse volume and store the data in a volume structure. @METHOD : @GLOBALS : @CALLS : @CREATED : August 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void load_volume(char *infile, Volume *volume) { int icvid, mincid; /* Create and set up icv for input */ icvid = miicv_create(); setup_icv(icvid); /* Open the image file */ mincid = miopen(infile, NC_NOWRITE); /* Attach the icv to the file */ (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); /* Get dimension information */ get_dimension_info(infile, icvid, volume); /* Read in volume data */ read_volume_data(icvid, volume); /* Close the file and free the icv */ (void) miclose(mincid); (void) miicv_free(icvid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_icv @INPUT : icvid - id of icv to set up @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up an icv @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_icv(int icvid) { /* Set desired type */ (void) miicv_setint(icvid, MI_ICV_TYPE, NC_BYTE); (void) miicv_setstr(icvid, MI_ICV_SIGN, MI_UNSIGNED); /* Set range of values */ (void) miicv_setint(icvid, MI_ICV_VALID_MIN, 0); (void) miicv_setint(icvid, MI_ICV_VALID_MAX, 255); /* Do normalization so that all pixels are on same scale */ (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); /* Make sure that any out of range values are mapped to lowest value of type (for input only) */ (void) miicv_setint(icvid, MI_ICV_DO_FILLVALUE, TRUE); /* We want to ensure that images have X, Y and Z dimensions in the positive direction, giving patient left on left and for drawing from bottom up. If we wanted patient right on left and drawing from top down, we would set to MI_ICV_NEGATIVE. */ (void) miicv_setint(icvid, MI_ICV_DO_DIM_CONV, TRUE); (void) miicv_setint(icvid, MI_ICV_XDIM_DIR, MI_ICV_POSITIVE); (void) miicv_setint(icvid, MI_ICV_YDIM_DIR, MI_ICV_POSITIVE); (void) miicv_setint(icvid, MI_ICV_ZDIM_DIR, MI_ICV_POSITIVE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dimension_info @INPUT : infile - name of input file icvid - id of the image conversion variable @OUTPUT : volume - input volume data @RETURNS : (nothing) @DESCRIPTION: Routine to get dimension information from an input file. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_dimension_info(char *infile, int icvid, Volume *volume) { int mincid, imgid, varid; int idim, ndims; int dim[MAX_VAR_DIMS]; long *dimlength; char *dimname; /* Get the minc file id and the image variable id */ (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); (void) miicv_inqint(icvid, MI_ICV_VARID, &imgid); if ((mincid == MI_ERROR) || (imgid == MI_ERROR)) { (void) fprintf(stderr, "File %s is not attached to an icv!\n", infile); exit(EXIT_FAILURE); } /* Get the list of dimensions subscripting the image variable */ (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Check that we only have three dimensions */ if (ndims != NUMBER_OF_DIMENSIONS) { (void) fprintf(stderr, "File %s does not have exactly %d dimensions\n", infile, NUMBER_OF_DIMENSIONS); exit(EXIT_FAILURE); } /* Loop through dimensions, checking them and getting their sizes */ for (idim=0; idimnslices) ; break; case 1: dimlength = &(volume->nrows) ; break; case 2: dimlength = &(volume->ncolumns) ; break; } /* Get dimension name and size */ dimname = volume->dimension_names[idim]; (void) ncdiminq(mincid, dim[idim], dimname, dimlength); } /* Get dimension step and start (defaults = 1 and 0). For slices, we read straight from the variable, but for image dimensions, we get the step and start from the icv. If we didn't have MI_ICV_DO_DIM_CONV set to TRUE, then we would have to get the image dimension step and start straight from the variables. */ for (idim=0; idimstep[idim] = 1.0; volume->start[idim] = 0.0; } ncopts = 0; (void) miicv_inqdbl(icvid, MI_ICV_ADIM_STEP, &volume->step[COLUMN]); (void) miicv_inqdbl(icvid, MI_ICV_ADIM_START, &volume->start[COLUMN]); (void) miicv_inqdbl(icvid, MI_ICV_BDIM_STEP, &volume->step[ROW]); (void) miicv_inqdbl(icvid, MI_ICV_BDIM_START, &volume->start[ROW]); if ((varid=ncvarid(mincid, volume->dimension_names[SLICE])) != MI_ERROR) { (void) miattget1(mincid, varid, MIstep, NC_DOUBLE, &volume->step[SLICE]); (void) miattget1(mincid, varid, MIstart, NC_DOUBLE, &volume->start[SLICE]); } ncopts = NC_OPTS_VAL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_volume_data @INPUT : icvid - id of icv to set up @OUTPUT : volume - volume data @RETURNS : (nothing) @DESCRIPTION: Routine to read in the volume data. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void read_volume_data(int icvid, Volume *volume) { long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; /* Set up the start and count variables for reading the volume */ (void) miset_coords(3, 0, start); count[0] = volume->nslices; count[1] = volume->nrows; count[2] = volume->ncolumns; /* Allocate space for the data */ volume->data = malloc(sizeof(*volume->data) * volume->ncolumns * volume->nrows * volume->nslices); /* Read in the volume */ (void) miicv_get(icvid, start, count, volume->data); /* Get the volume min and max */ (void) miicv_inqdbl(icvid, MI_ICV_NORM_MIN, &volume->minimum); (void) miicv_inqdbl(icvid, MI_ICV_NORM_MAX, &volume->maximum); } /* ----------------------------- MNI Header ----------------------------------- @NAME : save_volume @INPUT : infile - input file name (NULL means don't copy info) outfile - output file name arg_string - string giving argument list volume - volume data @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to save a transverse volume, copying information from an optional input file. @METHOD : @GLOBALS : @CALLS : @CREATED : August 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void save_volume(char *infile, char *outfile, char *arg_string, Volume *volume) { int mincid, icvid, inmincid; /* Create output file */ mincid = micreate(outfile, NC_CLOBBER); /* Open the input file if it is provided */ if (infile != NULL) { inmincid = miopen(infile, NC_NOWRITE); } else { inmincid = MI_ERROR; } /* Set up variables and put output file in data mode */ setup_variables(inmincid, mincid, volume, arg_string); /* Close the input file */ if (inmincid != MI_ERROR) { (void) miclose(inmincid); } /* Create an icv and set it up */ icvid = miicv_create(); setup_icv(icvid); /* Attach the icv to the file */ (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); /* Write out the volume data */ write_volume_data(icvid, volume); /* Close the file and free the icv */ (void) miclose(mincid); (void) miicv_free(icvid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_variables @INPUT : inmincid - id of input minc file (MI_ERROR if no file) mincid - id of output minc file volume - volume information arg_string - string giving argument list @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up variables in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_variables(int inmincid, int mincid, Volume *volume, char *arg_string) { int dim[MAX_VAR_DIMS], ndims, idim, varid; int excluded_vars[10], nexcluded; /* Create the dimensions */ ndims = NUMBER_OF_DIMENSIONS; dim[0] = ncdimdef(mincid, volume->dimension_names[0], volume->nslices); dim[1] = ncdimdef(mincid, volume->dimension_names[1], volume->nrows); dim[2] = ncdimdef(mincid, volume->dimension_names[2], volume->ncolumns); /* If an input file is provided, copy all header info from that file except image, image-max, image-min */ if (inmincid != MI_ERROR) { /* Look for the image variable and the image-max/min variables so that we can exclude them from the copy */ nexcluded = 0; excluded_vars[nexcluded] = ncvarid(inmincid, MIimage); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; excluded_vars[nexcluded] = ncvarid(inmincid, MIimagemax); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; excluded_vars[nexcluded] = ncvarid(inmincid, MIimagemin); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; /* Copy the variable definitions */ (void) micopy_all_var_defs(inmincid, mincid, nexcluded, excluded_vars); } /* Set up the dimension variables. If the variable doesn't exist, create it (either no input file or variable did not exist in it). If the dimensions are not standard, then no variable is created. */ for (idim=0; idim < ndims; idim++) { ncopts = 0; varid = ncvarid(mincid, volume->dimension_names[idim]); if (varid == MI_ERROR) { varid = micreate_std_variable(mincid, volume->dimension_names[idim], NC_INT, 0, NULL); } ncopts = NC_OPTS_VAL; if (varid != MI_ERROR) { (void) miattputdbl(mincid, varid, MIstep, volume->step[idim]); (void) miattputdbl(mincid, varid, MIstart, volume->start[idim]); } } /* Create the image, image-max and image-min variables */ setup_image_variables(inmincid, mincid, ndims, dim); /* Add the time stamp to the history */ update_history(mincid, arg_string); /* Put the file in data mode */ (void) ncendef(mincid); /* Copy over variable values */ if (inmincid != MI_ERROR) { (void) micopy_all_var_values(inmincid, mincid, nexcluded, excluded_vars); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_image_variables @INPUT : inmincid - id of input minc file (MI_ERROR if no file) mincid - id of output minc file ndims - number of dimensions dim - list of dimension ids @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up image, image-max and image-min variables in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_image_variables(int inmincid, int mincid, int ndims, int dim[]) { int imgid, maxid, minid; static double valid_range[2] = {0.0, 255.0}; /* Create the image max and min variables */ maxid = micreate_std_variable(mincid, MIimagemax, NC_DOUBLE, 0, NULL); minid = micreate_std_variable(mincid, MIimagemin, NC_DOUBLE, 0, NULL); if (inmincid != MI_ERROR) { (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemax), mincid, maxid); (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemin), mincid, minid); } /* Create the image variable, copy attributes, set the signtype attribute, set the valid range attribute and delete valid max/min attributes */ imgid = micreate_std_variable(mincid, MIimage, NC_BYTE, ndims, dim); if (inmincid != MI_ERROR) { (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimage), mincid, imgid); ncopts = 0; (void) ncattdel(mincid, imgid, MIvalid_max); (void) ncattdel(mincid, imgid, MIvalid_min); ncopts = NC_OPTS_VAL; } (void) miattputstr(mincid, imgid, MIsigntype, MI_UNSIGNED); (void) miset_valid_range(mincid, imgid, valid_range); } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_history @INPUT : mincid - id of output minc file arg_string - string giving list of arguments @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to update the history global variable in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void update_history(int mincid, char *arg_string) { nc_type datatype; int att_length; char *string; /* Get the history attribute length */ ncopts=0; if ((ncattinq(mincid, NC_GLOBAL, MIhistory, &datatype, &att_length) == MI_ERROR) || (datatype != NC_CHAR)) att_length = 0; att_length += strlen(arg_string) + 1; /* Allocate a string and get the old history */ string = malloc(att_length); string[0] = '\0'; (void) miattgetstr(mincid, NC_GLOBAL, MIhistory, att_length, string); ncopts = NC_OPTS_VAL; /* Add the new command and put the new history. */ (void) strcat(string, arg_string); (void) miattputstr(mincid, NC_GLOBAL, MIhistory, string); free(string); } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_volume_data @INPUT : icvid - id of icv to set up volume - volume data @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to write out the volume data. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void write_volume_data(int icvid, Volume *volume) { int mincid; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; /* Get the minc file id */ (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); /* Set up the start and count variables for writinging the volume */ (void) miset_coords(3, 0, start); count[0] = volume->nslices; count[1] = volume->nrows; count[2] = volume->ncolumns; /* Write out the volume min and max */ (void) mivarput1(mincid, ncvarid(mincid, MIimagemin), NULL, NC_DOUBLE, NULL, &volume->minimum); (void) mivarput1(mincid, ncvarid(mincid, MIimagemax), NULL, NC_DOUBLE, NULL, &volume->maximum); /* Write out the volume */ (void) miicv_put(icvid, start, count, volume->data); /* Free space for the data */ free(volume->data); } minc-2.2.00/progs/mincexample/mincexample2.c0000644000265600003100000006333012027132662015631 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincexample2 @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Example program copy a minc file one slice at a time (where mincexample loads in the whole volume and then writes it out). @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : * $Log: mincexample2.c,v $ * Revision 6.7 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.6 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.5 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.4 2001/09/18 15:32:46 neelin * Create image variable last to allow big images and to fix compatibility * problems with 2.3 and 3.x. * * Revision 6.3 2001/08/16 16:41:34 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.2 2001/04/17 18:40:19 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:22 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:45 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:45 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:58 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:39 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:34:42 neelin * Release of minc version 0.2 * * Revision 1.3 94/09/28 10:34:36 neelin * Pre-release * * Revision 1.2 94/03/17 08:36:29 neelin * Added support for 2-d files. * * Revision 1.1 94/03/16 12:00:59 neelin * Initial revision * ---------------------------------------------------------------------------- */ #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Definitions for accessing information on each dimension */ #define NUMBER_OF_DIMENSIONS 3 /* Number of dimensions of volume */ #define SLICE 0 /* Index for slice information */ #define ROW 1 /* Index for row information */ #define COLUMN 2 /* Index for column information */ /* Default ncopts values for error handling */ #define NC_OPTS_VAL NC_VERBOSE | NC_FATAL /* Types */ typedef struct { long nslices; /* Number of slices */ long nrows; /* Number of rows in image */ long ncolumns; /* Number of columns in image */ double maximum; /* Volume maximum */ double minimum; /* Volume minimum */ double step[NUMBER_OF_DIMENSIONS]; /* Step sizes for dimensions */ double start[NUMBER_OF_DIMENSIONS]; /* Start positions for dimensions */ char dimension_names[NUMBER_OF_DIMENSIONS][MAX_NC_NAME]; /* Dimension names */ } Volume_Info; /* Function prototypes */ static int get_volume_info(char *infile, Volume_Info *volume_info); static void setup_input_icv(int icvid); static void get_dimension_info(char *infile, int icvid, Volume_Info *volume_info); static void close_volume(int icvid); static void get_volume_slice(int icvid, Volume_Info *volume_info, int slice_num, unsigned char *image); static int save_volume_info(int input_icvid, char *outfile, char *arg_string, Volume_Info *volume_info); static void setup_output_icv(int icvid); static void setup_variables(int inmincid, int mincid, Volume_Info *volume_info, char *arg_string); static void setup_image_variables(int inmincid, int mincid, int ndims, int dim[]); static void update_history(int mincid, char *arg_string); static void save_volume_slice(int icvid, Volume_Info *volume_info, int slice_num, unsigned char *image, double slice_min, double slice_max); /* Main program */ int main(int argc, char *argv[]) { char *infile, *outfile; Volume_Info volume_info; char *arg_string; int input_icvid, output_icvid; unsigned char *image; int islice; /* Get arguments */ if (argc != 3) { (void) fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* Save list of arguments as string */ arg_string = time_stamp(argc, argv); /* Read in input volume information */ input_icvid = get_volume_info(infile, &volume_info); /* Print out volume information */ (void) printf("File %s:\n", infile); (void) printf(" maximum = %10g, minimum = %10g\n", volume_info.maximum, volume_info.minimum); (void) printf(" slices = %10s: n=%3d, step=%10g, start=%10g\n", volume_info.dimension_names[SLICE], (int) volume_info.nslices, volume_info.step[SLICE], volume_info.start[SLICE]); (void) printf(" rows = %10s: n=%3d, step=%10g, start=%10g\n", volume_info.dimension_names[ROW], (int) volume_info.nrows, volume_info.step[ROW], volume_info.start[ROW]); (void) printf(" columns = %10s: n=%3d, step=%10g, start=%10g\n", volume_info.dimension_names[COLUMN], (int) volume_info.ncolumns, volume_info.step[COLUMN], volume_info.start[COLUMN]); /* Save the volume, copying information from input file */ output_icvid = save_volume_info(input_icvid, outfile, arg_string, &volume_info); /* Loop through slices, copying them */ image = malloc(volume_info.nrows * volume_info.ncolumns * sizeof(*image)); for (islice=0; islice < volume_info.nslices; islice++) { get_volume_slice(input_icvid, &volume_info, islice, image); save_volume_slice(output_icvid, &volume_info, islice, image, volume_info.minimum, volume_info.maximum); } /* Free up image and close files */ close_volume(input_icvid); close_volume(output_icvid); free(image); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_info @INPUT : infile - input file name @OUTPUT : volume_info - input volume information @RETURNS : Id of icv created @DESCRIPTION: Routine to read volume information for a file. @METHOD : @GLOBALS : @CALLS : @CREATED : August 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_volume_info(char *infile, Volume_Info *volume_info) { int icvid, mincid; /* Create and set up icv for input */ icvid = miicv_create(); setup_input_icv(icvid); /* Open the image file */ mincid = miopen(infile, NC_NOWRITE); /* Attach the icv to the file */ (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); /* Get dimension information */ get_dimension_info(infile, icvid, volume_info); /* Get the volume min and max */ (void) miicv_inqdbl(icvid, MI_ICV_NORM_MIN, &volume_info->minimum); (void) miicv_inqdbl(icvid, MI_ICV_NORM_MAX, &volume_info->maximum); return icvid; } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_input_icv @INPUT : icvid - id of icv to set up @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up an icv @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_input_icv(int icvid) { /* Set desired type */ (void) miicv_setint(icvid, MI_ICV_TYPE, NC_BYTE); (void) miicv_setstr(icvid, MI_ICV_SIGN, MI_UNSIGNED); /* Set range of values */ (void) miicv_setint(icvid, MI_ICV_VALID_MIN, 0); (void) miicv_setint(icvid, MI_ICV_VALID_MAX, 255); /* Do normalization so that all pixels are on same scale */ (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); /* Make sure that any out of range values are mapped to lowest value of type (for input only) */ (void) miicv_setint(icvid, MI_ICV_DO_FILLVALUE, TRUE); /* We want to ensure that images have X, Y and Z dimensions in the positive direction, giving patient left on left and for drawing from bottom up. If we wanted patient right on left and drawing from top down, we would set to MI_ICV_NEGATIVE. */ (void) miicv_setint(icvid, MI_ICV_DO_DIM_CONV, TRUE); (void) miicv_setint(icvid, MI_ICV_DO_SCALAR, TRUE); (void) miicv_setint(icvid, MI_ICV_XDIM_DIR, MI_ICV_POSITIVE); (void) miicv_setint(icvid, MI_ICV_YDIM_DIR, MI_ICV_POSITIVE); (void) miicv_setint(icvid, MI_ICV_ZDIM_DIR, MI_ICV_POSITIVE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dimension_info @INPUT : infile - name of input file icvid - id of the image conversion variable @OUTPUT : volume - input volume data @RETURNS : (nothing) @DESCRIPTION: Routine to get dimension information from an input file. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_dimension_info(char *infile, int icvid, Volume_Info *volume_info) { int mincid, imgid, varid; int idim, ndims; int dim[MAX_VAR_DIMS]; long *dimlength; char *dimname; int offset; int missing_one_dimension; /* Get the minc file id and the image variable id */ (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); (void) miicv_inqint(icvid, MI_ICV_VARID, &imgid); if ((mincid == MI_ERROR) || (imgid == MI_ERROR)) { (void) fprintf(stderr, "File %s is not attached to an icv!\n", infile); exit(EXIT_FAILURE); } /* Get the list of dimensions subscripting the image variable */ (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); (void) miicv_inqint(icvid, MI_ICV_NUM_DIMS, &ndims); /* Check that we have two or three dimensions */ if ((ndims != NUMBER_OF_DIMENSIONS) && (ndims != NUMBER_OF_DIMENSIONS-1)) { (void) fprintf(stderr, "File %s does not have %d or %d dimensions\n", infile, NUMBER_OF_DIMENSIONS, NUMBER_OF_DIMENSIONS-1); exit(EXIT_FAILURE); } /* Pretend that we have three dimensions */ offset = ndims - NUMBER_OF_DIMENSIONS; missing_one_dimension = (offset < 0); ndims = NUMBER_OF_DIMENSIONS; /* Loop through dimensions, checking them and getting their sizes */ for (idim=0; idimnslices) ; break; case 1: dimlength = &(volume_info->nrows) ; break; case 2: dimlength = &(volume_info->ncolumns) ; break; } dimname = volume_info->dimension_names[idim]; /* Get dimension name and size */ if (missing_one_dimension && (idim==0)) { (void) strcpy(dimname, "unknown"); *dimlength = 1; } else { (void) ncdiminq(mincid, dim[idim+offset], dimname, dimlength); } } /* Get dimension step and start (defaults = 1 and 0). For slices, we read straight from the variable, but for image dimensions, we get the step and start from the icv. If we didn't have MI_ICV_DO_DIM_CONV set to TRUE, then we would have to get the image dimension step and start straight from the variables. */ for (idim=0; idimstep[idim] = 1.0; volume_info->start[idim] = 0.0; } ncopts = 0; (void) miicv_inqdbl(icvid, MI_ICV_ADIM_STEP, &volume_info->step[COLUMN]); (void) miicv_inqdbl(icvid, MI_ICV_ADIM_START, &volume_info->start[COLUMN]); (void) miicv_inqdbl(icvid, MI_ICV_BDIM_STEP, &volume_info->step[ROW]); (void) miicv_inqdbl(icvid, MI_ICV_BDIM_START, &volume_info->start[ROW]); if ((varid=ncvarid(mincid, volume_info->dimension_names[SLICE])) != MI_ERROR) { (void) miattget1(mincid, varid, MIstep, NC_DOUBLE, &volume_info->step[SLICE]); (void) miattget1(mincid, varid, MIstart, NC_DOUBLE, &volume_info->start[SLICE]); } ncopts = NC_OPTS_VAL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : close_volume @INPUT : icvid - id of open icv @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to close a minc file and free the associated icv @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void close_volume(int icvid) { int mincid; /* Get the minc file id and close the file */ ncopts = 0; if (miicv_inqint(icvid, MI_ICV_CDFID, &mincid) != MI_ERROR) { (void) miclose(mincid); } ncopts = NC_OPTS_VAL; /* Free the icv */ (void) miicv_free(icvid); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_slice @INPUT : icvid - id of icv to read volume_info - info for volume slice_num - number of slice to read in (counting from zero) @OUTPUT : image - image that is read in @RETURNS : (nothing) @DESCRIPTION: Routine to read in an image. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_volume_slice(int icvid, Volume_Info *volume_info, int slice_num, unsigned char *image) { long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; int offset, ndims; /* Get number of dimensions */ (void) miicv_inqint(icvid, MI_ICV_NUM_DIMS, &ndims); offset = ndims - NUMBER_OF_DIMENSIONS; /* Check slice_num */ if (slice_num >= volume_info->nslices) { (void) fprintf(stderr, "Slice %d is not in the file.\n", slice_num); exit(EXIT_FAILURE); } /* Set up the start and count variables for reading the volume */ (void) miset_coords(3, 0, start); if (offset >= 0) { start[offset] = slice_num; count[offset] = 1; } count[1+offset] = volume_info->nrows; count[2+offset] = volume_info->ncolumns; /* Read in the volume */ (void) miicv_get(icvid, start, count, image); } /* ----------------------------- MNI Header ----------------------------------- @NAME : save_volume_info @INPUT : input_icvid - input file icvid (MI_ERROR means no input volume) outfile - output file name arg_string - string giving argument list volume_info - volume information @OUTPUT : (nothing) @RETURNS : icv of output file @DESCRIPTION: Routine to save a 3-D volume, copying information from an optional input file. @METHOD : @GLOBALS : @CALLS : @CREATED : August 22, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int save_volume_info(int input_icvid, char *outfile, char *arg_string, Volume_Info *volume_info) { int mincid, icvid, inmincid; /* Create output file */ mincid = micreate(outfile, NC_NOCLOBBER); /* Open the input file if it is provided */ inmincid = MI_ERROR; if (input_icvid != MI_ERROR) { (void) miicv_inqint(input_icvid, MI_ICV_CDFID, &inmincid); } /* Set up variables and put output file in data mode */ setup_variables(inmincid, mincid, volume_info, arg_string); /* Create an icv and set it up */ icvid = miicv_create(); setup_output_icv(icvid); /* Attach the icv to the file */ (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); return icvid; } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_output_icv @INPUT : icvid - id of icv to set up @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up an icv @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_output_icv(int icvid) { /* Set desired type */ (void) miicv_setint(icvid, MI_ICV_TYPE, NC_BYTE); (void) miicv_setstr(icvid, MI_ICV_SIGN, MI_UNSIGNED); /* Set range of values */ (void) miicv_setint(icvid, MI_ICV_VALID_MIN, 0); (void) miicv_setint(icvid, MI_ICV_VALID_MAX, 255); /* No normalization so that pixels are scaled to the slice */ (void) miicv_setint(icvid, MI_ICV_DO_NORM, FALSE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_variables @INPUT : inmincid - id of input minc file (MI_ERROR if no file) mincid - id of output minc file volume_info - volume information arg_string - string giving argument list @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up variables in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_variables(int inmincid, int mincid, Volume_Info *volume_info, char *arg_string) { int dim[MAX_VAR_DIMS], ndims, idim, varid; int excluded_vars[10], nexcluded; /* Create the dimensions */ ndims = NUMBER_OF_DIMENSIONS; dim[0] = ncdimdef(mincid, volume_info->dimension_names[0], volume_info->nslices); dim[1] = ncdimdef(mincid, volume_info->dimension_names[1], volume_info->nrows); dim[2] = ncdimdef(mincid, volume_info->dimension_names[2], volume_info->ncolumns); /* If an input file is provided, copy all header info from that file except image, image-max, image-min */ if (inmincid != MI_ERROR) { /* Look for the image variable and the image-max/min variables so that we can exclude them from the copy */ nexcluded = 0; excluded_vars[nexcluded] = ncvarid(inmincid, MIimage); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; excluded_vars[nexcluded] = ncvarid(inmincid, MIimagemax); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; excluded_vars[nexcluded] = ncvarid(inmincid, MIimagemin); if (excluded_vars[nexcluded] != MI_ERROR) nexcluded++; /* Copy the variable definitions */ (void) micopy_all_var_defs(inmincid, mincid, nexcluded, excluded_vars); } /* Set up the dimension variables. If the variable doesn't exist, create it (either no input file or variable did not exist in it). If the dimensions are not standard, then no variable is created. */ for (idim=0; idim < ndims; idim++) { ncopts = 0; varid = ncvarid(mincid, volume_info->dimension_names[idim]); if (varid == MI_ERROR) { varid = micreate_std_variable(mincid, volume_info->dimension_names[idim], NC_INT, 0, NULL); } ncopts = NC_OPTS_VAL; if (varid != MI_ERROR) { (void) miattputdbl(mincid, varid, MIstep, volume_info->step[idim]); (void) miattputdbl(mincid, varid, MIstart, volume_info->start[idim]); } } /* Create the image, image-max and image-min variables */ setup_image_variables(inmincid, mincid, ndims, dim); /* Add the time stamp to the history */ update_history(mincid, arg_string); /* Put the file in data mode */ (void) ncendef(mincid); /* Copy over variable values */ if (inmincid != MI_ERROR) { (void) micopy_all_var_values(inmincid, mincid, nexcluded, excluded_vars); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_image_variables @INPUT : inmincid - id of input minc file (MI_ERROR if no file) mincid - id of output minc file ndims - number of dimensions dim - list of dimension ids @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to set up image, image-max and image-min variables in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_image_variables(int inmincid, int mincid, int ndims, int dim[]) { int imgid, maxid, minid; static double valid_range[2] = {0.0, 255.0}; /* Create the image max and min variables (varying over slices) */ maxid = micreate_std_variable(mincid, MIimagemax, NC_DOUBLE, 1, dim); minid = micreate_std_variable(mincid, MIimagemin, NC_DOUBLE, 1, dim); if (inmincid != MI_ERROR) { (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemax), mincid, maxid); (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimagemin), mincid, minid); } /* Create the image variable, copy attributes, set the signtype attribute, set the valid range attribute and delete valid max/min attributes */ imgid = micreate_std_variable(mincid, MIimage, NC_BYTE, ndims, dim); if (inmincid != MI_ERROR) { (void) micopy_all_atts(inmincid, ncvarid(inmincid, MIimage), mincid, imgid); ncopts = 0; (void) ncattdel(mincid, imgid, MIvalid_max); (void) ncattdel(mincid, imgid, MIvalid_min); ncopts = NC_OPTS_VAL; } (void) miattputstr(mincid, imgid, MIsigntype, MI_UNSIGNED); (void) miset_valid_range(mincid, imgid, valid_range); } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_history @INPUT : mincid - id of output minc file arg_string - string giving list of arguments @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to update the history global variable in the output minc file @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void update_history(int mincid, char *arg_string) { nc_type datatype; int att_length; char *string; /* Get the history attribute length */ ncopts=0; if ((ncattinq(mincid, NC_GLOBAL, MIhistory, &datatype, &att_length) == MI_ERROR) || (datatype != NC_CHAR)) att_length = 0; att_length += strlen(arg_string) + 1; /* Allocate a string and get the old history */ string = malloc(att_length); string[0] = '\0'; (void) miattgetstr(mincid, NC_GLOBAL, MIhistory, att_length, string); ncopts = NC_OPTS_VAL; /* Add the new command and put the new history. */ (void) strcat(string, arg_string); (void) miattputstr(mincid, NC_GLOBAL, MIhistory, string); free(string); } /* ----------------------------- MNI Header ----------------------------------- @NAME : save_volume_slice @INPUT : icvid - id of icv to write volume_info - volume information (minimum and maximum are ignored) slice_num - number of slice to write image - image to write slice_min - minimum real value for slice slice_max - maximum real value for slice @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to write out a slice. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void save_volume_slice(int icvid, Volume_Info *volume_info, int slice_num, unsigned char *image, double slice_min, double slice_max) { int mincid; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; /* Get the minc file id */ (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); /* Set up the start and count variables for writinging the volume */ (void) miset_coords(3, 0, start); start[0] = slice_num; count[0] = 1; count[1] = volume_info->nrows; count[2] = volume_info->ncolumns; /* Write out the slice min and max */ (void) mivarput1(mincid, ncvarid(mincid, MIimagemin), start, NC_DOUBLE, NULL, &slice_min); (void) mivarput1(mincid, ncvarid(mincid, MIimagemax), start, NC_DOUBLE, NULL, &slice_max); /* Write out the volume */ (void) miicv_put(icvid, start, count, image); } minc-2.2.00/progs/mincexpand/0000755000265600003100000000000012030114723012770 500000000000000minc-2.2.00/progs/mincexpand/mincexpand.man10000644000265600003100000000347712027132662015637 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincexpand/mincexpand.man1,v 6.1 2004-05-20 21:52:08 bert Exp $ .\" .TH MINCEXPAND 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincexpand - expands a compressed minc file, if necessary. .SH SYNOPSIS .B mincexpand [] [] .SH DESCRIPTION \fIMincexpand\fR expands a compressed, packed, gzipped or zipped minc file into a temporary file using gunzip (or zcat or pcat) and prints out the name of the new file. If the input file is not compressed, then nothing is done and the original file name is printed. A second line is printed, indicating whether the name is that of a new temporary file ("Temporary") or that of the original file ("Original"). If no output file name is given, then the program generates its own. .SH OPTIONS .TP \fB\-header_only\fR Expand only enough of the file to be able to read the header. .TP \fB\-all_data\fR Expand the whole file (default). .TP \fB\-name_only\fR Print out only the file name, not the status (Temporary or Original). .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1995 by Peter Neelin minc-2.2.00/progs/mincexpand/mincexpand.c0000644000265600003100000001022012027132662015205 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincexpand @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to expand a compressed minc image volume, if necessary. @METHOD : @GLOBALS : @CALLS : @CREATED : January 20, 1995 (Peter Neelin) @MODIFIED : * $Log: mincexpand.c,v $ * Revision 6.6 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.5 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.4 2006/05/19 00:35:58 bert * Add config.h to several files that might need it * * Revision 6.3 2004/12/14 23:51:24 bert * Get rid of compilation warning with c99 * * Revision 6.2 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.1 1999/10/19 14:45:22 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:16 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:15 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:02:02 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:32:41 neelin * Release of minc version 0.3 * * Revision 1.3 1995/01/24 09:06:19 neelin * Added -name_only option. * * Revision 1.2 95/01/24 08:48:57 neelin * Added optional output file argument. * * Revision 1.1 95/01/23 08:33:31 neelin * Initial revision * * Revision 1.1 95/01/20 15:51:32 neelin * Initial revision * @COPYRIGHT : Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE 1 #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Variables used for argument parsing */ int header_only = FALSE; int name_only = FALSE; /* Argument table */ ArgvInfo argTable[] = { {"-header_only", ARGV_CONSTANT, (char *) TRUE, (char *) &header_only, "Expand only enough file to get the header."}, {"-all_data", ARGV_CONSTANT, (char *) FALSE, (char *) &header_only, "Expand the whole file (default)."}, {"-name_only", ARGV_CONSTANT, (char *) TRUE, (char *) &name_only, "Print out only the file name."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *filename, *tempfile, *newfile; int created_tempfile; /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2) || (argc > 3)) { (void) fprintf(stderr, "\nUsage: %s [] []\n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } filename = argv[1]; if (argc == 3) tempfile = argv[2]; else tempfile = NULL; /* Expand the file */ ncopts = 0; newfile = miexpand_file(filename, tempfile, header_only, &created_tempfile); if (newfile == NULL) newfile = strdup(filename); /* Print out file name and message about temporary file */ (void) printf("%s\n", newfile); if (!name_only) { if (created_tempfile) { (void) printf("Temporary\n"); } else { (void) printf("Original\n"); } } /* Free the temporary file name string */ free(newfile); exit(EXIT_SUCCESS); } minc-2.2.00/progs/mincextract/0000755000265600003100000000000012030114723013163 500000000000000minc-2.2.00/progs/mincextract/mincextract.man10000644000265600003100000000571612027132662016223 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MINCEXTRACT 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincextract \- dump a hyperslab of MINC file data .SH SYNOPSIS .B mincextract .BI [options] .BI mincfile .SH DESCRIPTION \fImincextract\fR dumps a chunk of MINC file data to standard output in the format of your choice. .SH OPTIONS .TP \fB\-ascii\fR Write out data as ascii strings (default) .TP \fB\-byte\fR Write out data as 8-bit integers .TP \fB\-short\fR Write out data as 16-bit integers .TP \fB\-int\fR Write out data as 32-bit integers .TP \fB\-long\fR Superseded by \fB\-int\fR .TP \fB\-float\fR Write out data as single precision floating-point values .TP \fB\-double\fR Write out data as double precision floating-point values .TP \fB\-filetype\fR Write out data in the type of the file .TP \fB\-signed\fR Write out signed data (applies only to integer types) .TP \fB\-unsigned\fR Write out unsigned data (applies only to integer types) .TP \fB\-range\fR \fIlow\ high\fR Specify the range of output values .TP \fB\-normalize\fR Normalize integer pixel values to file max and min (Default) .TP \fB\-nonormalize\fR Turn off pixel normalization .TP \fB\-image_range\fR \fIlow\ high\fR Specify the range of real image values for normalization .TP \fB\-image_minimum\fR\ \fImin\fR Specify the minimum real image value for normalization .TP \fB\-image_maximum\fR\ \fImax\fR Specify the maximum real image value for normalization .TP \fB\-start\fR\ \fIindexvector\fR Specifies corner of hyperslab (C conventions for indices). Indices are either separated by spaces (enclosed by quotes) or commas (no quotes required). .TP \fB\-count\fR\ \fIindexvector\fR Specifies edge lengths of hyperslab to read. Indices are either separated by spaces (enclosed by quotes) or commas (no quotes required). .TP \fB\-positive_direction\fR Flip images to always have positive direction. .TP \fB\-negative_direction\fR Flip images to always have negative direction. .TP \fB\-any_direction\fR Do not flip images (Default). .TP \fB\+xdirection\fR Flip images to give positive xspace:step value (left-to-right). .TP \fB\-xdirection\fR Flip images to give negative xspace:step value (right-to-left). .TP \fB\-xanydirection\fR Don't flip images along x-axis (default). .TP \fB\+ydirection\fR Flip images to give positive yspace:step value (post-to-ant). .TP \fB\-ydirection\fR Flip images to give negative yspace:step value (ant-to-post). .TP \fB\-yanydirection\fR Don't flip images along y-axis (default). .TP \fB\+zdirection\fR Flip images to give positive zspace:step value (inf-to-sup). .TP \fB\-zdirection\fR Flip images to give negative zspace:step value (sup-to-inf). .TP \fB\-zanydirection\fR Don't flip images along z-axis (default). .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 by Peter Neelin .SH "SEE ALSO" .LP .BR minctoraw (1)minc-2.2.00/progs/mincextract/mincextract.c0000644000265600003100000004276512027132662015616 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincextract @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to dump a hyperslab of minc file data @METHOD : @GLOBALS : @CALLS : @CREATED : June 10, 1993 (Peter Neelin) @MODIFIED : * $Log: mincextract.c,v $ * Revision 6.9 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.8 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.7 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.6 2006/05/19 00:35:58 bert * Add config.h to several files that might need it * * Revision 6.5 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.4 2003/10/28 20:31:19 bert * Remove two unused variables * * Revision 6.3 2001/08/16 16:41:35 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.2 2001/04/17 18:40:19 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:23 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:38 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:38 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:45 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:33 neelin * Release of minc version 0.3 * * Revision 2.2 1995/02/08 19:31:47 neelin * Moved ARGSUSED statements for irix 5 lint. * * Revision 2.1 1995/01/23 12:32:52 neelin * Changed ncopen, ncclose to miopen, miclose. * * Revision 2.0 94/09/28 10:34:16 neelin * Release of minc version 0.2 * * Revision 1.12 94/09/28 10:34:12 neelin * Pre-release * * Revision 1.11 94/04/14 08:45:51 neelin * Added options for flipping images. * * Revision 1.10 94/04/11 16:12:42 neelin * Added -image_range, -image_minimum, -image_maximum. * Changed default to -normalize. * Changed behaviour so that -byte gives default range and sign even if * file is of type byte (must use -filetype to preserve range and sign). * * Revision 1.9 93/08/11 15:49:49 neelin * get_arg_vector must return a value (TRUE if all goes well). * * Revision 1.8 93/08/11 15:44:54 neelin * Functions called by ParseArgv must check that nextArg is not NULL. * * Revision 1.7 93/08/11 15:20:02 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define VECTOR_SEPARATOR ',' #define TYPE_ASCII 0 #define TYPE_BYTE 1 #define TYPE_SHORT 2 #define TYPE_INT 3 #define TYPE_FLOAT 4 #define TYPE_DOUBLE 5 #define TYPE_FILE 6 static nc_type nc_type_list[8] = { NC_DOUBLE, NC_BYTE, NC_SHORT, NC_INT, NC_FLOAT, NC_DOUBLE, NC_DOUBLE }; /* Function declarations */ static int get_arg_vector(char *dst, char *key, char *nextArg); /* Variables used for argument parsing */ static int arg_odatatype = TYPE_ASCII; static nc_type output_datatype = NC_DOUBLE; static int output_signed = INT_MAX; static double valid_range[2] = {DBL_MAX, DBL_MAX}; static int normalize_output = TRUE; static double image_range[2] = {DBL_MAX, DBL_MAX}; static long hs_start[MAX_VAR_DIMS] = {LONG_MIN}; static long hs_count[MAX_VAR_DIMS] = {LONG_MIN}; static int xdirection = INT_MAX; static int ydirection = INT_MAX; static int zdirection = INT_MAX; static int default_direction = INT_MAX; /* Argument table */ ArgvInfo argTable[] = { {"-ascii", ARGV_CONSTANT, (char *) TYPE_ASCII, (char *) &arg_odatatype, "Write out data as ascii strings (default)"}, {"-byte", ARGV_CONSTANT, (char *) TYPE_BYTE, (char *) &arg_odatatype, "Write out data as bytes"}, {"-short", ARGV_CONSTANT, (char *) TYPE_SHORT, (char *) &arg_odatatype, "Write out data as short integers"}, {"-int", ARGV_CONSTANT, (char *) TYPE_INT, (char *) &arg_odatatype, "Write out data as 32-bit integers"}, {"-long", ARGV_CONSTANT, (char *) TYPE_INT, (char *) &arg_odatatype, "Superseded by -int"}, {"-float", ARGV_CONSTANT, (char *) TYPE_FLOAT, (char *) &arg_odatatype, "Write out data as single precision floating-point values"}, {"-double", ARGV_CONSTANT, (char *) TYPE_DOUBLE, (char *) &arg_odatatype, "Write out data as double precision floating-point values"}, {"-filetype", ARGV_CONSTANT, (char *) TYPE_FILE, (char *) &arg_odatatype, "Write out data in the type of the file"}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &output_signed, "Write out signed data"}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &output_signed, "Write out unsigned data"}, {"-range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Specify the range of output values"}, {"-normalize", ARGV_CONSTANT, (char *) TRUE, (char *) &normalize_output, "Normalize integer pixel values to file max and min (Default)"}, {"-nonormalize", ARGV_CONSTANT, (char *) FALSE, (char *) &normalize_output, "Turn off pixel normalization"}, {"-image_range", ARGV_FLOAT, (char *) 2, (char *) image_range, "Specify the range of real image values for normalization"}, {"-image_minimum", ARGV_FLOAT, (char *) 1, (char *) &image_range[0], "Specify the minimum real image value for normalization"}, {"-image_maximum", ARGV_FLOAT, (char *) 1, (char *) &image_range[1], "Specify the maximum real image value for normalization"}, {"-start", ARGV_FUNC, (char *) get_arg_vector, (char *) hs_start, "Specifies corner of hyperslab (C conventions for indices)"}, {"-count", ARGV_FUNC, (char *) get_arg_vector, (char *) hs_count, "Specifies edge lengths of hyperslab to read"}, {"-positive_direction", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &default_direction, "Flip images to always have positive direction."}, {"-negative_direction", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &default_direction, "Flip images to always have negative direction."}, {"-any_direction", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &default_direction, "Do not flip images (Default)."}, {"+xdirection", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &xdirection, "Flip images to give positive xspace:step value (left-to-right)."}, {"-xdirection", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &xdirection, "Flip images to give negative xspace:step value (right-to-left)."}, {"-xanydirection", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &xdirection, "Don't flip images along x-axis (default)."}, {"+ydirection", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &ydirection, "Flip images to give positive yspace:step value (post-to-ant)."}, {"-ydirection", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &ydirection, "Flip images to give negative yspace:step value (ant-to-post)."}, {"-yanydirection", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &ydirection, "Don't flip images along y-axis (default)."}, {"+zdirection", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &zdirection, "Flip images to give positive zspace:step value (inf-to-sup)."}, {"-zdirection", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &zdirection, "Flip images to give negative zspace:step value (sup-to-inf)."}, {"-zanydirection", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &zdirection, "Don't flip images along z-axis (default)."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *filename; int mincid, imgid, icvid, ndims, dims[MAX_VAR_DIMS]; nc_type datatype; int is_signed; long start[MAX_VAR_DIMS], end[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS], cur[MAX_VAR_DIMS]; int element_size; int idim; int nstart, ncount; void *data; double temp; long nelements, ielement; double *dbl_data; int user_normalization; /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc != 2)) { (void) fprintf(stderr, "\nUsage: %s [] \n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } filename = argv[1]; /* Set normalization if image_range specified */ user_normalization = FALSE; if ((image_range[0] != DBL_MAX) || (image_range[1] != DBL_MAX)) { user_normalization = TRUE; normalize_output = TRUE; } /* Check direction values */ if (default_direction == INT_MAX) default_direction = MI_ICV_ANYDIR; if (xdirection == INT_MAX) xdirection = default_direction; if (ydirection == INT_MAX) ydirection = default_direction; if (zdirection == INT_MAX) zdirection = default_direction; /* Open the file */ mincid = miopen(filename, NC_NOWRITE); /* Inquire about the image variable */ imgid = ncvarid(mincid, MIimage); (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dims, NULL); (void) miget_datatype(mincid, imgid, &datatype, &is_signed); /* Check if arguments set */ /* Check the start and count arguments */ for (nstart=0; (nstart valid_range[1]) { temp = valid_range[0]; valid_range[0] = valid_range[1]; valid_range[1] = temp; } /* Set up image conversion */ icvid = miicv_create(); (void) miicv_setint(icvid, MI_ICV_TYPE, output_datatype); (void) miicv_setstr(icvid, MI_ICV_SIGN, (output_signed ? MI_SIGNED : MI_UNSIGNED)); (void) miicv_setdbl(icvid, MI_ICV_VALID_MIN, valid_range[0]); (void) miicv_setdbl(icvid, MI_ICV_VALID_MAX, valid_range[1]); (void) miicv_setint(icvid, MI_ICV_DO_DIM_CONV, TRUE); (void) miicv_setint(icvid, MI_ICV_DO_SCALAR, FALSE); (void) miicv_setint(icvid, MI_ICV_XDIM_DIR, xdirection); (void) miicv_setint(icvid, MI_ICV_YDIM_DIR, ydirection); (void) miicv_setint(icvid, MI_ICV_ZDIM_DIR, zdirection); if ((output_datatype == NC_FLOAT) || (output_datatype == NC_DOUBLE)) { (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); } else if (normalize_output) { (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); if (user_normalization) { (void) miicv_attach(icvid, mincid, imgid); if (image_range[0] == DBL_MAX) { (void) miicv_inqdbl(icvid, MI_ICV_NORM_MIN, &image_range[0]); } if (image_range[1] == DBL_MAX) { (void) miicv_inqdbl(icvid, MI_ICV_NORM_MAX, &image_range[1]); } (void) miicv_detach(icvid); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MIN, image_range[0]); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MAX, image_range[1]); } } (void) miicv_attach(icvid, mincid, imgid); /* Set input file start, count and end vectors for reading a slice at a time */ nelements = 1; for (idim=0; idim < ndims; idim++) { /* Get start */ start[idim] = (nstart == 0) ? 0 : hs_start[idim]; cur[idim] = start[idim]; /* Get end */ if (ncount!=0) end[idim] = start[idim]+hs_count[idim]; else if (nstart!=0) end[idim] = start[idim]+1; else (void) ncdiminq(mincid, dims[idim], NULL, &end[idim]); /* Compare start and end */ if (start[idim] >= end[idim]) { (void) fprintf(stderr, "start or count out of range\n"); exit(EXIT_FAILURE); } /* Get count and nelements */ if (idim < ndims-2) count[idim] = 1; else count[idim] = end[idim] - start[idim]; nelements *= count[idim]; } element_size = nctypelen(output_datatype); /* Allocate space */ data = malloc(element_size*nelements); /* Loop over input slices */ while (cur[0] < end[0]) { /* Read in the slice */ (void) miicv_get(icvid, cur, count, data); /* Write out the slice */ if (arg_odatatype == TYPE_ASCII) { dbl_data = data; for (ielement=0; ielement0) && (cur[idim] >= end[idim])) { cur[idim] = start[idim]; idim--; cur[idim] += count[idim]; } } /* End loop over slices */ /* Clean up */ (void) miclose(mincid); (void) miicv_free(icvid); free(data); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_arg_vector @INPUT : key - argv key string (-start, -count) nextArg - string from which vector should be read @OUTPUT : dst - pointer to vector of longs into which values should be written (padded with LONG_MIN) @RETURNS : TRUE, since nextArg is used (unless it is NULL) @DESCRIPTION: Parses a command-line argument into a vector of longs. The string should contain at most MAX_VAR_DIMS comma separated integer values (spaces are skipped). @METHOD : @GLOBALS : @CALLS : @CREATED : June 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_arg_vector(char *dst, char *key, char *nextArg) /* ARGSUSED */ { long *vector; int nvals, i; char *cur, *end, *prev; /* Check for following argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); return FALSE; } /* Get pointer to vector of longs */ vector = (long *) dst; /* Set up pointers to end of string and first non-space character */ end = nextArg + strlen(nextArg); cur = nextArg; while (isspace(*cur)) cur++; nvals = 0; /* Loop through string looking for integers */ while ((nvals < MAX_VAR_DIMS) && (cur!=end)) { /* Get integer */ prev = cur; vector[nvals] = strtol(prev, &cur, 0); if (cur == prev) { (void) fprintf(stderr, "expected vector of integers for \"%s\", but got \"%s\"\n", key, nextArg); exit(EXIT_FAILURE); } nvals++; /* Skip any spaces */ while (isspace(*cur)) cur++; /* Skip an optional comma */ if (*cur == VECTOR_SEPARATOR) cur++; } /* Pad with LONG_MIN */ for (i=nvals; i < MAX_VAR_DIMS; i++) { vector[i] = LONG_MIN; } return TRUE; } minc-2.2.00/progs/mincgen/0000755000265600003100000000000012030114723012262 500000000000000minc-2.2.00/progs/mincgen/generic.h0000644000265600003100000000104512027132663014000 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/generic.h,v 1.1 2004-06-15 20:14:40 bert Exp $ *********************************************************************/ #ifndef UD_GENERIC_H #define UD_GENERIC_H union generic { /* used to hold any kind of fill_value */ float floatv; double doublev; int intv; short shortv; char charv; }; #endif minc-2.2.00/progs/mincgen/genlib.h0000644000265600003100000000556012027132663013632 00000000000000#ifndef NC_GENLIB_H #define NC_GENLIB_H /********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/genlib.h,v 1.1 2004-06-15 20:14:40 bert Exp $ *********************************************************************/ #include #include extern const char *progname; /* for error messages */ extern const char *cdlname; /* for error messages */ #define FORT_MAX_LINES 20 /* max lines in FORTRAN statement */ #define FORT_MAX_STMNT 66*FORT_MAX_LINES /* max chars in FORTRAN statement */ #define C_MAX_STMNT FORT_MAX_STMNT /* until we fix to break up C lines */ #ifdef __cplusplus extern "C" { #endif extern void cline ( const char* stmnt ); extern void fline ( const char* stmnt ); extern char* nctype ( nc_type type ); extern char* ncctype ( nc_type type ); extern char* ncstype ( nc_type type ); extern char* ncatype ( nc_type type ); extern char* nfstype ( nc_type type ); extern char* nfftype ( nc_type type ); extern char* fstring ( nc_type type, void* valp, int num ); extern char* cstrstr ( const char* valp, size_t len ); extern char* fstrstr ( const char* str, size_t ilen ); extern size_t nctypesize( nc_type type ); extern void derror ( const char *fmt, ... ); extern void check_err ( int status ); extern void *emalloc ( size_t size ); extern void *ecalloc ( size_t size ); extern void *erealloc ( void *ptr, size_t size ); extern void expe2d ( char *ptr ); extern void grow_iarray ( int narray, int **array ); extern void grow_varray ( int narray, struct vars **array ); extern void grow_darray ( int narray, struct dims **array ); extern void grow_aarray ( int narray, struct atts **array ); extern char* decodify (const char *name); extern int put_variable ( void* rec_start ); /* initializes netcdf counts (e.g. nvars), defined in init.c */ extern void init_netcdf ( int ); /* generates all define mode stuff, defined in genlib.c */ extern void define_netcdf(char *netcdfname); /* generates variable puts, defined in load.c */ extern void load_netcdf ( void* rec_start ); /* generates close, defined in close.c */ extern void close_netcdf ( void ); /* defined in escapes.c */ extern void expand_escapes ( char* termstring, char* yytext, int yyleng ); /* to get fill value for various types, defined in getfill.c */ extern void nc_getfill ( nc_type type, union generic* gval ); /* to put fill value for various types, defined in getfill.c */ extern void nc_putfill ( nc_type type, void* val, union generic* gval ); /* fills a generic array with a value, defined in getfill.c */ extern void nc_fill ( nc_type type, size_t num, void* datp, union generic fill_val ); /* reset symbol table to empty, defined in ncgen.y */ extern void clearout(void); #ifdef __cplusplus } #endif #endif /*!NC_GENLIB_H*/ minc-2.2.00/progs/mincgen/ncgen.h0000644000265600003100000000454712027132663013470 00000000000000#ifndef NC_NCGEN_H #define NC_NCGEN_H /********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/ncgen.h,v 1.2 2007-02-02 18:49:36 baghdadi Exp $ *********************************************************************/ #define MAX_NC_ATTSIZE 500000 /* max size of attribute (for ncgen) */ #define MAXTRST 100000 /* max size of string value (for ncgen) */ /* True if string a equals string b*/ #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) #include "generic.h" extern int ncid; /* handle for netCDF */ extern int ndims; /* number of dimensions declared for netcdf */ extern int nvars; /* number of variables declared for netcdf */ extern int natts; /* number of attributes */ extern int nvdims; /* number of dimensions for variables */ extern int dimnum; /* dimension number index for variables */ extern int varnum; /* variable number index for attributes */ extern int valnum; /* number of values specified for variable */ extern int rec_dim; /* number of the unlimited dimension, if any */ extern size_t rec_len; /* number of elements for a record of data */ extern size_t var_len; /* variable length (product of dimensions) */ extern size_t var_size; /* size of each element of variable */ extern int is_hdf5; extern struct dims { size_t size; char *name; char *lname; /* with no "-" characters, for C and Fortran */ } *dims; /* table of dimensions */ extern struct vars { char *name; nc_type type; int ndims; int *dims; /* array of dimension ids */ union generic fill_value; /* set to value of _FillValue attribute */ int has_data; /* 1 if data specified, 0 otherwise */ size_t nrecs; /* for record variables, number of records * of data in CDL */ char *data_stmnt; /* for record variables, to avoid * two passes with -f option */ char *lname; /* with no "-" characters, for C and Fortran */ } *vars; /* table of variables */ extern struct atts { int var; /* number of variable for this attribute */ char *name; nc_type type; size_t len; void *val; char *lname; /* with no "-" characters, for C and Fortran */ } *atts; /* table of variable and global attributes */ #endif /*!NC_NCGEN_H*/ minc-2.2.00/progs/mincgen/ncgentab.h0000644000265600003100000000554412030102322014134 00000000000000 /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NC_UNLIMITED_K = 258, BYTE_K = 259, CHAR_K = 260, SHORT_K = 261, INT_K = 262, FLOAT_K = 263, DOUBLE_K = 264, IDENT = 265, TERMSTRING = 266, BYTE_CONST = 267, CHAR_CONST = 268, SHORT_CONST = 269, INT_CONST = 270, FLOAT_CONST = 271, DOUBLE_CONST = 272, DIMENSIONS = 273, VARIABLES = 274, NETCDF = 275, HDF5 = 276, DATA = 277, FILLVALUE = 278 }; #endif /* Tokens. */ #define NC_UNLIMITED_K 258 #define BYTE_K 259 #define CHAR_K 260 #define SHORT_K 261 #define INT_K 262 #define FLOAT_K 263 #define DOUBLE_K 264 #define IDENT 265 #define TERMSTRING 266 #define BYTE_CONST 267 #define CHAR_CONST 268 #define SHORT_CONST 269 #define INT_CONST 270 #define FLOAT_CONST 271 #define DOUBLE_CONST 272 #define DIMENSIONS 273 #define VARIABLES 274 #define NETCDF 275 #define HDF5 276 #define DATA 277 #define FILLVALUE 278 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; minc-2.2.00/progs/mincgen/mincgen.man10000644000265600003100000003116312027132663014415 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" $Header: /private-cvsroot/minc/progs/mincgen/mincgen.man1,v 1.3 2008-10-12 05:07:12 stever Exp $ .TH MINCGEN 1 "$Date: 2008-10-12 05:07:12 $" "" "MINC User's Guide" .SH NAME mincgen \- Generate a MINC file from a CDL file. .SH SYNOPSIS .HP mincgen .nh \%[-b] \%[-n] \%[-o \fIminc_filename\fP] \%\fIinput_file\fP .hy .ft .SH DESCRIPTION \fBmincgen\fP generates a MINC file. The input to \fBmincgen\fP is a description of a MINC file in a small language known as CDL (network Common Data form Language), described below. If no options are specified in invoking \fBmincgen\fP, it merely checks the syntax of the input CDL file, producing error messages for any violations of CDL syntax. Other options can be used to create the corresponding MINC file. .LP \fBmincgen\fP may be used with the companion program \fBmincdump\fP to perform some simple operations on MINC files. For example, to rename a dimension in a MINC file, use \fBmincdump\fP to get a CDL version of the MINC file, edit the CDL file to change the name of the dimensions, and use \fBmincgen\fP to generate the corresponding MINC file from the edited CDL file. .SH OPTIONS .IP "\fB-b\fP" Create a (binary) MINC file. If the \fB-o\fP option is absent, a default file name will be constructed from the MINC name (specified after the \fBnetcdf\fP or \fBhdf5\fP keyword in the input) by appending the `.mnc' extension. If a file already exists with the specified name, it will be overwritten. .IP "\fB-o\fP \fRminc_filename\fP" Name for the binary MINC file created. If this option is specified, it implies the "\fB-b\fP" option. (This option is necessary because MINC files cannot be written directly to standard output, since standard output is not seekable.) .SH EXAMPLES .LP Check the syntax of the CDL file `\fBfoo.cdl\fP': .RS .HP mincgen foo.cdl .RE .LP From the CDL file `\fBfoo.cdl\fP', generate an equivalent binary MINC file named `\fBx.mnc\fP': .RS .HP mincgen -o x.mnc foo.cdl .RE .LP .SH USAGE .SS "CDL Syntax Summary" .LP Below is an example of CDL syntax, describing a MINC file with several named dimensions (xspace, yspace, and zspace), variables (zspace, image), variable attributes (valid_range, signtype), and some data. CDL keywords are in boldface. (This example is intended to illustrate the syntax; a real CDL file would have a more complete set of attributes so that the data would be more completely self-describing.) .RS .nf \fBnetcdf\fP foo { // an example MINC specification in CDL \fBdimensions\fP: xspace = 8; yspace = 8; zspace = 5; \fBvariables\fP: \fBfloat\fP xspace; \fBfloat\fP yspace; \fBfloat\fP zspace(zspace); \fBshort\fP image(zspace,yspace,xspace); \fBdouble\fP image-min(zspace) \fBdouble\fP image-max(zspace) // variable attributes image:valid_range = 0,5; \fBdata\fP: image-min = -1,-1,-1,-1,-1; image-max = 1,1,1,1,1; image = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5; zspace = 0,2,3.5,7,10; } .fi .RE .LP All CDL statements are terminated by a semicolon. Spaces, tabs, and newlines can be used freely for readability. Comments may follow the characters `//' on any line. .LP A CDL description consists of three optional parts: \fIdimensions\fP, \fIvariables\fP, and \fIdata\fP, beginning with the keyword .BR dimensions: , .BR variables: , and .BR data , respectively. The variable part may contain \fIvariable declarations\fP and \fIattribute assignments\fP. .LP A MINC \fIdimension\fP is used to define the shape of one or more of the multidimensional variables contained in the MINC file. A MINC dimension has a name, a size, and possibly several other attributes. .LP A \fIvariable\fP represents a multidimensional array of values of the same type. A variable has a name, a data type, and a shape described by its list of dimensions. Each variable may also have associated \fIattributes\fP (see below) as well as data values. The name, data type, and shape of a variable are specified by its declaration in the \fIvariable\fP section of a CDL description. A variable may have the same name as a dimension; by convention such a variable is one-dimensional and contains coordinates of the dimension it names. Dimensions need not have corresponding variables. .LP A netCDF \fIattribute\fP contains information about a netCDF variable or about the whole netCDF dataset. Attributes are used to specify such properties as units, special values, maximum and minimum valid values, scaling factors, offsets, and parameters. Attribute information is represented by single values or arrays of values. For example, "units" is an attribute represented by a character array such as "celsius". An attribute has an associated variable, a name, a data type, a length, and a value. In contrast to variables that are intended for data, attributes are intended for metadata (data about data). .LP In CDL, an attribute is designated by a variable and attribute name, separated by `:'. It is possible to assign \fIglobal\fP attributes not associated with any variable to the file as a whole by using `:' before the attribute name. The data type of an attribute in CDL is derived from the type of the value assigned to it. The length of an attribute is the number of data values assigned to it, or the number of characters in the character string assigned to it. Multiple values are assigned to non-character attributes by separating the values with commas. All values assigned to an attribute must be of the same type. .LP The names for CDL dimensions, variables, and attributes must begin with an alphabetic character or `_', and subsequent characters may be alphanumeric or `_' or `-'. .LP The optional \fIdata\fP section of a CDL specification is where variables may be initialized. The syntax of an initialization is simple: a variable name, an equals sign, and a comma-delimited list of constants (possibly separated by spaces, tabs and newlines) terminated with a semicolon. For multi-dimensional arrays, the last dimension varies fastest. Thus row-order rather than column order is used for matrices. If fewer values are supplied than are needed to fill a variable, it is extended with a type-dependent `fill value', which can be overridden by supplying a value for a distinguished variable attribute named `_FillValue'. The types of constants need not match the type declared for a variable; coercions are done to convert integers to floating point, for example. The constant `_' can be used to designate the fill value for a variable. .SS "Primitive Data Types" .LP .RS .nf \fBchar\fP characters \fBbyte\fP 8-bit data \fBshort\fP 16-bit signed integers \fBlong\fP 32-bit signed integers \fBint\fP (synonymous with \fBlong\fP) \fBfloat\fP IEEE single precision floating point (32 bits) \fBreal\fP (synonymous with \fBfloat\fP) \fBdouble\fP IEEE double precision floating point (64 bits) .fi .RE .LP Except for the added data-type \fBbyte\fP and the lack of \fBunsigned\fP, CDL supports the same primitive data types as C. The names for the primitive data types are reserved words in CDL, so the names of variables, dimensions, and attributes must not be type names. In declarations, type names may be specified in either upper or lower case. .LP Bytes differ from characters in that they are intended to hold a full eight bits of data, and the zero byte has no special significance, as it does for character data. .LP Shorts can hold values between -32768 and 32767. .LP Longs can hold values between -2147483648 and 2147483647. \fBint\fP and \fBinteger\fP are accepted as synonyms for \fBlong\fP in CDL declarations. Now that there are platforms with 64-bit representations for C longs, it may be better to use the \fBint\fP synonym to avoid confusion. .LP Floats can hold values between about -3.4+38 and 3.4+38. Their external representation is as 32-bit IEEE normalized single-precision floating point numbers. \fBreal\fP is accepted as a synonym for \fBfloat\fP in CDL declarations. .LP Doubles can hold values between about -1.7+308 and 1.7+308. Their external representation is as 64-bit IEEE standard normalized double-precision floating point numbers. .LP .SS "CDL Constants" .LP Constants assigned to attributes or variables may be of any of the basic MINC types. The syntax for constants is similar to C syntax, except that type suffixes must be appended to shorts and floats to distinguish them from longs and doubles. .LP A \fIbyte\fP constant is represented by a single character or multiple character escape sequence enclosed in single quotes. For example, .RS .nf 'a' // ASCII `a' '\\0' // a zero byte '\\n' // ASCII newline character '\\33' // ASCII escape character (33 octal) '\\x2b' // ASCII plus (2b hex) '\\377' // 377 octal = 255 decimal, non-ASCII .fi .RE .LP Character constants are enclosed in double quotes. A character array may be represented as a string enclosed in double quotes. The usual C string escape conventions are honored. For example .RS .nf "a" // ASCII `a' "Two\\nlines\\n" // a 10-character string with two embedded newlines "a bell:\\007" // a string containing an ASCII bell .fi .RE Note that the character array "a" would fit in a one-element variable, since no terminating NULL character is assumed. However, a zero byte in a character array is interpreted as the end of the significant characters by the \fBmincdump\fP program, following the C convention. Therefore, a NULL byte should not be embedded in a character string unless at the end: use the \fIbyte\fP data type instead for byte arrays that contain the zero byte. MINC and CDL have no string type, but only fixed-length character arrays, which may be multi-dimensional. .LP \fIshort\fP integer constants are intended for representing 16-bit signed quantities. The form of a \fIshort\fP constant is an integer constant with an `s' or `S' appended. If a \fIshort\fP constant begins with `0', it is interpreted as octal, except that if it begins with `0x', it is interpreted as a hexadecimal constant. For example: .RS .nf -2s // a short -2 0123s // octal 0x7ffs //hexadecimal .fi .RE .LP \fILong\fP integer constants are intended for representing 32-bit signed quantities. The form of a \fIlong\fP constant is an ordinary integer constant, although it is acceptable to append an optional `l' or `L'. If a \fIlong\fP constant begins with `0', it is interpreted as octal, except that if it begins with `0x', it is interpreted as a hexadecimal constant. Examples of valid \fIlong\fP constants include: .RS .nf -2 1234567890L 0123 // octal 0x7ff // hexadecimal .fi .RE .LP Floating point constants of type \fIfloat\fP are appropriate for representing floating point data with about seven significant digits of precision. The form of a \fIfloat\fP constant is the same as a C floating point constant with an `f' or `F' appended. For example the following are all acceptable \fIfloat\fP constants: .RS .nf -2.0f 3.14159265358979f // will be truncated to less precision 1.f .fi .RE .LP Floating point constants of type \fIdouble\fP are appropriate for representing floating point data with about sixteen significant digits of precision. The form of a \fIdouble\fP constant is the same as a C floating point constant. An optional `d' or `D' may be appended. For example the following are all acceptable \fIdouble\fP constants: .RS .nf -2.0 3.141592653589793 1.0e-20 1.d .fi .RE .SH AUTHOR Originally written by members of the Unidata Program at the University Corporation for Atmospheric Research. Modified by Bert Vincent (bert@bic.mni.mcgill.ca) for use with both netCDF and HDF5 files. .SH COPYRIGHTS Copyright \(co University Corporation for Atmospheric Research .SH "SEE ALSO" .LP .BR ncdump (1), .BR ncgen (1), .BR netcdf (3) .SH BUGS .LP The CDL syntax makes it easy to assign what looks like an array of variable-length strings to a variable, but the strings will simply be concatenated into a single array of characters, since MINC cannot represent an array of variable-length strings in one MINC variable. .LP MINC and CDL do not yet support a type corresponding to a 64-bit integer. minc-2.2.00/progs/mincgen/ncgentab.c0000644000265600003100000021351312030102322014124 00000000000000 /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.4.1" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 9 "ncgentab.y" #ifndef lint static char SccsId[] __attribute__ ((unused)) = "$Id: ncgentab.y,v 1.3 2008-01-13 06:49:41 stever Exp $"; #endif #include #include #include #include "generic.h" #include "ncgen.h" #include "genlib.h" /* for grow_darray() et al */ typedef struct Symbol { /* symbol table entry */ char *name; struct Symbol *next; unsigned is_dim : 1; /* appears as netCDF dimension */ unsigned is_var : 1; /* appears as netCDF variable */ unsigned is_att : 1; /* appears as netCDF attribute */ int dnum; /* handle as a dimension */ int vnum; /* handle as a variable */ } *YYSTYPE1; #define YYSTYPE YYSTYPE1 YYSTYPE symlist; /* symbol table: linked list */ extern int derror_count; /* counts errors in netcdf definition */ extern int lineno; /* line number for error messages */ static int not_a_string; /* whether last constant read was a string */ char termstring[MAXTRST]; /* last terminal string read */ double double_val; /* last double value read */ float float_val; /* last float value read */ int int_val; /* last int value read */ short short_val; /* last short value read */ static char char_val; /* last char value read */ signed char byte_val; /* last byte value read */ static nc_type type_code; /* holds declared type for variables */ static nc_type atype_code; /* holds derived type for attributes */ char *netcdfname; /* to construct netcdf file name */ static void *att_space; /* pointer to block for attribute values */ static nc_type valtype; /* type code for list of attribute values */ static char *char_valp; /* pointers used to accumulate data values */ static signed char *byte_valp; static short *short_valp; static int *int_valp; static float *float_valp; static double *double_valp; static void *rec_cur; /* pointer to where next data value goes */ static void *rec_start; /* start of space for data */ /* Line 189 of yacc.c */ #line 126 "progs/mincgen/ncgentab.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 1 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NC_UNLIMITED_K = 258, BYTE_K = 259, CHAR_K = 260, SHORT_K = 261, INT_K = 262, FLOAT_K = 263, DOUBLE_K = 264, IDENT = 265, TERMSTRING = 266, BYTE_CONST = 267, CHAR_CONST = 268, SHORT_CONST = 269, INT_CONST = 270, FLOAT_CONST = 271, DOUBLE_CONST = 272, DIMENSIONS = 273, VARIABLES = 274, NETCDF = 275, HDF5 = 276, DATA = 277, FILLVALUE = 278 }; #endif /* Tokens. */ #define NC_UNLIMITED_K 258 #define BYTE_K 259 #define CHAR_K 260 #define SHORT_K 261 #define INT_K 262 #define FLOAT_K 263 #define DOUBLE_K 264 #define IDENT 265 #define TERMSTRING 266 #define BYTE_CONST 267 #define CHAR_CONST 268 #define SHORT_CONST 269 #define INT_CONST 270 #define FLOAT_CONST 271 #define DOUBLE_CONST 272 #define DIMENSIONS 273 #define VARIABLES 274 #define NETCDF 275 #define HDF5 276 #define DATA 277 #define FILLVALUE 278 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 214 "progs/mincgen/ncgentab.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 6 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 87 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 32 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 42 /* YYNRULES -- Number of rules. */ #define YYNRULES 78 /* YYNRULES -- Number of states. */ #define YYNSTATES 115 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 278 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 29, 30, 2, 2, 27, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 31, 26, 2, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 24, 2, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 4, 5, 14, 15, 16, 25, 26, 29, 32, 36, 38, 42, 46, 50, 52, 54, 55, 58, 60, 63, 67, 69, 71, 74, 78, 80, 83, 85, 87, 89, 91, 93, 95, 97, 101, 102, 106, 108, 109, 113, 115, 119, 121, 122, 127, 131, 134, 136, 138, 140, 144, 146, 148, 150, 152, 154, 156, 158, 160, 161, 164, 167, 171, 172, 177, 179, 183, 184, 187, 189, 191, 193, 195, 197, 199, 201 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 33, 0, -1, -1, -1, 20, 24, 34, 38, 44, 35, 66, 25, -1, -1, -1, 21, 24, 36, 38, 44, 37, 66, 25, -1, -1, 18, 39, -1, 40, 26, -1, 39, 40, 26, -1, 41, -1, 40, 27, 41, -1, 42, 28, 15, -1, 42, 28, 3, -1, 43, -1, 10, -1, -1, 19, 45, -1, 47, -1, 46, 26, -1, 45, 46, 26, -1, 49, -1, 58, -1, 48, 26, -1, 47, 48, 26, -1, 58, -1, 50, 51, -1, 4, -1, 5, -1, 6, -1, 7, -1, 8, -1, 9, -1, 52, -1, 51, 27, 52, -1, -1, 54, 53, 55, -1, 10, -1, -1, 29, 56, 30, -1, 57, -1, 56, 27, 57, -1, 43, -1, -1, 60, 59, 28, 63, -1, 61, 31, 62, -1, 31, 62, -1, 54, -1, 10, -1, 64, -1, 63, 27, 64, -1, 65, -1, 13, -1, 11, -1, 12, -1, 14, -1, 15, -1, 16, -1, 17, -1, -1, 22, 67, -1, 68, 26, -1, 67, 68, 26, -1, -1, 61, 69, 28, 70, -1, 71, -1, 70, 27, 71, -1, -1, 72, 73, -1, 13, -1, 11, -1, 12, -1, 14, -1, 15, -1, 16, -1, 17, -1, 23, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 94, 94, 97, 92, 110, 113, 108, 124, 125, 127, 128, 130, 131, 133, 139, 147, 163, 165, 166, 167, 169, 170, 172, 172, 174, 175, 177, 179, 181, 182, 183, 184, 185, 186, 188, 189, 192, 191, 230, 232, 233, 235, 236, 238, 260, 259, 304, 305, 311, 321, 332, 333, 335, 344, 350, 363, 369, 375, 381, 387, 395, 396, 399, 400, 403, 402, 467, 468, 471, 471, 522, 547, 601, 626, 651, 676, 701, 729 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "NC_UNLIMITED_K", "BYTE_K", "CHAR_K", "SHORT_K", "INT_K", "FLOAT_K", "DOUBLE_K", "IDENT", "TERMSTRING", "BYTE_CONST", "CHAR_CONST", "SHORT_CONST", "INT_CONST", "FLOAT_CONST", "DOUBLE_CONST", "DIMENSIONS", "VARIABLES", "NETCDF", "HDF5", "DATA", "FILLVALUE", "'{'", "'}'", "';'", "','", "'='", "'('", "')'", "':'", "$accept", "ncdesc", "$@1", "$@2", "$@3", "$@4", "dimsection", "dimdecls", "dimdecline", "dimdecl", "dimd", "dim", "vasection", "vadecls", "vadecl", "gattdecls", "gattdecl", "vardecl", "type", "varlist", "varspec", "$@5", "var", "dimspec", "dimlist", "vdim", "attdecl", "$@6", "att", "avar", "attr", "attvallist", "aconst", "attconst", "datasection", "datadecls", "datadecl", "$@7", "constlist", "dconst", "$@8", "const", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 123, 125, 59, 44, 61, 40, 41, 58 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 32, 34, 35, 33, 36, 37, 33, 38, 38, 39, 39, 40, 40, 41, 41, 42, 43, 44, 44, 44, 45, 45, 46, 46, 47, 47, 48, 49, 50, 50, 50, 50, 50, 50, 51, 51, 53, 52, 54, 55, 55, 56, 56, 57, 59, 58, 60, 60, 61, 62, 63, 63, 64, 65, 65, 65, 65, 65, 65, 65, 66, 66, 67, 67, 69, 68, 70, 70, 72, 71, 73, 73, 73, 73, 73, 73, 73, 73 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 0, 8, 0, 0, 8, 0, 2, 2, 3, 1, 3, 3, 3, 1, 1, 0, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 0, 3, 1, 0, 3, 1, 3, 1, 0, 4, 3, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 3, 0, 4, 1, 3, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 0, 0, 0, 0, 2, 5, 1, 8, 8, 0, 18, 18, 17, 9, 0, 12, 0, 16, 39, 0, 0, 3, 20, 0, 49, 27, 45, 0, 6, 0, 10, 0, 0, 29, 30, 31, 32, 33, 34, 19, 0, 23, 0, 24, 50, 48, 61, 0, 25, 0, 0, 61, 11, 13, 15, 14, 0, 21, 28, 35, 37, 0, 0, 26, 0, 47, 0, 22, 0, 40, 65, 62, 0, 4, 55, 56, 54, 57, 58, 59, 60, 46, 51, 53, 7, 36, 0, 38, 0, 0, 63, 0, 44, 0, 42, 69, 64, 52, 0, 41, 66, 67, 0, 43, 69, 72, 73, 71, 74, 75, 76, 77, 78, 70, 68 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 3, 7, 46, 8, 51, 10, 13, 14, 15, 16, 17, 21, 39, 40, 22, 23, 41, 42, 58, 59, 69, 24, 87, 93, 94, 25, 49, 26, 27, 45, 81, 82, 83, 62, 71, 72, 88, 100, 101, 102, 113 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -53 static const yytype_int8 yypact[] = { -6, -12, -5, 18, -53, -53, -53, 31, 31, 40, -2, -2, -53, 40, 17, -53, 23, -53, -53, -4, 42, -53, -1, 27, -53, -53, -53, 24, -53, 21, -53, 40, 13, -53, -53, -53, -53, -53, -53, -4, 28, -53, 46, -53, -53, -53, 35, 32, -53, 33, 42, 35, -53, -53, -53, -53, 34, -53, 36, -53, -53, 46, 37, -53, 25, -53, 39, -53, 46, 30, -53, 46, 41, -53, -53, -53, -53, -53, -53, -53, -53, 38, -53, -53, -53, -53, 40, -53, 43, 44, -53, 25, -53, -17, -53, -53, -53, -53, 40, -53, 45, -53, 9, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, -53 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -53, -53, -53, -53, -53, -53, 58, -53, 55, 47, -53, -52, 62, -53, 48, -53, 52, -53, -53, -53, 1, -53, -35, -53, -53, -23, -8, -53, -53, -26, 26, -53, -14, -53, 29, -53, 8, -53, -53, -22, -53, -53 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { 33, 34, 35, 36, 37, 38, 18, 60, 18, 18, 98, 43, 4, 99, 1, 2, 54, 19, 6, 5, 105, 106, 107, 108, 109, 110, 111, 20, 55, 20, 20, 43, 112, 60, 92, 70, 74, 75, 76, 77, 78, 79, 80, 30, 31, 70, 92, 52, 31, 9, 12, 32, 44, 48, 57, 50, 18, 61, 63, 86, 67, 64, 73, 68, 84, 91, 11, 90, 29, 85, 96, 95, 104, 28, 47, 103, 65, 97, 53, 89, 66, 0, 114, 0, 0, 0, 0, 56 }; static const yytype_int8 yycheck[] = { 4, 5, 6, 7, 8, 9, 10, 42, 10, 10, 27, 19, 24, 30, 20, 21, 3, 19, 0, 24, 11, 12, 13, 14, 15, 16, 17, 31, 15, 31, 31, 39, 23, 68, 86, 61, 11, 12, 13, 14, 15, 16, 17, 26, 27, 71, 98, 26, 27, 18, 10, 28, 10, 26, 26, 31, 10, 22, 26, 29, 26, 28, 25, 27, 25, 27, 8, 26, 13, 68, 26, 28, 27, 11, 22, 98, 50, 91, 31, 71, 51, -1, 104, -1, -1, -1, -1, 39 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 20, 21, 33, 24, 24, 0, 34, 36, 18, 38, 38, 10, 39, 40, 41, 42, 43, 10, 19, 31, 44, 47, 48, 54, 58, 60, 61, 44, 40, 26, 27, 28, 4, 5, 6, 7, 8, 9, 45, 46, 49, 50, 58, 10, 62, 35, 48, 26, 59, 31, 37, 26, 41, 3, 15, 46, 26, 51, 52, 54, 22, 66, 26, 28, 62, 66, 26, 27, 53, 61, 67, 68, 25, 11, 12, 13, 14, 15, 16, 17, 63, 64, 65, 25, 52, 29, 55, 69, 68, 26, 27, 43, 56, 57, 28, 26, 64, 27, 30, 70, 71, 72, 57, 27, 11, 12, 13, 14, 15, 16, 17, 23, 73, 71 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*-------------------------. | yyparse or yypush_parse. | `-------------------------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: /* Line 1455 of yacc.c */ #line 94 "ncgentab.y" { init_netcdf(0); } break; case 3: /* Line 1455 of yacc.c */ #line 97 "ncgentab.y" { if (derror_count == 0) define_netcdf(netcdfname); } break; case 4: /* Line 1455 of yacc.c */ #line 103 "ncgentab.y" { if (derror_count == 0) close_netcdf(); } break; case 5: /* Line 1455 of yacc.c */ #line 110 "ncgentab.y" { init_netcdf(1); } break; case 6: /* Line 1455 of yacc.c */ #line 113 "ncgentab.y" { if (derror_count == 0) define_netcdf(netcdfname); } break; case 7: /* Line 1455 of yacc.c */ #line 119 "ncgentab.y" { if (derror_count == 0) close_netcdf(); } break; case 14: /* Line 1455 of yacc.c */ #line 134 "ncgentab.y" { if (int_val <= 0) derror("dimension length must be positive"); dims[ndims].size = int_val; ndims++; } break; case 15: /* Line 1455 of yacc.c */ #line 140 "ncgentab.y" { if (rec_dim != -1) derror("only one NC_UNLIMITED dimension allowed"); rec_dim = ndims; /* the unlimited (record) dimension */ dims[ndims].size = NC_UNLIMITED; ndims++; } break; case 16: /* Line 1455 of yacc.c */ #line 148 "ncgentab.y" { if ((yyvsp[(1) - (1)])->is_dim == 1) { derror( "duplicate dimension declaration for %s", (yyvsp[(1) - (1)])->name); } (yyvsp[(1) - (1)])->is_dim = 1; (yyvsp[(1) - (1)])->dnum = ndims; /* make sure dims array will hold dimensions */ grow_darray(ndims, /* must hold ndims+1 dims */ &dims); /* grow as needed */ dims[ndims].name = (char *) emalloc(strlen((yyvsp[(1) - (1)])->name)+1); (void) strcpy(dims[ndims].name, (yyvsp[(1) - (1)])->name); /* name for use in generated Fortran and C variables */ dims[ndims].lname = decodify((yyvsp[(1) - (1)])->name); } break; case 29: /* Line 1455 of yacc.c */ #line 181 "ncgentab.y" { type_code = NC_BYTE; } break; case 30: /* Line 1455 of yacc.c */ #line 182 "ncgentab.y" { type_code = NC_CHAR; } break; case 31: /* Line 1455 of yacc.c */ #line 183 "ncgentab.y" { type_code = NC_SHORT; } break; case 32: /* Line 1455 of yacc.c */ #line 184 "ncgentab.y" { type_code = NC_INT; } break; case 33: /* Line 1455 of yacc.c */ #line 185 "ncgentab.y" { type_code = NC_FLOAT; } break; case 34: /* Line 1455 of yacc.c */ #line 186 "ncgentab.y" { type_code = NC_DOUBLE; } break; case 37: /* Line 1455 of yacc.c */ #line 192 "ncgentab.y" { static struct vars dummyvar; dummyvar.name = "dummy"; dummyvar.type = NC_DOUBLE; dummyvar.ndims = 0; dummyvar.dims = 0; dummyvar.fill_value.doublev = NC_FILL_DOUBLE; dummyvar.has_data = 0; nvdims = 0; /* make sure variable not re-declared */ if ((yyvsp[(1) - (1)])->is_var == 1) { derror( "duplicate variable declaration for %s", (yyvsp[(1) - (1)])->name); } (yyvsp[(1) - (1)])->is_var = 1; (yyvsp[(1) - (1)])->vnum = nvars; /* make sure vars array will hold variables */ grow_varray(nvars, /* must hold nvars+1 vars */ &vars); /* grow as needed */ vars[nvars] = dummyvar; /* to make Purify happy */ vars[nvars].name = (char *) emalloc(strlen((yyvsp[(1) - (1)])->name)+1); (void) strcpy(vars[nvars].name, (yyvsp[(1) - (1)])->name); /* name for use in generated Fortran and C variables */ vars[nvars].lname = decodify((yyvsp[(1) - (1)])->name); vars[nvars].type = type_code; /* set default fill value. You can override this with * the variable attribute "_FillValue". */ nc_getfill(type_code, &vars[nvars].fill_value); vars[nvars].has_data = 0; /* has no data (yet) */ } break; case 38: /* Line 1455 of yacc.c */ #line 225 "ncgentab.y" { vars[nvars].ndims = nvdims; nvars++; } break; case 44: /* Line 1455 of yacc.c */ #line 239 "ncgentab.y" { if (nvdims >= NC_MAX_VAR_DIMS) { derror("%s has too many dimensions",vars[nvars].name); } if ((yyvsp[(1) - (1)])->is_dim == 1) dimnum = (yyvsp[(1) - (1)])->dnum; else { derror( "%s is not declared as a dimension", (yyvsp[(1) - (1)])->name); dimnum = ndims; } if (rec_dim != -1 && dimnum == rec_dim && nvdims != 0) { derror("unlimited dimension must be first"); } grow_iarray(nvdims, /* must hold nvdims+1 ints */ &vars[nvars].dims); /* grow as needed */ vars[nvars].dims[nvdims] = dimnum; nvdims++; } break; case 45: /* Line 1455 of yacc.c */ #line 260 "ncgentab.y" { valnum = 0; valtype = NC_UNSPECIFIED; /* get a large block for attributes, realloc later */ att_space = emalloc(MAX_NC_ATTSIZE); /* make all kinds of pointers point to it */ char_valp = (char *) att_space; byte_valp = (signed char *) att_space; short_valp = (short *) att_space; int_valp = (int *) att_space; float_valp = (float *) att_space; double_valp = (double *) att_space; } break; case 46: /* Line 1455 of yacc.c */ #line 274 "ncgentab.y" { { /* check if duplicate attribute for this var */ int i; for(i=0; iis_var == 1) varnum = (yyvsp[(1) - (1)])->vnum; else { derror("%s not declared as a variable, fatal error", (yyvsp[(1) - (1)])->name); YYABORT; } } break; case 50: /* Line 1455 of yacc.c */ #line 322 "ncgentab.y" { /* make sure atts array will hold attributes */ grow_aarray(natts, /* must hold natts+1 atts */ &atts); /* grow as needed */ atts[natts].name = (char *) emalloc(strlen((yyvsp[(1) - (1)])->name)+1); (void) strcpy(atts[natts].name,(yyvsp[(1) - (1)])->name); /* name for use in generated Fortran and C variables */ atts[natts].lname = decodify((yyvsp[(1) - (1)])->name); } break; case 53: /* Line 1455 of yacc.c */ #line 336 "ncgentab.y" { if (valtype == NC_UNSPECIFIED) valtype = atype_code; if (valtype != atype_code) derror("values for attribute must be all of same type"); } break; case 54: /* Line 1455 of yacc.c */ #line 345 "ncgentab.y" { atype_code = NC_CHAR; *char_valp++ = char_val; valnum++; } break; case 55: /* Line 1455 of yacc.c */ #line 351 "ncgentab.y" { atype_code = NC_CHAR; { /* don't null-terminate attribute strings */ size_t len = strlen(termstring); if (len == 0) /* need null if that's only value */ len = 1; (void)strncpy(char_valp,termstring,len); valnum += len; char_valp += len; } } break; case 56: /* Line 1455 of yacc.c */ #line 364 "ncgentab.y" { atype_code = NC_BYTE; *byte_valp++ = byte_val; valnum++; } break; case 57: /* Line 1455 of yacc.c */ #line 370 "ncgentab.y" { atype_code = NC_SHORT; *short_valp++ = short_val; valnum++; } break; case 58: /* Line 1455 of yacc.c */ #line 376 "ncgentab.y" { atype_code = NC_INT; *int_valp++ = int_val; valnum++; } break; case 59: /* Line 1455 of yacc.c */ #line 382 "ncgentab.y" { atype_code = NC_FLOAT; *float_valp++ = float_val; valnum++; } break; case 60: /* Line 1455 of yacc.c */ #line 388 "ncgentab.y" { atype_code = NC_DOUBLE; *double_valp++ = double_val; valnum++; } break; case 65: /* Line 1455 of yacc.c */ #line 403 "ncgentab.y" { valtype = vars[varnum].type; /* variable type */ valnum = 0; /* values accumulated for variable */ vars[varnum].has_data = 1; /* compute dimensions product */ var_size = nctypesize(valtype); if (vars[varnum].ndims == 0) { /* scalar */ var_len = 1; } else if (vars[varnum].dims[0] == rec_dim) { var_len = 1; /* one record for unlimited vars */ } else { var_len = dims[vars[varnum].dims[0]].size; } for(dimnum = 1; dimnum < vars[varnum].ndims; dimnum++) var_len = var_len*dims[vars[varnum].dims[dimnum]].size; /* allocate memory for variable data */ if (var_len*var_size != (size_t)(var_len*var_size)) { derror("variable %s too large for memory", vars[varnum].name); exit(9); } rec_len = var_len; rec_start = malloc ((size_t)(rec_len*var_size)); if (rec_start == 0) { derror ("out of memory\n"); exit(3); } rec_cur = rec_start; switch (valtype) { case NC_CHAR: char_valp = (char *) rec_start; break; case NC_BYTE: byte_valp = (signed char *) rec_start; break; case NC_SHORT: short_valp = (short *) rec_start; break; case NC_INT: int_valp = (int *) rec_start; break; case NC_FLOAT: float_valp = (float *) rec_start; break; case NC_DOUBLE: double_valp = (double *) rec_start; break; } } break; case 66: /* Line 1455 of yacc.c */ #line 453 "ncgentab.y" { if (valnum < var_len) { /* leftovers */ nc_fill(valtype, var_len - valnum, rec_cur, vars[varnum].fill_value); } /* put out var_len values */ vars[varnum].nrecs = valnum / rec_len; if (derror_count == 0) put_variable(rec_start); free ((char *) rec_start); } break; case 69: /* Line 1455 of yacc.c */ #line 471 "ncgentab.y" { if(valnum >= var_len) { if (vars[varnum].dims[0] != rec_dim) { /* not recvar */ derror("too many values for this variable, %d >= %d", valnum, var_len); exit (4); } else { /* a record variable, so grow data container and increment var_len by multiple of record size */ ptrdiff_t rec_inc = (char *)rec_cur - (char *)rec_start; var_len = rec_len * (1 + valnum / rec_len); rec_start = erealloc(rec_start, var_len*var_size); rec_cur = (char *)rec_start + rec_inc; char_valp = (char *) rec_cur; byte_valp = (signed char *) rec_cur; short_valp = (short *) rec_cur; int_valp = (int *) rec_cur; float_valp = (float *) rec_cur; double_valp = (double *) rec_cur; } } not_a_string = 1; } break; case 70: /* Line 1455 of yacc.c */ #line 496 "ncgentab.y" { if (not_a_string) { switch (valtype) { case NC_CHAR: rec_cur = (void *) char_valp; break; case NC_BYTE: rec_cur = (void *) byte_valp; break; case NC_SHORT: rec_cur = (void *) short_valp; break; case NC_INT: rec_cur = (void *) int_valp; break; case NC_FLOAT: rec_cur = (void *) float_valp; break; case NC_DOUBLE: rec_cur = (void *) double_valp; break; } } } break; case 71: /* Line 1455 of yacc.c */ #line 523 "ncgentab.y" { atype_code = NC_CHAR; switch (valtype) { case NC_CHAR: *char_valp++ = char_val; break; case NC_BYTE: *byte_valp++ = char_val; break; case NC_SHORT: *short_valp++ = char_val; break; case NC_INT: *int_valp++ = char_val; break; case NC_FLOAT: *float_valp++ = char_val; break; case NC_DOUBLE: *double_valp++ = char_val; break; } valnum++; } break; case 72: /* Line 1455 of yacc.c */ #line 548 "ncgentab.y" { not_a_string = 0; atype_code = NC_CHAR; { size_t len = strlen(termstring); if(valnum + len > var_len) { if (vars[varnum].dims[0] != rec_dim) { derror("too many values for this variable, %d>%d", valnum+len, var_len); exit (5); } else {/* a record variable so grow it */ ptrdiff_t rec_inc = (char *)rec_cur - (char *)rec_start; var_len += rec_len * (len + valnum - var_len)/rec_len; rec_start = erealloc(rec_start, var_len*var_size); rec_cur = (char *)rec_start + rec_inc; char_valp = (char *) rec_cur; } } switch (valtype) { case NC_CHAR: { int ld; size_t i, sl; (void)strncpy(char_valp,termstring,len); ld = vars[varnum].ndims-1; if (ld > 0) {/* null-fill to size of last dim */ sl = dims[vars[varnum].dims[ld]].size; for (i =len;i $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } /* Line 1675 of yacc.c */ #line 764 "ncgentab.y" /* PROGRAMS */ #ifdef vms void #else int #endif yyerror( /* called for yacc syntax error */ char *s) { derror(s); #ifndef vms return -1; #endif } /* undefine yywrap macro, in case we are using bison instead of yacc */ #ifdef yywrap #undef yywrap #endif int yywrap(void) /* returns 1 on EOF if no more input */ { return 1; } /* Symbol table operations for ncgen tool */ YYSTYPE lookup( /* find sname in symbol table (linear search) */ char *sname) { YYSTYPE sp; for (sp = symlist; sp != (YYSTYPE) 0; sp = sp -> next) if (STREQ(sp -> name, sname)) { return sp; } return 0; /* 0 ==> not found */ } YYSTYPE install( /* install sname in symbol table */ char *sname) { YYSTYPE sp; sp = (YYSTYPE) emalloc (sizeof (struct Symbol)); sp -> name = (char *) emalloc (strlen (sname) + 1);/* +1 for '\0' */ (void) strcpy (sp -> name, sname); sp -> next = symlist; /* put at front of list */ sp -> is_dim = 0; sp -> is_var = 0; sp -> is_att = 0; symlist = sp; return sp; } void clearout(void) /* reset symbol table to empty */ { YYSTYPE sp, tp; for (sp = symlist; sp != (YYSTYPE) 0;) { tp = sp -> next; free (sp -> name); free ((char *) sp); sp = tp; } symlist = 0; } minc-2.2.00/progs/mincgen/ncgenyy.c0000644000265600003100000017577112030102322014034 00000000000000 #line 3 "progs/mincgen/ncgenyy.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 31 #define YY_END_OF_BUFFER 32 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[259] = { 0, 0, 0, 32, 30, 29, 18, 30, 30, 30, 30, 20, 30, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 29, 0, 2, 0, 0, 0, 20, 23, 23, 0, 0, 20, 20, 0, 21, 1, 24, 24, 19, 24, 23, 22, 0, 23, 19, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 0, 0, 0, 0, 20, 0, 0, 20, 1, 24, 20, 24, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 7, 17, 17, 17, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 7, 17, 17, 17, 17, 17, 17, 28, 26, 0, 0, 20, 0, 20, 21, 20, 5, 4, 17, 17, 17, 17, 17, 17, 17, 17, 16, 17, 7, 17, 3, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 26, 0, 27, 0, 16, 0, 12, 17, 17, 17, 17, 0, 17, 17, 17, 6, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 8, 17, 17, 14, 14, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 0, 17, 17, 13, 13, 17, 17, 17, 17, 17, 15, 17, 9, 17, 17, 17, 17, 11, 17, 10, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 5, 6, 1, 1, 1, 7, 1, 1, 1, 8, 1, 9, 10, 11, 12, 13, 13, 13, 13, 14, 13, 13, 15, 15, 16, 1, 1, 1, 1, 1, 6, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30, 26, 26, 31, 32, 33, 34, 35, 26, 36, 37, 26, 6, 38, 6, 1, 26, 1, 39, 40, 41, 42, 43, 44, 45, 46, 47, 26, 26, 48, 49, 50, 51, 26, 26, 52, 53, 54, 55, 56, 26, 36, 57, 26, 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[59] = { 0, 1, 1, 2, 1, 1, 3, 4, 1, 3, 3, 1, 5, 5, 5, 5, 1, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 5, 5, 5, 5, 5, 5, 3, 3, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7 } ; static yyconst flex_int16_t yy_base[270] = { 0, 0, 0, 477, 478, 57, 478, 55, 438, 52, 62, 94, 464, 133, 177, 0, 437, 449, 61, 88, 36, 452, 39, 441, 49, 449, 445, 439, 450, 409, 419, 43, 416, 421, 412, 410, 417, 416, 412, 407, 417, 67, 75, 478, 452, 447, 105, 0, 110, 0, 118, 403, 0, 478, 149, 478, 0, 108, 72, 101, 170, 478, 478, 0, 0, 478, 0, 419, 434, 417, 421, 414, 392, 187, 193, 219, 416, 394, 422, 410, 398, 412, 407, 410, 421, 407, 409, 404, 380, 394, 378, 382, 375, 378, 384, 373, 376, 371, 385, 372, 374, 369, 478, 413, 209, 412, 132, 256, 374, 198, 293, 0, 478, 218, 224, 396, 385, 398, 393, 395, 372, 0, 0, 394, 371, 395, 387, 123, 384, 387, 0, 378, 373, 378, 377, 358, 348, 360, 355, 357, 357, 381, 351, 348, 147, 344, 316, 314, 310, 478, 478, 230, 333, 478, 124, 166, 167, 478, 0, 0, 323, 309, 309, 286, 300, 278, 329, 307, 0, 279, 0, 308, 0, 294, 298, 308, 308, 273, 274, 267, 274, 298, 275, 262, 265, 273, 478, 304, 478, 303, 478, 259, 478, 271, 281, 258, 274, 295, 275, 248, 272, 0, 268, 274, 238, 247, 246, 266, 243, 239, 245, 237, 257, 0, 256, 230, 0, 277, 244, 220, 271, 232, 237, 212, 206, 203, 207, 200, 223, 202, 206, 192, 246, 226, 215, 184, 186, 185, 167, 190, 159, 0, 194, 120, 107, 84, 87, 58, 478, 78, 0, 88, 45, 76, 69, 478, 65, 478, 478, 341, 348, 353, 359, 366, 369, 74, 372, 374, 379, 385 } ; static yyconst flex_int16_t yy_def[270] = { 0, 258, 1, 258, 258, 258, 258, 259, 260, 258, 258, 258, 258, 258, 258, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 258, 259, 258, 259, 258, 262, 11, 14, 14, 258, 258, 11, 258, 258, 258, 263, 13, 264, 264, 264, 258, 258, 265, 14, 258, 261, 261, 261, 261, 261, 261, 261, 258, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 258, 258, 258, 266, 48, 258, 258, 258, 258, 263, 258, 60, 265, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 258, 258, 258, 267, 258, 258, 264, 264, 258, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 258, 258, 258, 258, 258, 258, 258, 261, 261, 261, 261, 268, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 258, 261, 261, 261, 261, 268, 268, 261, 261, 261, 261, 261, 261, 261, 261, 261, 258, 261, 261, 261, 261, 269, 261, 261, 261, 261, 261, 258, 261, 261, 269, 269, 261, 261, 261, 261, 261, 258, 261, 261, 261, 261, 261, 261, 258, 261, 258, 0, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258 } ; static yyconst flex_int16_t yy_nxt[537] = { 0, 4, 5, 6, 5, 7, 4, 8, 9, 10, 11, 12, 13, 14, 14, 14, 4, 15, 16, 17, 18, 19, 20, 15, 21, 22, 15, 23, 15, 24, 15, 25, 26, 15, 27, 28, 15, 15, 4, 15, 29, 30, 31, 19, 32, 15, 33, 34, 35, 15, 36, 15, 37, 38, 15, 39, 40, 15, 4, 41, 43, 41, 47, 76, 48, 49, 49, 49, 79, 41, 82, 41, 47, 50, 48, 49, 49, 49, 69, 114, 43, 257, 90, 50, 77, 257, 70, 51, 83, 80, 91, 71, 255, 44, 92, 50, 73, 74, 256, 112, 75, 75, 75, 75, 255, 50, 52, 52, 52, 52, 254, 253, 72, 44, 53, 54, 55, 104, 104, 104, 112, 53, 106, 106, 106, 106, 73, 73, 112, 250, 107, 107, 107, 107, 252, 112, 53, 54, 55, 251, 250, 105, 53, 47, 258, 57, 57, 57, 57, 112, 58, 59, 58, 58, 60, 58, 112, 109, 109, 258, 61, 110, 110, 110, 110, 62, 181, 168, 190, 63, 169, 191, 58, 59, 58, 58, 60, 58, 73, 73, 258, 61, 113, 113, 113, 113, 62, 47, 182, 64, 64, 64, 64, 112, 112, 65, 242, 112, 50, 107, 107, 107, 107, 130, 61, 75, 75, 75, 75, 62, 110, 110, 110, 110, 112, 112, 150, 65, 112, 249, 50, 151, 151, 151, 248, 61, 258, 258, 247, 246, 62, 75, 75, 75, 75, 245, 244, 186, 155, 121, 156, 122, 187, 187, 187, 157, 121, 243, 242, 130, 168, 112, 240, 239, 238, 237, 62, 236, 170, 235, 155, 121, 156, 122, 234, 233, 157, 121, 107, 107, 107, 107, 112, 232, 231, 170, 153, 62, 55, 217, 230, 229, 228, 153, 227, 226, 225, 220, 220, 224, 213, 223, 222, 221, 220, 219, 218, 217, 153, 215, 55, 214, 213, 212, 153, 110, 110, 110, 110, 211, 188, 186, 210, 53, 209, 55, 201, 208, 207, 206, 53, 172, 205, 204, 192, 203, 202, 201, 200, 199, 198, 197, 196, 172, 195, 53, 194, 55, 193, 192, 188, 53, 42, 42, 42, 42, 42, 42, 42, 45, 45, 45, 45, 45, 45, 45, 66, 185, 66, 66, 103, 184, 103, 103, 103, 103, 103, 111, 183, 111, 111, 111, 111, 111, 58, 58, 152, 152, 189, 189, 216, 216, 216, 216, 216, 216, 241, 241, 241, 241, 241, 241, 172, 170, 180, 166, 179, 178, 177, 176, 159, 158, 175, 174, 173, 172, 171, 170, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 154, 149, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 120, 119, 118, 117, 116, 115, 108, 102, 258, 101, 100, 99, 98, 97, 96, 95, 94, 93, 89, 88, 87, 86, 85, 84, 81, 78, 68, 67, 56, 46, 258, 3, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258 } ; static yyconst flex_int16_t yy_chk[537] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 7, 5, 9, 20, 9, 9, 9, 9, 22, 41, 24, 41, 10, 9, 10, 10, 10, 10, 18, 265, 42, 256, 31, 10, 20, 254, 18, 10, 24, 22, 31, 18, 253, 7, 31, 9, 19, 19, 252, 58, 19, 19, 19, 19, 251, 10, 11, 11, 11, 11, 249, 247, 18, 42, 11, 11, 11, 46, 46, 46, 58, 11, 48, 48, 48, 48, 50, 50, 59, 246, 50, 50, 50, 50, 245, 57, 11, 11, 11, 244, 243, 46, 11, 13, 57, 13, 13, 13, 13, 59, 13, 13, 13, 13, 13, 13, 57, 54, 54, 106, 13, 54, 54, 54, 54, 13, 144, 127, 154, 13, 127, 154, 13, 13, 13, 13, 13, 13, 60, 60, 106, 13, 60, 60, 60, 60, 13, 14, 144, 14, 14, 14, 14, 155, 156, 14, 242, 60, 14, 73, 73, 73, 73, 240, 14, 74, 74, 74, 74, 14, 109, 109, 109, 109, 155, 156, 104, 14, 60, 239, 14, 104, 104, 104, 238, 14, 113, 113, 237, 236, 14, 75, 75, 75, 75, 235, 234, 151, 113, 75, 113, 75, 151, 151, 151, 113, 75, 233, 232, 231, 230, 114, 229, 228, 227, 226, 114, 225, 224, 223, 113, 75, 113, 75, 222, 221, 113, 75, 107, 107, 107, 107, 114, 220, 219, 218, 107, 114, 107, 217, 215, 214, 212, 107, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 200, 199, 198, 197, 107, 196, 107, 195, 194, 193, 107, 110, 110, 110, 110, 191, 189, 187, 185, 110, 184, 110, 183, 182, 181, 180, 110, 179, 178, 177, 176, 175, 174, 173, 171, 169, 167, 166, 165, 164, 163, 110, 162, 110, 161, 160, 152, 110, 259, 259, 259, 259, 259, 259, 259, 260, 260, 260, 260, 260, 260, 260, 261, 148, 261, 261, 262, 147, 262, 262, 262, 262, 262, 263, 146, 263, 263, 263, 263, 263, 264, 264, 266, 266, 267, 267, 268, 268, 268, 268, 268, 268, 269, 269, 269, 269, 269, 269, 145, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 129, 128, 126, 125, 124, 123, 120, 119, 118, 117, 116, 115, 108, 105, 103, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 72, 71, 70, 69, 68, 67, 51, 45, 44, 40, 39, 38, 37, 36, 35, 34, 33, 32, 30, 29, 28, 27, 26, 25, 23, 21, 17, 16, 12, 8, 3, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "ncgenyy.l" #line 2 "ncgenyy.l" /********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Id: ncgenyy.l,v 1.3 2005-06-22 21:02:11 bert Exp $ *********************************************************************/ /* lex specification for tokens for ncgen */ /* Fill value used by ncdump from version 2.4 and later. Should match definition of FILL_STRING in ../ncdump/vardata.h */ #define FILL_STRING "_" #define XDR_INT_MIN (-2147483647-1) #define XDR_INT_MAX 2147483647 char errstr[100]; /* for short error messages */ #include #include #include #include "ncgen.h" #include "genlib.h" #include "ncgentab.h" extern int int_val; extern float float_val; #if !defined (YYSTYPE) && !defined(YYSTYPE_IS_DECLARED) extern void * yylval; #define YYLVAL_NULL ((void *) NULL) #else #define YYLVAL_NULL ((YYSTYPE) NULL) #endif /* YYSTYPE defined */ extern int lineno; extern signed char byte_val; extern short short_val; extern double double_val; extern char *netcdfname; extern char termstring[]; #define YY_BREAK /* defining as nothing eliminates unreachable statement warnings from flex output, but make sure every action ends with "return" or "break"! */ #line 704 "progs/mincgen/ncgenyy.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (void ); int yyget_debug (void ); void yyset_debug (int debug_flag ); YY_EXTRA_TYPE yyget_extra (void ); void yyset_extra (YY_EXTRA_TYPE user_defined ); FILE *yyget_in (void ); void yyset_in (FILE * in_str ); FILE *yyget_out (void ); void yyset_out (FILE * out_str ); int yyget_leng (void ); char *yyget_text (void ); int yyget_lineno (void ); void yyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif static void yyunput (int c,char *buf_ptr ); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 52 "ncgenyy.l" #line 893 "progs/mincgen/ncgenyy.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 259 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 478 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 53 "ncgenyy.l" { /* comment */ break; } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 57 "ncgenyy.l" { if(yyleng > MAXTRST) { yyerror("string too long, truncated\n"); yytext[MAXTRST-1] = '\0'; } expand_escapes(termstring,(char *)yytext,yyleng); return (TERMSTRING); } YY_BREAK case 3: YY_RULE_SETUP #line 66 "ncgenyy.l" {return (FLOAT_K);} YY_BREAK case 4: YY_RULE_SETUP #line 67 "ncgenyy.l" {return (CHAR_K);} YY_BREAK case 5: YY_RULE_SETUP #line 68 "ncgenyy.l" {return (BYTE_K);} YY_BREAK case 6: YY_RULE_SETUP #line 69 "ncgenyy.l" {return (SHORT_K);} YY_BREAK case 7: YY_RULE_SETUP #line 70 "ncgenyy.l" {return (INT_K);} YY_BREAK case 8: YY_RULE_SETUP #line 71 "ncgenyy.l" {return (DOUBLE_K);} YY_BREAK case 9: YY_RULE_SETUP #line 72 "ncgenyy.l" {int_val = -1; return (NC_UNLIMITED_K);} YY_BREAK case 10: YY_RULE_SETUP #line 75 "ncgenyy.l" {return (DIMENSIONS);} YY_BREAK case 11: YY_RULE_SETUP #line 76 "ncgenyy.l" {return (VARIABLES);} YY_BREAK case 12: YY_RULE_SETUP #line 77 "ncgenyy.l" {return (DATA);} YY_BREAK case 13: /* rule 13 can match eol */ YY_RULE_SETUP #line 78 "ncgenyy.l" { char *s = (char*)yytext+strlen("netcdf"); char *t = (char*)yytext+yyleng-1; while (isspace(*s)) s++; while (isspace(*t)) t--; t++; if (t-s+1 < 1) { yyerror("netCDF name required"); return (DATA); /* generate syntax error */ } netcdfname = (char *) emalloc(t-s+1); (void) strncpy(netcdfname, s, t-s); netcdfname[t-s] = '\0'; return (NETCDF); } YY_BREAK case 14: /* rule 14 can match eol */ YY_RULE_SETUP #line 95 "ncgenyy.l" { char *s = (char*)yytext+strlen("hdf5"); char *t = (char*)yytext+yyleng-1; while (isspace(*s)) s++; while (isspace(*t)) t--; t++; if (t-s+1 < 1) { yyerror("HDF5 name required"); return (DATA); /* generate syntax error */ } netcdfname = (char *) emalloc(t-s+1); (void) strncpy(netcdfname, s, t-s); netcdfname[t-s] = '\0'; return (HDF5); } YY_BREAK case 15: YY_RULE_SETUP #line 112 "ncgenyy.l" { /* missing value (pre-2.4 backward compatibility) */ if (yytext[0] == '-') { double_val = -NC_FILL_DOUBLE; } else { double_val = NC_FILL_DOUBLE; } return (DOUBLE_CONST); } YY_BREAK case 16: YY_RULE_SETUP #line 120 "ncgenyy.l" { /* missing value (pre-2.4 backward compatibility) */ if (yytext[0] == '-') { float_val = -NC_FILL_FLOAT; } else { float_val = NC_FILL_FLOAT; } return (FLOAT_CONST); } YY_BREAK case 17: YY_RULE_SETUP #line 128 "ncgenyy.l" { if (STREQ((char *)yytext, FILL_STRING)) return (FILLVALUE); if ((yylval = lookup((char *)yytext)) == YYLVAL_NULL) { yylval = install((char *)yytext); } return (IDENT); } YY_BREAK case 18: /* rule 18 can match eol */ YY_RULE_SETUP #line 137 "ncgenyy.l" { lineno++ ; break; } YY_BREAK case 19: YY_RULE_SETUP #line 142 "ncgenyy.l" { int ii; if (sscanf((char*)yytext, "%d", &ii) != 1) { sprintf(errstr,"bad byte constant: %s",(char*)yytext); yyerror(errstr); } byte_val = ii; if (ii != (int)byte_val) { sprintf(errstr,"byte constant out of range (-128,127): %s",(char*)yytext); yyerror(errstr); } return (BYTE_CONST); } YY_BREAK case 20: YY_RULE_SETUP #line 156 "ncgenyy.l" { if (sscanf((char*)yytext, "%le", &double_val) != 1) { sprintf(errstr,"bad long or double constant: %s",(char*)yytext); yyerror(errstr); } return (DOUBLE_CONST); } YY_BREAK case 21: YY_RULE_SETUP #line 163 "ncgenyy.l" { if (sscanf((char*)yytext, "%e", &float_val) != 1) { sprintf(errstr,"bad float constant: %s",(char*)yytext); yyerror(errstr); } return (FLOAT_CONST); } YY_BREAK case 22: YY_RULE_SETUP #line 170 "ncgenyy.l" { if (sscanf((char*)yytext, "%hd", &short_val) != 1) { sprintf(errstr,"bad short constant: %s",(char*)yytext); yyerror(errstr); } return (SHORT_CONST); } YY_BREAK case 23: YY_RULE_SETUP #line 177 "ncgenyy.l" { char *ptr; errno = 0; double_val = strtod((char*)yytext, &ptr); if (errno != 0 && double_val == 0.0) { sprintf(errstr,"bad numerical constant: %s",(char*)yytext); yyerror(errstr); } if (double_val < XDR_INT_MIN ||double_val > XDR_INT_MAX) { return DOUBLE_CONST; } else { int_val = (int) double_val; return INT_CONST; } } YY_BREAK case 24: YY_RULE_SETUP #line 192 "ncgenyy.l" { char *ptr; long long_val; errno = 0; long_val = strtol((char*)yytext, &ptr, 0); if (errno != 0) { sprintf(errstr,"bad long constant: %s",(char*)yytext); yyerror(errstr); } if (long_val < XDR_INT_MIN || long_val > XDR_INT_MAX) { double_val = (double) long_val; return DOUBLE_CONST; } else { int_val = (int) long_val; return INT_CONST; } } YY_BREAK case 25: /* rule 25 can match eol */ YY_RULE_SETUP #line 209 "ncgenyy.l" { (void) sscanf((char*)&yytext[1],"%c",&byte_val); return (BYTE_CONST); } YY_BREAK case 26: YY_RULE_SETUP #line 213 "ncgenyy.l" { byte_val = (char) strtol((char*)&yytext[2], (char **) 0, 8); return (BYTE_CONST); } YY_BREAK case 27: YY_RULE_SETUP #line 217 "ncgenyy.l" { byte_val = (char) strtol((char*)&yytext[3], (char **) 0, 16); return (BYTE_CONST); } YY_BREAK case 28: YY_RULE_SETUP #line 221 "ncgenyy.l" { switch ((char)yytext[2]) { case 'a': byte_val = '\007'; break; /* not everyone under- * stands '\a' yet */ case 'b': byte_val = '\b'; break; case 'f': byte_val = '\f'; break; case 'n': byte_val = '\n'; break; case 'r': byte_val = '\r'; break; case 't': byte_val = '\t'; break; case 'v': byte_val = '\v'; break; case '\\': byte_val = '\\'; break; case '?': byte_val = '\177'; break; case '\'': byte_val = '\''; break; default: byte_val = (char)yytext[2]; } return (BYTE_CONST); } YY_BREAK case 29: YY_RULE_SETUP #line 239 "ncgenyy.l" { /* whitespace */ break; } YY_BREAK case 30: YY_RULE_SETUP #line 242 "ncgenyy.l" return (yytext[0]) ; YY_BREAK case 31: YY_RULE_SETUP #line 243 "ncgenyy.l" ECHO; YY_BREAK #line 1289 "progs/mincgen/ncgenyy.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 259 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 259 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 258); return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ int yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param line_number * */ void yyset_lineno (int line_number ) { yylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * in_str ) { yyin = in_str ; } void yyset_out (FILE * out_str ) { yyout = out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int bdebug ) { yy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 243 "ncgenyy.l" minc-2.2.00/progs/mincgen/escapes.c0000644000265600003100000000410612027132663014003 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/escapes.c,v 1.2 2008-01-12 19:08:15 stever Exp $ *********************************************************************/ #include #include #include "generic.h" #include "ncgen.h" #include "genlib.h" /* * "Expands" valid escape sequences in yystring (read by lex) into the * apropriate characters in termstring. For example, the two character * sequence "\t" in yystring would be converted into a single tab character * in termstring. On return, termstring is properly terminated. */ void expand_escapes( char *termstring, /* returned, with escapes expanded */ char *yytext, int yyleng) { char *s, *t, *endp; yytext[yyleng-1]='\0'; /* don't copy quotes */ /* expand "\" escapes, e.g. "\t" to tab character */ s = termstring; t = yytext+1; while(*t) { if (*t == '\\') { t++; switch (*t) { case 'a': *s++ = '\007'; t++; /* will use '\a' when STDC */ break; case 'b': *s++ = '\b'; t++; break; case 'f': *s++ = '\f'; t++; break; case 'n': *s++ = '\n'; t++; break; case 'r': *s++ = '\r'; t++; break; case 't': *s++ = '\t'; t++; break; case 'v': *s++ = '\v'; t++; break; case '\\': *s++ = '\\'; t++; break; case '?': *s++ = '\177'; t++; break; case '\'': *s++ = '\''; t++; break; case '\"': *s++ = '\"'; t++; break; case 'x': t++; /* now t points to one or more hex digits */ *s++ = (char) strtol(t, &endp, 16); t = endp; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* t now points to octal digits */ *s++ = (char) strtol(t, &endp, 8); t = endp; break; default: *s++ = *t++; break; } } else { *s++ = *t++; } } *s = '\0'; return; } minc-2.2.00/progs/mincgen/genlib.c0000644000265600003100000013006012027132663013617 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/genlib.c,v 1.5 2008-01-12 19:08:15 stever Exp $ *********************************************************************/ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include /* for isprint() */ #ifndef NO_STDARG #include #else /* try varargs instead */ #include #endif /* !NO_STDARG */ #include #include "generic.h" #include "ncgen.h" #include "genlib.h" extern char *netcdf_name; /* output netCDF filename, if on command line. */ extern int netcdf_flag; extern int c_flag; extern int fortran_flag; int lineno = 1; int derror_count = 0; /* create netCDF from in-memory structure */ static void gen_netcdf( char *filename) /* name for output netcdf file */ { int idim, ivar, iatt; int dimid; int varid; int stat; #if MINC2 ncid = micreate(filename, (is_hdf5) ? (MI2_CREATE_V2 | NC_CLOBBER) : NC_CLOBBER); #else ncid = micreate(filename, NC_CLOBBER); #endif check_err(ncid); /* define dimensions from info in dims array */ for (idim = 0; idim < ndims; idim++) { dimid = ncdimdef(ncid, dims[idim].name, dims[idim].size); check_err(dimid); } /* define variables from info in vars array */ for (ivar = 0; ivar < nvars; ivar++) { varid = ncvardef(ncid, vars[ivar].name, vars[ivar].type, vars[ivar].ndims, vars[ivar].dims); check_err(varid); } /* define attributes from info in atts array */ for (iatt = 0; iatt < natts; iatt++) { varid = (atts[iatt].var == -1) ? NC_GLOBAL : atts[iatt].var; stat = ncattput(ncid, varid, atts[iatt].name, atts[iatt].type, atts[iatt].len, atts[iatt].val); check_err(stat); } stat = ncendef(ncid); check_err(stat); } /* * Given a netcdf type, a pointer to a vector of values of that type, * and the index of the vector element desired, returns a pointer to a * malloced string representing the value in C. */ static char * cstring( nc_type type, /* netCDF type code */ void *valp, /* pointer to vector of values */ int num) /* element of vector desired */ { static char *cp, *sp, ch; signed char *bytep; short *shortp; int *intp; float *floatp; double *doublep; switch (type) { case NC_CHAR: sp = cp = (char *) emalloc (7); *cp++ = '\''; ch = *((char *)valp + num); switch (ch) { case '\b': *cp++ = '\\'; *cp++ = 'b'; break; case '\f': *cp++ = '\\'; *cp++ = 'f'; break; case '\n': *cp++ = '\\'; *cp++ = 'n'; break; case '\r': *cp++ = '\\'; *cp++ = 'r'; break; case '\t': *cp++ = '\\'; *cp++ = 't'; break; case '\v': *cp++ = '\\'; *cp++ = 'v'; break; case '\\': *cp++ = '\\'; *cp++ = '\\'; break; case '\'': *cp++ = '\\'; *cp++ = '\''; break; default: if (!isprint(ch)) { static char octs[] = "01234567"; int rem = ((unsigned char)ch)%64; *cp++ = '\\'; *cp++ = octs[((unsigned char)ch)/64]; /* to get, e.g. '\177' */ *cp++ = octs[rem/8]; *cp++ = octs[rem%8]; } else { *cp++ = ch; } break; } *cp++ = '\''; *cp = '\0'; return sp; case NC_BYTE: cp = (char *) emalloc (7); bytep = (signed char *)valp; /* Need to convert '\377' to -1, for example, on all platforms */ (void) sprintf(cp,"%d", (signed char) *(bytep+num)); return cp; case NC_SHORT: cp = (char *) emalloc (10); shortp = (short *)valp; (void) sprintf(cp,"%d",* (shortp + num)); return cp; case NC_INT: cp = (char *) emalloc (20); intp = (int *)valp; (void) sprintf(cp,"%d",* (intp + num)); return cp; case NC_FLOAT: cp = (char *) emalloc (20); floatp = (float *)valp; (void) sprintf(cp,"%.8g",* (floatp + num)); return cp; case NC_DOUBLE: cp = (char *) emalloc (20); doublep = (double *)valp; (void) sprintf(cp,"%.16g",* (doublep + num)); return cp; default: derror("cstring: bad type code"); return 0; } } /* * Generate C code for creating netCDF from in-memory structure. */ static void gen_c( char *filename) { int idim, ivar, iatt, jatt, maxdims; int vector_atts; char *val_string; char stmnt[C_MAX_STMNT]; /* wrap in main program */ cline("#include "); cline("#include "); cline("#include "); cline(""); cline("void"); cline("check_err(const int stat, const int line, const char *file) {"); cline(" if (stat != NC_NOERR) {"); cline(" (void) fprintf(stderr, \"line %d of %s: %s\\n\", line, file, nc_strerror(stat));"); cline(" exit(1);"); cline(" }"); cline("}"); cline(""); cline("int"); sprintf(stmnt, "main() {\t\t\t/* create %s */", filename); cline(stmnt); /* create necessary declarations */ cline(""); cline(" int ncid;\t\t\t/* netCDF id */"); if (ndims > 0) { cline(""); cline(" /* dimension ids */"); for (idim = 0; idim < ndims; idim++) { sprintf(stmnt, " int %s_dim;", dims[idim].lname); cline(stmnt); } cline(""); cline(" /* dimension lengths */"); for (idim = 0; idim < ndims; idim++) { if (dims[idim].size == NC_UNLIMITED) { sprintf(stmnt, " size_t %s_len = NC_UNLIMITED;", dims[idim].lname); } else { sprintf(stmnt, " size_t %s_len = %lu;", dims[idim].lname, (unsigned long) dims[idim].size); } cline(stmnt); } } maxdims = 0; /* most dimensions of any variable */ for (ivar = 0; ivar < nvars; ivar++) if (vars[ivar].ndims > maxdims) maxdims = vars[ivar].ndims; if (nvars > 0) { cline(""); cline(" /* variable ids */"); for (ivar = 0; ivar < nvars; ivar++) { sprintf(stmnt, " int %s_id;", vars[ivar].lname); cline(stmnt); } cline(""); cline(" /* rank (number of dimensions) for each variable */"); for (ivar = 0; ivar < nvars; ivar++) { sprintf(stmnt, "# define RANK_%s %d", vars[ivar].lname, vars[ivar].ndims); cline(stmnt); } if (maxdims > 0) { /* we have dimensioned variables */ cline(""); cline(" /* variable shapes */"); for (ivar = 0; ivar < nvars; ivar++) { if (vars[ivar].ndims > 0) { sprintf(stmnt, " int %s_dims[RANK_%s];", vars[ivar].lname, vars[ivar].lname); cline(stmnt); } } } } /* determine if we need any attribute vectors */ vector_atts = 0; for (iatt = 0; iatt < natts; iatt++) { if (atts[iatt].type != NC_CHAR) { vector_atts = 1; break; } } if (vector_atts) { cline(""); cline(" /* attribute vectors */"); for (iatt = 0; iatt < natts; iatt++) { if (atts[iatt].type != NC_CHAR) { sprintf(stmnt, " %s %s_%s[%lu];", ncatype(atts[iatt].type), atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname, atts[iatt].lname, (unsigned long) atts[iatt].len); cline(stmnt); } } } /* create netCDF file, uses NC_CLOBBER mode */ cline(""); cline(" /* enter define mode */"); sprintf(stmnt, " int stat = nc_create(\"%s\", NC_CLOBBER, &ncid);", filename); cline(stmnt); cline(" check_err(stat,__LINE__,__FILE__);"); /* define dimensions from info in dims array */ if (ndims > 0) { cline(""); cline(" /* define dimensions */"); } for (idim = 0; idim < ndims; idim++) { sprintf(stmnt, " stat = nc_def_dim(ncid, \"%s\", %s_len, &%s_dim);", dims[idim].name, dims[idim].lname, dims[idim].lname); cline(stmnt); cline(" check_err(stat,__LINE__,__FILE__);"); } /* define variables from info in vars array */ if (nvars > 0) { cline(""); cline(" /* define variables */"); for (ivar = 0; ivar < nvars; ivar++) { cline(""); for (idim = 0; idim < vars[ivar].ndims; idim++) { sprintf(stmnt, " %s_dims[%d] = %s_dim;", vars[ivar].lname, idim, dims[vars[ivar].dims[idim]].lname); cline(stmnt); } if (vars[ivar].ndims > 0) { /* a dimensioned variable */ sprintf(stmnt, " stat = nc_def_var(ncid, \"%s\", %s, RANK_%s, %s_dims, &%s_id);", vars[ivar].name, nctype(vars[ivar].type), vars[ivar].lname, vars[ivar].lname, vars[ivar].lname); } else { /* a scalar */ sprintf(stmnt, " stat = nc_def_var(ncid, \"%s\", %s, RANK_%s, 0, &%s_id);", vars[ivar].name, nctype(vars[ivar].type), vars[ivar].lname, vars[ivar].lname); } cline(stmnt); cline(" check_err(stat,__LINE__,__FILE__);"); } } /* define attributes from info in atts array */ if (natts > 0) { cline(""); cline(" /* assign attributes */"); for (iatt = 0; iatt < natts; iatt++) { if (atts[iatt].type == NC_CHAR) { /* string */ val_string = cstrstr((char *) atts[iatt].val, atts[iatt].len); sprintf(stmnt, " stat = nc_put_att_text(ncid, %s%s, \"%s\", %lu, %s);", atts[iatt].var == -1 ? "NC_GLOBAL" : vars[atts[iatt].var].lname, atts[iatt].var == -1 ? "" : "_id", atts[iatt].name, (unsigned long) atts[iatt].len, val_string); cline(stmnt); free (val_string); } else { /* vector attribute */ for (jatt = 0; jatt < atts[iatt].len ; jatt++) { val_string = cstring(atts[iatt].type,atts[iatt].val,jatt); sprintf(stmnt, " %s_%s[%d] = %s;", atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname, atts[iatt].lname, jatt, val_string); cline(stmnt); free (val_string); } sprintf(stmnt, " stat = nc_put_att_%s(ncid, %s%s, \"%s\", %s, %lu, %s_%s);", ncatype(atts[iatt].type), atts[iatt].var == -1 ? "NC_GLOBAL" : vars[atts[iatt].var].lname, atts[iatt].var == -1 ? "" : "_id", atts[iatt].name, nctype(atts[iatt].type), (unsigned long) atts[iatt].len, atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname, atts[iatt].lname); cline(stmnt); } cline(" check_err(stat,__LINE__,__FILE__);"); } } cline(""); cline(" /* leave define mode */"); cline(" stat = nc_enddef (ncid);"); cline(" check_err(stat,__LINE__,__FILE__);"); } /* return Fortran type name for netCDF type, given type code */ static char * ncftype( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "integer"; case NC_CHAR: return "character"; case NC_SHORT: return "integer"; case NC_INT: #ifdef MSDOS return "integer*4"; #else return "integer"; #endif case NC_FLOAT: return "real"; #ifdef _CRAY case NC_DOUBLE: return "real"; /* we don't support CRAY 128-bit doubles */ #else case NC_DOUBLE: return "double precision"; #endif default: derror("ncftype: bad type code"); return 0; } } /* return Fortran type suffix for netCDF type, given type code */ char * nfstype( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "int1"; case NC_CHAR: return "text"; case NC_SHORT: return "int2"; case NC_INT: return "int"; case NC_FLOAT: return "real"; case NC_DOUBLE: return "double"; default: derror("nfstype: bad type code"); return 0; } } /* Return Fortran function suffix for netCDF type, given type code. * This should correspond to the Fortran type name in ncftype(). */ char * nfftype( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "int"; case NC_CHAR: return "text"; case NC_SHORT: return "int"; case NC_INT: return "int"; case NC_FLOAT: return "real"; #ifdef _CRAY case NC_DOUBLE: return "real"; /* we don't support CRAY 128-bit doubles */ #else case NC_DOUBLE: return "double"; #endif default: derror("nfstype: bad type code"); return 0; } } /* return FORTRAN name for netCDF type, given type code */ static char * ftypename( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "NF_INT1"; case NC_CHAR: return "NF_CHAR"; case NC_SHORT: return "NF_INT2"; case NC_INT: return "NF_INT"; case NC_FLOAT: return "NF_REAL"; case NC_DOUBLE: return "NF_DOUBLE"; default: derror("ftypename: bad type code"); return 0; } } /* * Generate FORTRAN code for creating netCDF from in-memory structure. */ static void gen_fortran( char *filename) { int idim, ivar, iatt, jatt, itype, maxdims; int vector_atts; char *val_string; char stmnt[FORT_MAX_STMNT]; char s2[NC_MAX_NAME + 10]; char *sp; /* Need how many netCDF types there are, because we create an array * for each type of attribute. */ int ntypes = 6; /* number of netCDF types, NC_BYTE, ... */ nc_type types[6]; /* at least ntypes */ size_t max_atts[NC_DOUBLE + 1]; types[0] = NC_BYTE; types[1] = NC_CHAR; types[2] = NC_SHORT; types[3] = NC_INT; types[4] = NC_FLOAT; types[5] = NC_DOUBLE; fline("program fgennc"); fline("include 'netcdf.inc'"); /* create necessary declarations */ fline("* error status return"); fline("integer iret"); fline("* netCDF id"); fline("integer ncid"); if (ndims > 0) { fline("* dimension ids"); for (idim = 0; idim < ndims; idim++) { sprintf(stmnt, "integer %s_dim", dims[idim].lname); fline(stmnt); } fline("* dimension lengths"); for (idim = 0; idim < ndims; idim++) { sprintf(stmnt, "integer %s_len", dims[idim].lname); fline(stmnt); } for (idim = 0; idim < ndims; idim++) { if (dims[idim].size == NC_UNLIMITED) { sprintf(stmnt, "parameter (%s_len = NF_UNLIMITED)", dims[idim].lname); } else { sprintf(stmnt, "parameter (%s_len = %lu)", dims[idim].lname, (unsigned long) dims[idim].size); } fline(stmnt); } } maxdims = 0; /* most dimensions of any variable */ for (ivar = 0; ivar < nvars; ivar++) if (vars[ivar].ndims > maxdims) maxdims = vars[ivar].ndims; if (nvars > 0) { fline("* variable ids"); for (ivar = 0; ivar < nvars; ivar++) { sprintf(stmnt, "integer %s_id", vars[ivar].lname); fline(stmnt); } fline("* rank (number of dimensions) for each variable"); for (ivar = 0; ivar < nvars; ivar++) { sprintf(stmnt, "integer %s_rank", vars[ivar].lname); fline(stmnt); } for (ivar = 0; ivar < nvars; ivar++) { sprintf(stmnt, "parameter (%s_rank = %d)", vars[ivar].lname, vars[ivar].ndims); fline(stmnt); } fline("* variable shapes"); for (ivar = 0; ivar < nvars; ivar++) { if (vars[ivar].ndims > 0) { sprintf(stmnt, "integer %s_dims(%s_rank)", vars[ivar].lname, vars[ivar].lname); fline(stmnt); } } } /* declarations for variables to be initialized */ if (nvars > 0) { /* we have variables */ fline("* data variables"); for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; /* Generate declarations here for non-record data variables only. Record variables are declared in separate subroutine later, when we know how big they are. */ if (v->ndims > 0 && v->dims[0] == rec_dim) { continue; } /* Make declarations for non-text variables only; for text variables, just include string in nf_put_var call */ if (v->type == NC_CHAR) { continue; } if (v->ndims == 0) { /* scalar */ sprintf(stmnt, "%s %s", ncftype(v->type), v->lname); } else { sprintf(stmnt, "%s %s(", ncftype(v->type), v->lname); /* reverse dimensions for FORTRAN */ for (idim = v->ndims-1; idim >= 0; idim--) { sprintf(s2, "%s_len, ", dims[v->dims[idim]].lname); strcat(stmnt, s2); } sp = strrchr(stmnt, ','); if(sp != NULL) { *sp = '\0'; } strcat(stmnt, ")"); } fline(stmnt); } } /* determine what attribute vectors needed */ for (itype = 0; itype < ntypes; itype++) max_atts[(int)types[itype]] = 0; vector_atts = 0; for (iatt = 0; iatt < natts; iatt++) { if (atts[iatt].len > max_atts[(int) atts[iatt].type]) { max_atts[(int)atts[iatt].type] = atts[iatt].len; vector_atts = 1; } } if (vector_atts) { fline("* attribute vectors"); for (itype = 0; itype < ntypes; itype++) { if (types[itype] != NC_CHAR && max_atts[(int)types[itype]] > 0) { sprintf(stmnt, "%s %sval(%lu)", ncftype(types[itype]), nfstype(types[itype]), (unsigned long) max_atts[(int)types[itype]]); fline(stmnt); } } } /* create netCDF file, uses NC_CLOBBER mode */ fline("* enter define mode"); sprintf(stmnt, "iret = nf_create(\'%s\', NF_CLOBBER, ncid)", filename); fline(stmnt); fline("call check_err(iret)"); /* define dimensions from info in dims array */ if (ndims > 0) fline("* define dimensions"); for (idim = 0; idim < ndims; idim++) { if (dims[idim].size == NC_UNLIMITED) sprintf(stmnt, "iret = nf_def_dim(ncid, \'%s\', NF_UNLIMITED, %s_dim)", dims[idim].name, dims[idim].lname); else sprintf(stmnt, "iret = nf_def_dim(ncid, \'%s\', %lu, %s_dim)", dims[idim].name, (unsigned long) dims[idim].size, dims[idim].lname); fline(stmnt); fline("call check_err(iret)"); } /* define variables from info in vars array */ if (nvars > 0) { fline("* define variables"); for (ivar = 0; ivar < nvars; ivar++) { for (idim = 0; idim < vars[ivar].ndims; idim++) { sprintf(stmnt, "%s_dims(%d) = %s_dim", vars[ivar].lname, vars[ivar].ndims - idim, /* reverse dimensions */ dims[vars[ivar].dims[idim]].lname); fline(stmnt); } if (vars[ivar].ndims > 0) { /* a dimensioned variable */ sprintf(stmnt, "iret = nf_def_var(ncid, \'%s\', %s, %s_rank, %s_dims, %s_id)", vars[ivar].name, ftypename(vars[ivar].type), vars[ivar].lname, vars[ivar].lname, vars[ivar].lname); } else { /* a scalar */ sprintf(stmnt, "iret = nf_def_var(ncid, \'%s\', %s, %s_rank, 0, %s_id)", vars[ivar].name, ftypename(vars[ivar].type), vars[ivar].lname, vars[ivar].lname); } fline(stmnt); fline("call check_err(iret)"); } } /* define attributes from info in atts array */ if (natts > 0) { fline("* assign attributes"); for (iatt = 0; iatt < natts; iatt++) { if (atts[iatt].type == NC_CHAR) { /* string */ val_string = fstrstr((char *) atts[iatt].val, atts[iatt].len); sprintf(stmnt, "iret = nf_put_att_text(ncid, %s%s, \'%s\', %lu, %s)", atts[iatt].var == -1 ? "NF_GLOBAL" : vars[atts[iatt].var].lname, atts[iatt].var == -1 ? "" : "_id", atts[iatt].name, (unsigned long) atts[iatt].len, val_string); fline(stmnt); fline("call check_err(iret)"); free(val_string); } else { for (jatt = 0; jatt < atts[iatt].len ; jatt++) { val_string = fstring(atts[iatt].type,atts[iatt].val,jatt); sprintf(stmnt, "%sval(%d) = %s", nfstype(atts[iatt].type), jatt+1, val_string); fline(stmnt); free (val_string); } sprintf(stmnt, "iret = nf_put_att_%s(ncid, %s%s, \'%s\', %s, %lu, %sval)", nfftype(atts[iatt].type), atts[iatt].var == -1 ? "NCGLOBAL" : vars[atts[iatt].var].lname, atts[iatt].var == -1 ? "" : "_id", atts[iatt].name, ftypename(atts[iatt].type), (unsigned long) atts[iatt].len, nfstype(atts[iatt].type)); fline(stmnt); fline("call check_err(iret)"); } } } fline("* leave define mode"); fline("iret = nf_enddef(ncid)"); fline("call check_err(iret)"); } /* * Output a C statement. */ void cline( const char *stmnt) { FILE *cout = stdout; fputs(stmnt, cout); fputs("\n", cout); } /* * From a long line FORTRAN statment, generates the necessary FORTRAN * lines with continuation characters in column 6. If stmnt starts with "*", * it is treated as a one-line comment. Statement labels are *not* handled, * but since we don't generate any labels, we don't care. */ void fline( const char *stmnt) { FILE *fout = stdout; int len = (int) strlen(stmnt); int line = 0; static char cont[] = { /* continuation characters */ ' ', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; if(stmnt[0] == '*') { fputs(stmnt, fout); fputs("\n", fout); return; } while (len > 0) { if (line >= FORT_MAX_LINES) derror("FORTRAN statement too long: %s",stmnt); (void) fprintf(fout, " %c", cont[line++]); (void) fprintf(fout, "%.66s\n", stmnt); len -= 66; if (len > 0) stmnt += 66; } } /* return C name for netCDF type, given type code */ char * nctype( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "NC_BYTE"; case NC_CHAR: return "NC_CHAR"; case NC_SHORT: return "NC_SHORT"; case NC_INT: return "NC_INT"; case NC_FLOAT: return "NC_FLOAT"; case NC_DOUBLE: return "NC_DOUBLE"; default: derror("nctype: bad type code"); return 0; } } /* * Return C type name for netCDF type, given type code. */ char * ncctype( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "signed char"; case NC_CHAR: return "char"; case NC_SHORT: return "short"; case NC_INT: return "int"; case NC_FLOAT: return "float"; case NC_DOUBLE: return "double"; default: derror("ncctype: bad type code"); return 0; } } /* * Return C type name for netCDF type suffix, given type code. */ char * ncstype( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "schar"; case NC_CHAR: return "text"; case NC_SHORT: return "short"; case NC_INT: return "int"; case NC_FLOAT: return "float"; case NC_DOUBLE: return "double"; default: derror("ncstype: bad type code"); return 0; } } /* * Return C type name for netCDF attribute container type, given type code. */ char * ncatype( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return "int"; /* avoids choosing between uchar and schar */ case NC_CHAR: return "text"; case NC_SHORT: return "short"; case NC_INT: return "int"; case NC_FLOAT: return "float"; case NC_DOUBLE: return "double"; default: derror("ncatype: bad type code"); return 0; } } /* return internal size for values of specified netCDF type */ size_t nctypesize( nc_type type) /* netCDF type code */ { switch (type) { case NC_BYTE: return sizeof(char); case NC_CHAR: return sizeof(char); case NC_SHORT: return sizeof(short); case NC_INT: return sizeof(int); case NC_FLOAT: return sizeof(float); case NC_DOUBLE: return sizeof(double); default: derror("nctypesize: bad type code"); return 0; } } /* * Given a netcdf numeric type, a pointer to a vector of values of that * type, and the index of the vector element desired, returns a pointer * to a malloced string representing the value in FORTRAN. Since this * may be used in a DATA statement, it must not include non-constant * expressions, such as "char(26)". */ char * fstring( nc_type type, /* netCDF type code */ void *valp, /* pointer to vector of values */ int num) /* element of vector desired */ { static char *cp; signed char *schp; short *shortp; int *intp; float *floatp; double *doublep; switch (type) { case NC_BYTE: cp = (char *) emalloc (10); schp = (signed char *)valp; sprintf(cp,"%d", schp[num]); return cp; case NC_SHORT: cp = (char *) emalloc (10); shortp = (short *)valp; (void) sprintf(cp,"%d",* (shortp + num)); return cp; case NC_INT: cp = (char *) emalloc (20); intp = (int *)valp; (void) sprintf(cp,"%d",* (intp + num)); return cp; case NC_FLOAT: cp = (char *) emalloc (20); floatp = (float *)valp; (void) sprintf(cp,"%.8g",* (floatp + num)); return cp; case NC_DOUBLE: cp = (char *) emalloc (25); doublep = (double *)valp; (void) sprintf(cp,"%.16g",* (doublep + num)); expe2d(cp); /* change 'e' to 'd' in exponent */ return cp; default: derror("fstring: bad type code"); return 0; } } /* * Given a pointer to a counted string, returns a pointer to a malloced string * representing the string as a C constant. */ char * cstrstr( const char *valp, /* pointer to vector of characters*/ size_t len) /* number of characters in valp */ { static char *sp; char *cp; char *istr, *istr0; /* for null-terminated copy */ int ii; if(4*len+3 != (unsigned)(4*len+3)) { derror("too much character data!"); exit(9); } sp = cp = (char *) emalloc(4*len+3); if(len == 1 && *valp == 0) { /* empty string */ strcpy(sp,"\"\""); return sp; } istr0 = istr = (char *) emalloc(len + 1); for(ii = 0; ii < len; ii++) { istr[ii] = valp[ii]; } istr[len] = '\0'; *cp++ = '"'; for(ii = 0; ii < len; ii++) { switch (*istr) { case '\0': *cp++ = '\\'; *cp++ = '0'; *cp++ = '0'; *cp++ = '0'; break; case '\b': *cp++ = '\\'; *cp++ = 'b'; break; case '\f': *cp++ = '\\'; *cp++ = 'f'; break; case '\n': *cp++ = '\\'; *cp++ = 'n'; break; case '\r': *cp++ = '\\'; *cp++ = 'r'; break; case '\t': *cp++ = '\\'; *cp++ = 't'; break; case '\v': *cp++ = '\\'; *cp++ = 'v'; break; case '\\': *cp++ = '\\'; *cp++ = '\\'; break; case '\"': *cp++ = '\\'; *cp++ = '\"'; break; default: if (!isprint(*istr)) { static char octs[] = "01234567"; int rem = ((unsigned char)*istr)%64; *cp++ = '\\'; *cp++ = octs[((unsigned char)*istr)/64]; /* to get, e.g. '\177' */ *cp++ = octs[rem/8]; *cp++ = octs[rem%8]; } else { *cp++ = *istr; } break; } istr++; } *cp++ = '"'; *cp = '\0'; free(istr0); return sp; } /* Given a pointer to a counted string (not necessarily * null-terminated), returns a pointer to a malloced string representing * the string as a FORTRAN string expression. For example, the string * "don't" would yield the FORTRAN string "'don''t'", and the string * "ab\ncd" would yield "'ab'//char(10)//'cd'". The common * interpretation of "\"-escaped characters is non-standard, so the * generated Fortran may require adjustment in compilers that don't * recognize "\" as anything special in a character context. */ char * fstrstr( const char *str, /* pointer to vector of characters */ size_t ilen) /* number of characters in istr */ { static char *ostr; char *cp, tstr[12]; int was_print = 0; /* true if last character was printable */ char *istr, *istr0; /* for null-terminated copy */ int ii; if(12*ilen != (size_t)(12*ilen)) { derror("too much character data!"); exit(9); } istr0 = istr = (char *) emalloc(ilen + 1); for(ii = 0; ii < ilen; ii++) { istr[ii] = str[ii]; } istr[ilen] = '\0'; if (*istr == '\0') { /* empty string input, not legal in FORTRAN */ ostr = (char*) emalloc(strlen("char(0)") + 1); strcpy(ostr, "char(0)"); free(istr0); return ostr; } ostr = cp = (char *) emalloc(12*ilen); *ostr = '\0'; if (isprint(*istr)) { /* handle first character in input */ *cp++ = '\''; switch (*istr) { case '\'': *cp++ = '\''; *cp++ = '\''; break; case '\\': *cp++ = '\\'; *cp++ = '\\'; break; default: *cp++ = *istr; break; } *cp = '\0'; was_print = 1; } else { sprintf(tstr, "char(%d)", (unsigned char)*istr); strcat(cp, tstr); cp += strlen(tstr); was_print = 0; } istr++; for(ii = 1; ii < ilen; ii++) { /* handle subsequent characters in input */ if (isprint(*istr)) { if (! was_print) { strcat(cp, "//'"); cp += 3; } switch (*istr) { case '\'': *cp++ = '\''; *cp++ = '\''; break; case '\\': *cp++ = '\\'; *cp++ = '\\'; break; default: *cp++ = *istr; break; } *cp = '\0'; was_print = 1; } else { if (was_print) { *cp++ = '\''; *cp = '\0'; } sprintf(tstr, "//char(%d)", (unsigned char)*istr); strcat(cp, tstr); cp += strlen(tstr); was_print = 0; } istr++; } if (was_print) *cp++ = '\''; *cp = '\0'; free(istr0); return ostr; } static void cl_netcdf(void) { int stat = miclose(ncid); check_err(stat); } static void cl_c(void) { cline(" stat = nc_close(ncid);"); cline(" check_err(stat,__LINE__,__FILE__);"); #ifndef vms cline(" return 0;"); #else cline(" return 1;"); #endif cline("}"); } /* Returns true if dimension used in at least one record variable, otherwise false. This is an inefficient algorithm, but we don't call it very often ... */ static int used_in_rec_var( int idim /* id of dimension */ ) { int ivar; for (ivar = 0; ivar < nvars; ivar++) { if (vars[ivar].ndims > 0 && vars[ivar].dims[0] == rec_dim) { int jdim; for (jdim = 0; jdim < vars[ivar].ndims; jdim++) { if (vars[ivar].dims[jdim] == idim) return 1; } } } return 0; } /* Return name for Fortran fill constant of specified type */ static char * f_fill_name( nc_type type ) { switch(type) { case NC_BYTE: return "NF_FILL_BYTE"; case NC_CHAR: return "NF_FILL_CHAR"; case NC_SHORT: return "NF_FILL_SHORT"; case NC_INT: return "NF_FILL_INT"; case NC_FLOAT: return "NF_FILL_FLOAT"; case NC_DOUBLE: return "NF_FILL_DOUBLE"; } derror("f_fill_name: bad type code"); return 0; } /* Generate Fortran for cleaning up and closing file */ static void cl_fortran(void) { int ivar; int idim; char stmnt[FORT_MAX_STMNT]; char s2[FORT_MAX_STMNT]; char*sp; int have_rec_var = 0; /* do we have any record variables? */ for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim) { have_rec_var = 1; break; } } if (have_rec_var) { fline(" "); fline("* Write record variables"); sprintf(stmnt, "call writerecs(ncid,"); /* generate parameter list for subroutine to write record vars */ for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; /* if a record variable, include id in parameter list */ if (v->ndims > 0 && v->dims[0] == rec_dim) { sprintf(s2, "%s_id,", v->lname); strcat(stmnt, s2); } } sp = strrchr(stmnt, ','); if(sp != NULL) { *sp = '\0'; } strcat(stmnt, ")"); fline(stmnt); } fline(" "); fline("iret = nf_close(ncid)"); fline("call check_err(iret)"); fline("end"); fline(" "); if (have_rec_var) { sprintf(stmnt, "subroutine writerecs(ncid,"); for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim) { sprintf(s2, "%s_id,", v->lname); strcat(stmnt, s2); } } sp = strrchr(stmnt, ','); if(sp != NULL) { *sp = '\0'; } strcat(stmnt, ")"); fline(stmnt); fline(" "); fline("* netCDF id"); fline("integer ncid"); fline("* variable ids"); for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim) { sprintf(stmnt, "integer %s_id", v->lname); fline(stmnt); } } fline(" "); fline("include 'netcdf.inc'"); /* create necessary declarations */ fline("* error status return"); fline("integer iret"); /* generate integer/parameter declarations for all dimensions used in record variables, except record dimension. */ fline(" "); fline("* netCDF dimension sizes for dimensions used with record variables"); for (idim = 0; idim < ndims; idim++) { /* if used in a record variable and not record dimension */ if (used_in_rec_var(idim) && dims[idim].size != NC_UNLIMITED) { sprintf(stmnt, "integer %s_len", dims[idim].lname); fline(stmnt); sprintf(stmnt, "parameter (%s_len = %lu)", dims[idim].lname, (unsigned long) dims[idim].size); fline(stmnt); } } fline(" "); fline("* rank (number of dimensions) for each variable"); for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim) { sprintf(stmnt, "integer %s_rank", v->lname); fline(stmnt); } } for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim) { sprintf(stmnt, "parameter (%s_rank = %d)", v->lname, v->ndims); fline(stmnt); } } fline("* starts and counts for array sections of record variables"); for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim) { sprintf(stmnt, "integer %s_start(%s_rank), %s_count(%s_rank)", v->lname, v->lname, v->lname, v->lname); fline(stmnt); } } fline(" "); fline("* data variables"); for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim) { char *sp; fline(" "); sprintf(stmnt, "integer %s_nr", v->lname); fline(stmnt); if (v->nrecs > 0) { sprintf(stmnt, "parameter (%s_nr = %lu)", v->lname, (unsigned long) v->nrecs); } else { sprintf(stmnt, "parameter (%s_nr = 1)", v->lname); } fline(stmnt); if (v->type != NC_CHAR) { sprintf(stmnt, "%s %s(", ncftype(v->type), v->lname); /* reverse dimensions for FORTRAN */ for (idim = v->ndims-1; idim >= 0; idim--) { if(v->dims[idim] == rec_dim) { sprintf(s2, "%s_nr, ", v->lname); } else { sprintf(s2, "%s_len, ", dims[v->dims[idim]].lname); } strcat(stmnt, s2); } sp = strrchr(stmnt, ','); if(sp != NULL) { *sp = '\0'; } strcat(stmnt, ")"); fline(stmnt); } } } fline(" "); /* Emit DATA statements after declarations, because f2c on Linux can't handle interspersing them */ for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; if (v->ndims > 0 && v->dims[0] == rec_dim && v->type != NC_CHAR) { if (v->has_data) { fline(v->data_stmnt); } else { /* generate data statement for FILL record */ size_t rec_len = 1; for (idim = 1; idim < v->ndims; idim++) { rec_len *= dims[v->dims[idim]].size; } sprintf(stmnt,"data %s /%lu * %s/", v->lname, (unsigned long) rec_len, f_fill_name(v->type)); fline(stmnt); } } } fline(" "); for (ivar = 0; ivar < nvars; ivar++) { struct vars *v = &vars[ivar]; /* if a record variable, declare starts and counts */ if (v->ndims > 0 && v->dims[0] == rec_dim) { if (!v->has_data) continue; sprintf(stmnt, "* store %s", v->name); fline(stmnt); for (idim = 0; idim < v->ndims; idim++) { sprintf(stmnt, "%s_start(%d) = 1", v->lname, idim+1); fline(stmnt); } for (idim = v->ndims-1; idim > 0; idim--) { sprintf(stmnt, "%s_count(%d) = %s_len", v->lname, v->ndims - idim, dims[v->dims[idim]].lname); fline(stmnt); } sprintf(stmnt, "%s_count(%d) = %s_nr", v->lname, v->ndims, v->lname); fline(stmnt); if (v->type != NC_CHAR) { sprintf(stmnt, "iret = nf_put_vara_%s(ncid, %s_id, %s_start, %s_count, %s)", nfftype(v->type), v->lname, v->lname, v->lname, v->lname); } else { sprintf(stmnt, "iret = nf_put_vara_%s(ncid, %s_id, %s_start, %s_count, %s)", nfftype(v->type), v->lname, v->lname, v->lname, v->data_stmnt); } fline(stmnt); fline("call check_err(iret)"); } } fline(" "); fline("end"); fline(" "); } fline("subroutine check_err(iret)"); fline("integer iret"); fline("include 'netcdf.inc'"); fline("if (iret .ne. NF_NOERR) then"); fline("print *, nf_strerror(iret)"); fline("stop"); fline("endif"); fline("end"); } /* invoke netcdf calls (or generate C or Fortran code) to create netcdf * from in-memory structure. */ void define_netcdf( char *netcdfname) { char *filename; /* output file name */ if (netcdf_name) { /* name given on command line */ filename = netcdf_name; } else { /* construct name from CDL name */ filename = (char *) emalloc(strlen(netcdfname) + 5); (void) strcpy(filename,netcdfname); (void) strcat(filename,".mnc"); } if (netcdf_flag) gen_netcdf(filename); /* create netcdf */ if (c_flag) /* create C code to create netcdf */ gen_c(filename); if (fortran_flag) /* create Fortran code to create netcdf */ gen_fortran(filename); if (!netcdf_name) { free(filename); } } void close_netcdf(void) { if (netcdf_flag) cl_netcdf(); /* close netcdf */ if (c_flag) /* create C code to close netcdf */ cl_c(); if (fortran_flag) /* create Fortran code to close netcdf */ cl_fortran(); } void check_err(int stat) { if (stat < 0) { fprintf(stderr, "ncgen: %s\n", nc_strerror(stat)); } } /* * For logging error conditions. */ #ifndef NO_STDARG void derror(const char *fmt, ...) #else /*VARARGS1*/ void derror(fmt, va_alist) const char *fmt ; /* error-message printf-style format */ va_dcl /* variable number of error args, if any */ #endif /* !NO_STDARG */ { va_list args ; if (lineno == 1) (void) fprintf(stderr,"%s: %s: ", progname, cdlname); else (void) fprintf(stderr,"%s: %s line %d: ", progname, cdlname, lineno); #ifndef NO_STDARG va_start(args ,fmt) ; #else va_start(args) ; #endif /* !NO_STDARG */ (void) vfprintf(stderr,fmt,args) ; va_end(args) ; (void) fputc('\n',stderr) ; (void) fflush(stderr); /* to ensure log files are current */ derror_count++; } void * emalloc ( /* check return from malloc */ size_t size) { void *p; p = (void *) malloc (size); if (p == 0) { derror ("out of memory\n"); exit(3); } return p; } void * ecalloc ( /* check return from calloc */ size_t size) { void *p; p = (void *) calloc (size, 1); if (p == 0) { derror ("out of memory\n"); exit(3); } return p; } void * erealloc ( /* check return from realloc */ void *ptr, size_t size) /* if 0, this is really a free */ { void *p; p = (void *) realloc (ptr, size); if (p == 0 && size != 0) { derror ("out of memory"); exit(3); } return p; } /* * For generated Fortran, change 'e' to 'd' in exponent of double precision * constants. */ void expe2d( char *cp) /* string containing double constant */ { char *expchar = strrchr(cp,'e'); if (expchar) { *expchar = 'd'; } } /* Returns non-zero if n is a power of 2, 0 otherwise */ int pow2( int n) { int m = n; int p = 1; while (m > 0) { m /= 2; p *= 2; } return p == 2*n; } /* * Grow an integer array as necessary. * * Assumption: nar never incremented by more than 1 from last call. * * Makes sure an array is within a factor of 2 of the size needed. * * Make sure *arpp points to enough space to hold nar integers. If not big * enough, malloc more space, copy over existing stuff, free old. When * called for first time, *arpp assumed to be uninitialized. */ void grow_iarray( int nar, /* array must be at least this big */ int **arpp) /* address of start of int array */ { if (nar == 0) { *arpp = (int *) emalloc(1 * sizeof(int)); return; } if (! pow2(nar)) /* return unless nar is a power of two */ return; *arpp = (int *) erealloc(*arpp, 2 * nar * sizeof(int)); } /* * Grow an array of variables as necessary. * * Assumption: nar never incremented by more than 1 from last call. * * Makes sure array is within a factor of 2 of the size needed. * * Make sure *arpp points to enough space to hold nar variables. If not big * enough, malloc more space, copy over existing stuff, free old. When * called for first time, *arpp assumed to be uninitialized. */ void grow_varray( int nar, /* array must be at least this big */ struct vars **arpp) /* address of start of var array */ { if (nar == 0) { *arpp = (struct vars *) emalloc(1 * sizeof(struct vars)); return; } if (! pow2(nar)) /* return unless nar is a power of two */ return; *arpp = (struct vars *) erealloc(*arpp, 2 * nar * sizeof(struct vars)); } /* * Grow an array of dimensions as necessary. * * Assumption: nar never incremented by more than 1 from last call. * * Makes sure array is within a factor of 2 of the size needed. * * Make sure *arpp points to enough space to hold nar dimensions. If not big * enough, malloc more space, copy over existing stuff, free old. When * called for first time, *arpp assumed to be uninitialized. */ void grow_darray( int nar, /* array must be at least this big */ struct dims **arpp) /* address of start of var array */ { if (nar == 0) { *arpp = (struct dims *) emalloc(1 * sizeof(struct dims)); return; } if (! pow2(nar)) /* return unless nar is a power of two */ return; *arpp = (struct dims *) erealloc(*arpp, 2 * nar * sizeof(struct dims)); } /* * Grow an array of attributes as necessary. * * Assumption: nar never incremented by more than 1 from last call. * * Makes sure array is within a factor of 2 of the size needed. * * Make sure *arpp points to enough space to hold nar attributes. If not big * enough, malloc more space, copy over existing stuff, free old. When * called for first time, *arpp assumed to be uninitialized. */ void grow_aarray( int nar, /* array must be at least this big */ struct atts **arpp) /* address of start of var array */ { if (nar == 0) { *arpp = (struct atts *) emalloc(1 * sizeof(struct atts)); return; } if (! pow2(nar)) /* return unless nar is a power of two */ return; *arpp = (struct atts *) erealloc(*arpp, 2 * nar * sizeof(struct atts)); } /* * Replace dashes and dots in name so it can be used in C and * Fortran without causing syntax errors. Here we just replace each "-" * in a name with "_dash_" and each "." with "_dot_", though any * similar replacement that doesn't clash with existing names would * work. */ extern char* decodify ( const char *name) { int count=0; /* number of minus signs in name */ char *newname; const char *cp = name; char *sp; while(*cp != '\0') { switch (*cp) { case '-': count += strlen("_dash_") - 1; break; case '.': count += strlen("_dot_") - 1; break; case '@': count += strlen("_at_") - 1; break; case '#': count += strlen("_hash_") - 1; break; case '[': count += strlen("_lbr_") - 1; break; case ']': count += strlen("_rbr_") - 1; break; default: break; } cp++; } newname = (char *) ecalloc(strlen(name) + count + 1); cp = name; sp = newname; while(*cp != '\0') { switch (*cp) { case '-': strcat(sp, "_dash_"); sp += strlen("_dash_"); break; case '.': strcat(sp, "_dot_"); sp += strlen("_dot_"); break; case '@': strcat(sp, "_at_"); sp += strlen("_at_"); break; case '#': strcat(sp, "_hash_"); sp += strlen("_hash_"); break; case '[': strcat(sp, "_lbr_"); sp += strlen("_lbr_"); break; case ']': strcat(sp, "_rbr_"); sp += strlen("_rbr_"); break; default: *sp++ = *cp; break; } cp++; } *sp = '\0'; return newname; } minc-2.2.00/progs/mincgen/getfill.c0000644000265600003100000000527712027132663014020 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/getfill.c,v 1.2 2008-01-12 19:08:15 stever Exp $ *********************************************************************/ #include "netcdf.h" #include "generic.h" #include "ncgen.h" #include "genlib.h" /* * Given netCDF type, return a default fill_value appropriate for * that type. */ void nc_getfill( nc_type type, union generic *gval) { switch(type) { case NC_CHAR: gval->charv = NC_FILL_CHAR; return; case NC_BYTE: gval->charv = NC_FILL_BYTE; return; case NC_SHORT: gval->shortv = NC_FILL_SHORT; return; case NC_INT: gval->intv = NC_FILL_INT; return; case NC_FLOAT: gval->floatv = NC_FILL_FLOAT; return; case NC_DOUBLE: gval->doublev = NC_FILL_DOUBLE; return; default: derror("nc_getfill: unrecognized type"); } } void nc_fill( nc_type type, /* netcdf type code */ size_t num, /* number of values to fill */ void *datp, /* where to start filling */ union generic fill_val) /* value to use */ { char *char_valp; /* pointers used to accumulate data values */ short *short_valp; int *long_valp; float *float_valp; double *double_valp; switch (type) { case NC_CHAR: case NC_BYTE: char_valp = (char *) datp; break; case NC_SHORT: short_valp = (short *) datp; break; case NC_INT: long_valp = (int *) datp; break; case NC_FLOAT: float_valp = (float *) datp; break; case NC_DOUBLE: double_valp = (double *) datp; break; } while (num--) { switch (type) { case NC_CHAR: case NC_BYTE: *char_valp++ = fill_val.charv; break; case NC_SHORT: *short_valp++ = fill_val.shortv; break; case NC_INT: *long_valp++ = fill_val.intv; break; case NC_FLOAT: *float_valp++ = fill_val.floatv; break; case NC_DOUBLE: *double_valp++ = fill_val.doublev; break; } } } /* * Given netCDF type, put a value of that type into a fill_value */ void nc_putfill( nc_type type, void *val, /* value of type to be put */ union generic *gval) /* where the value is to be put */ { switch(type) { case NC_CHAR: case NC_BYTE: gval->charv = *(char *)val; return; case NC_SHORT: gval->shortv = *(short *)val; return; case NC_INT: gval->intv = *(int *)val; return; case NC_FLOAT: gval->floatv = *(float *)val; return; case NC_DOUBLE: gval->doublev = *(double *)val; return; default: derror("nc_putfill: unrecognized type"); } } minc-2.2.00/progs/mincgen/init.c0000644000265600003100000000323412027132663013324 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/init.c,v 1.2 2006-05-19 00:35:58 bert Exp $ *********************************************************************/ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include "generic.h" #include "ncgen.h" #include "genlib.h" extern int netcdf_flag; extern int c_flag; extern int fortran_flag; struct dims *dims; /* table of netcdf dimensions */ int ncid; /* handle for netCDF */ int ndims; /* number of dimensions declared for netcdf */ int nvars; /* number of variables declared for netcdf */ int natts; /* number of attributes */ int nvdims; /* number of dimensions for variables */ int dimnum; /* dimension number index for variables */ int varnum; /* variable number index for attributes */ int valnum; /* value number index for attributes */ int rec_dim; /* number of the unlimited dimension, if any */ size_t var_len; /* variable length (product of dimensions) */ size_t rec_len; /* number of elements for a record of data */ size_t var_size; /* size of each element of variable */ struct vars *vars; /* a malloc'ed list */ struct atts *atts; /* table of variable and global attributes */ int is_hdf5; /* TRUE if HDF5 file */ void init_netcdf(int flag) { /* initialize global counts, flags */ clearout(); /* reset symbol table to empty */ ndims = 0; nvars = 0; rec_dim = -1; /* means no unlimited dimension (yet) */ is_hdf5 = flag; } minc-2.2.00/progs/mincgen/load.c0000644000265600003100000003010212027132663013272 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Id: load.c,v 1.3 2005-11-23 04:37:26 bert Exp $ *********************************************************************/ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "generic.h" #include "ncgen.h" #include "genlib.h" extern int netcdf_flag; extern int c_flag; extern int fortran_flag; #define fpr (void) fprintf /* * Remove trailing zeros (after decimal point) but not trailing decimal * point from ss, a string representation of a floating-point number that * might include an exponent part. */ static void tztrim( char *ss /* returned string representing dd */ ) { char *cp, *ep; cp = ss; if (*cp == '-') cp++; while(isdigit((int)*cp) || *cp == '.') cp++; if (*--cp == '.') return; ep = cp+1; while (*cp == '0') cp--; cp++; if (cp == ep) return; while (*ep) *cp++ = *ep++; *cp = '\0'; return; } /* generate C to put netCDF record from in-memory data */ static void gen_load_c( void *rec_start ) { int idim, ival; char *val_string; char *charvalp; short *shortvalp; int *intvalp; float *floatvalp; double *doublevalp; char stmnt[C_MAX_STMNT]; size_t stmnt_len; char s2[C_MAX_STMNT]; if (!vars[varnum].has_data) return; cline(""); sprintf(stmnt, " {\t\t\t/* store %s */", vars[varnum].name); cline(stmnt); if (vars[varnum].ndims > 0) { if (vars[varnum].dims[0] == rec_dim) { sprintf(stmnt, " static size_t %s_start[RANK_%s];", vars[varnum].lname, vars[varnum].lname); cline(stmnt); sprintf(stmnt, " static size_t %s_count[RANK_%s];", vars[varnum].lname, vars[varnum].lname); cline(stmnt); } /* load variable with data values using static initialization */ sprintf(stmnt, " static %s %s[] = {", ncctype(vars[varnum].type), vars[varnum].lname); stmnt_len = strlen(stmnt); switch (vars[varnum].type) { case NC_CHAR: val_string = cstrstr((char *) rec_start, var_len); sprintf(s2, "%s", val_string); strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) ); free(val_string); break; default: switch (vars[varnum].type) { case NC_BYTE: charvalp = (char *) rec_start; break; case NC_SHORT: shortvalp = (short *) rec_start; break; case NC_INT: intvalp = (int *) rec_start; break; case NC_FLOAT: floatvalp = (float *) rec_start; break; case NC_DOUBLE: doublevalp = (double *) rec_start; break; } for (ival = 0; ival < var_len-1; ival++) { switch (vars[varnum].type) { case NC_BYTE: sprintf(s2, "%d, ", *charvalp++); break; case NC_SHORT: sprintf(s2, "%d, ", *shortvalp++); break; case NC_INT: sprintf(s2, "%ld, ", (long)*intvalp++); break; case NC_FLOAT: sprintf(s2, "%.8g, ", *floatvalp++); break; case NC_DOUBLE: sprintf(s2, "%#.16g", *doublevalp++); tztrim(s2); strcat(s2, ", "); break; } stmnt_len += strlen(s2); if (stmnt_len < C_MAX_STMNT) strcat(stmnt, s2); else { cline(stmnt); strcpy(stmnt,s2); stmnt_len = strlen(stmnt); } } for (;ival < var_len; ival++) { switch (vars[varnum].type) { case NC_BYTE: sprintf(s2, "%d", *charvalp); break; case NC_SHORT: sprintf(s2, "%d", *shortvalp); break; case NC_INT: sprintf(s2, "%ld", (long)*intvalp); break; case NC_FLOAT: sprintf(s2, "%.8g", *floatvalp); break; case NC_DOUBLE: sprintf(s2, "%#.16g", *doublevalp++); tztrim(s2); break; } stmnt_len += strlen(s2); if (stmnt_len < C_MAX_STMNT) strcat(stmnt, s2); else { cline(stmnt); strcpy(stmnt,s2); stmnt_len = strlen(stmnt); } } break; } strcat(stmnt,"};"); cline(stmnt); if (vars[varnum].dims[0] == rec_dim) { sprintf(stmnt, " %s_len = %lu; /* number of records of %s data */", dims[rec_dim].lname, (unsigned long)vars[varnum].nrecs, /* number of recs for this variable */ vars[varnum].name); cline(stmnt); for (idim = 0; idim < vars[varnum].ndims; idim++) { sprintf(stmnt, " %s_start[%d] = 0;", vars[varnum].lname, idim); cline(stmnt); } for (idim = 0; idim < vars[varnum].ndims; idim++) { sprintf(stmnt, " %s_count[%d] = %s_len;", vars[varnum].lname, idim, dims[vars[varnum].dims[idim]].lname); cline(stmnt); } } if (vars[varnum].dims[0] == rec_dim) { sprintf(stmnt, " stat = nc_put_vara_%s(ncid, %s_id, %s_start, %s_count, %s);", ncstype(vars[varnum].type), vars[varnum].lname, vars[varnum].lname, vars[varnum].lname, vars[varnum].lname); } else { /* non-record variables */ sprintf(stmnt, " stat = nc_put_var_%s(ncid, %s_id, %s);", ncstype(vars[varnum].type), vars[varnum].lname, vars[varnum].lname); } cline(stmnt); } else { /* scalar variables */ /* load variable with data values using static initialization */ sprintf(stmnt, " static %s %s = ", ncctype(vars[varnum].type), vars[varnum].lname); switch (vars[varnum].type) { case NC_CHAR: val_string = cstrstr((char *) rec_start, var_len); val_string[strlen(val_string)-1] = '\0'; sprintf(s2, "'%s'", &val_string[1]); free(val_string); break; case NC_BYTE: charvalp = (char *) rec_start; sprintf(s2, "%d", *charvalp); break; case NC_SHORT: shortvalp = (short *) rec_start; sprintf(s2, "%d", *shortvalp); break; case NC_INT: intvalp = (int *) rec_start; sprintf(s2, "%ld", (long)*intvalp); break; case NC_FLOAT: floatvalp = (float *) rec_start; sprintf(s2, "%.8g", *floatvalp); break; case NC_DOUBLE: doublevalp = (double *) rec_start; sprintf(s2, "%#.16g", *doublevalp++); tztrim(s2); break; } strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) ); strcat(stmnt,";"); cline(stmnt); sprintf(stmnt, " stat = nc_put_var_%s(ncid, %s_id, &%s);", ncstype(vars[varnum].type), vars[varnum].lname, vars[varnum].lname); cline(stmnt); } cline(" check_err(stat,__LINE__,__FILE__);"); cline(" }"); } /* * Add to a partial Fortran statement, checking if it's too long. If it is too * long, output the first part of it as a single statement with continuation * characters and start a new (probably invalid) statement with the remainder. * This will cause a Fortran compiler error, but at least all the information * will be available. */ static void fstrcat( char *s, /* source string of stement being built */ char *t, /* string to be appended to source */ size_t *slenp /* pointer to length of source string */ ) { *slenp += strlen(t); if (*slenp >= FORT_MAX_STMNT) { derror("FORTRAN statement too long: %s",s); fline(s); strcpy(s, t); *slenp = strlen(s); } else { strcat(s, t); } } /* * Create Fortran data statement to initialize numeric variable with * values. */ static void f_var_init( int varnum, /* which variable */ void *rec_start /* start of data */ ) { char *val_string; char *charvalp; short *shortvalp; int *intvalp; float *floatvalp; double *doublevalp; char stmnt[FORT_MAX_STMNT]; size_t stmnt_len; char s2[FORT_MAX_STMNT]; int ival; /* load variable with data values */ sprintf(stmnt, "data %s /",vars[varnum].lname); stmnt_len = strlen(stmnt); switch (vars[varnum].type) { case NC_BYTE: charvalp = (char *) rec_start; for (ival = 0; ival < var_len-1; ival++) { val_string = fstring(NC_BYTE,(void *)charvalp++,0); sprintf(s2, "%s, ", val_string); fstrcat(stmnt, s2, &stmnt_len); free(val_string); } val_string = fstring(NC_BYTE,(void *)charvalp++,0); fstrcat(stmnt, val_string, &stmnt_len); free(val_string); break; case NC_SHORT: shortvalp = (short *) rec_start; for (ival = 0; ival < var_len-1; ival++) { sprintf(s2, "%d, ", *shortvalp++); fstrcat(stmnt, s2, &stmnt_len); } sprintf(s2, "%d", *shortvalp); fstrcat(stmnt, s2, &stmnt_len); break; case NC_INT: intvalp = (int *) rec_start; for (ival = 0; ival < var_len-1; ival++) { sprintf(s2, "%ld, ", (long)*intvalp++); fstrcat(stmnt, s2, &stmnt_len); } sprintf(s2, "%ld", (long)*intvalp); fstrcat(stmnt, s2, &stmnt_len); break; case NC_FLOAT: floatvalp = (float *) rec_start; for (ival = 0; ival < var_len-1; ival++) { sprintf(s2, "%.8g, ", *floatvalp++); fstrcat(stmnt, s2, &stmnt_len); } sprintf(s2, "%.8g", *floatvalp); fstrcat(stmnt, s2, &stmnt_len); break; case NC_DOUBLE: doublevalp = (double *) rec_start; for (ival = 0; ival < var_len-1; ival++) { sprintf(s2, "%#.16g", *doublevalp++); tztrim(s2); expe2d(s2); /* change 'e' to 'd' in exponent */ fstrcat(s2, ", ", &stmnt_len); fstrcat(stmnt, s2, &stmnt_len); } sprintf(s2, "%#.16g", *doublevalp++); tztrim(s2); expe2d(s2); fstrcat(stmnt, s2, &stmnt_len); break; default: derror("fstrstr: bad type"); break; } fstrcat(stmnt, "/", &stmnt_len); /* For record variables, store data statement for later use; otherwise, just print it. */ if (vars[varnum].ndims > 0 && vars[varnum].dims[0] == rec_dim) { char *dup_stmnt = emalloc(strlen(stmnt)+1); strcpy(dup_stmnt, stmnt); /* ULTRIX missing strdup */ vars[varnum].data_stmnt = dup_stmnt; } else { fline(stmnt); } } /* make Fortran to put record */ static void gen_load_fortran( void *rec_start ) { char stmnt[FORT_MAX_STMNT]; struct vars *v = &vars[varnum]; if (!v->has_data) return; if (v->ndims == 0 || v->dims[0] != rec_dim) { sprintf(stmnt, "* store %s", v->name); fline(stmnt); } /* generate code to initialize variable with values found in CDL input */ if (v->type != NC_CHAR) { f_var_init(varnum, rec_start); } else { v->data_stmnt = fstrstr(rec_start, valnum); } if (v->ndims >0 && v->dims[0] == rec_dim) { return; } if (v->type != NC_CHAR) { sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)", nfftype(v->type), v->lname, v->lname); } else { char *char_expr = fstrstr(rec_start, valnum); sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)", nfftype(v->type), v->lname, char_expr); free(char_expr); } fline(stmnt); fline("call check_err(iret)"); } /* invoke netcdf calls (or generate C or Fortran code) to load netcdf variable * from in-memory data. Assumes following global variables set from yacc * parser: * int varnum - number of variable to be loaded. * struct vars[varnum] - structure containing info on variable, specifically * name, type, ndims, dims, fill_value, has_data * int rec_dim - id of record dimension, or -1 if none * struct dims[] - structure containing name and size of dimensions. */ int put_variable( void *rec_start /* points to data to be loaded */ ) { if (netcdf_flag) load_netcdf(rec_start); /* put variable values */ if (c_flag) /* create C code to put values */ gen_load_c(rec_start); if (fortran_flag) /* create Fortran code to put values */ gen_load_fortran(rec_start); return 0; } /* write out variable's data from in-memory structure */ void load_netcdf( void *rec_start ) { int idim; int stat; long start[NC_MAX_VAR_DIMS]; long count[NC_MAX_VAR_DIMS]; /* load values into variable */ if (vars[varnum].ndims > 0) { /* initialize start to upper left corner (0,0,0,...) */ start[0] = 0; if (vars[varnum].dims[0] == rec_dim) { count[0] = vars[varnum].nrecs; } else { count[0] = dims[vars[varnum].dims[0]].size; } } for (idim = 1; idim < vars[varnum].ndims; idim++) { start[idim] = 0; count[idim] = dims[vars[varnum].dims[idim]].size; } stat = ncvarput(ncid, varnum, start, count, rec_start); check_err(stat); } minc-2.2.00/progs/mincgen/main.c0000644000265600003100000000571612027132663013314 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /private-cvsroot/minc/progs/mincgen/main.c,v 1.6 2008-01-11 07:17:08 stever Exp $ *********************************************************************/ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef __hpux #include #endif #include #include #include "generic.h" #include "ncgen.h" #include "genlib.h" extern int yyparse(void); const char *progname; /* for error messages */ const char *cdlname; int c_flag; int fortran_flag; int netcdf_flag; char *netcdf_name = NULL; /* name of output netCDF file to write */ extern FILE *yyin; static const char* ubasename ( const char* av0 ); static void usage ( void ); int main ( int argc, char** argv ); /* strip off leading path */ static const char * ubasename( const char *av0) { const char *logident ; #ifdef VMS #define SEP ']' #endif #ifdef MSDOS #define SEP '\\' #endif #ifndef SEP #define SEP '/' #endif if ((logident = strrchr(av0, SEP)) == NULL) logident = av0 ; else logident++ ; return logident ; } static void usage(void) { derror("Usage: %s [ -b ] [ -c ] [ -f ] [ -o outfile] [ file ... ]", progname); derror("netcdf library version %s", nc_inq_libvers()); } int main( int argc, char *argv[]) { FILE *fp; static ArgvInfo argTable[] = { { "-b", ARGV_CONSTANT, (char *) 1, (char *) &netcdf_flag, "Select binary netCDF output" }, { "-c", ARGV_CONSTANT, (char *) 1, (char *) &c_flag, "Select 'C' output" }, { "-f", ARGV_CONSTANT, (char *) 1, (char *) &fortran_flag, "Select FORTRAN output" }, { "-o", ARGV_STRING, (char *) 1, (char *) &netcdf_name, "Select name for netCDF output" }, { NULL, ARGV_END, NULL, NULL, NULL } }; #ifdef __hpux setlocale(LC_CTYPE,""); #endif #ifdef MDEBUG malloc_debug(2) ; /* helps find malloc/free errors on Sun */ #endif /* MDEBUG */ progname = ubasename(argv[0]); cdlname = "-"; c_flag = 0; fortran_flag = 0; netcdf_flag = 0; #if _CRAYMPP && 0 /* initialize CRAY MPP parallel-I/O library */ (void) par_io_init(32, 32); #endif if (ParseArgv(&argc, argv, argTable, 0)) { usage(); return (8); } if (fortran_flag && c_flag) { derror("Only one of -c or -f may be specified"); return(8); } if (netcdf_name != NULL) { netcdf_flag = 1; } argc -= 1; argv += 1; if (argc > 1) { derror ("%s: only one input file argument permitted",progname); return(6); } fp = stdin; if (argc > 0 && strcmp(argv[0], "-") != 0) { if ((fp = fopen(argv[0], "r")) == NULL) { derror ("can't open file %s for reading: ", argv[0]); perror(""); return(7); } cdlname = argv[0]; } yyin = fp; return (yyparse()); } minc-2.2.00/progs/mincgen/ncgentab.y0000644000265600003100000005434712027132663014203 00000000000000/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Id: ncgentab.y,v 1.3 2008-01-13 06:49:41 stever Exp $ *********************************************************************/ /* yacc source for "ncgen", a netCDL parser and netCDF generator */ %{ #ifndef lint static char SccsId[] __attribute__ ((unused)) = "$Id: ncgentab.y,v 1.3 2008-01-13 06:49:41 stever Exp $"; #endif #include #include #include #include "generic.h" #include "ncgen.h" #include "genlib.h" /* for grow_darray() et al */ typedef struct Symbol { /* symbol table entry */ char *name; struct Symbol *next; unsigned is_dim : 1; /* appears as netCDF dimension */ unsigned is_var : 1; /* appears as netCDF variable */ unsigned is_att : 1; /* appears as netCDF attribute */ int dnum; /* handle as a dimension */ int vnum; /* handle as a variable */ } *YYSTYPE1; #define YYSTYPE YYSTYPE1 YYSTYPE symlist; /* symbol table: linked list */ extern int derror_count; /* counts errors in netcdf definition */ extern int lineno; /* line number for error messages */ static int not_a_string; /* whether last constant read was a string */ char termstring[MAXTRST]; /* last terminal string read */ double double_val; /* last double value read */ float float_val; /* last float value read */ int int_val; /* last int value read */ short short_val; /* last short value read */ static char char_val; /* last char value read */ signed char byte_val; /* last byte value read */ static nc_type type_code; /* holds declared type for variables */ static nc_type atype_code; /* holds derived type for attributes */ char *netcdfname; /* to construct netcdf file name */ static void *att_space; /* pointer to block for attribute values */ static nc_type valtype; /* type code for list of attribute values */ static char *char_valp; /* pointers used to accumulate data values */ static signed char *byte_valp; static short *short_valp; static int *int_valp; static float *float_valp; static double *double_valp; static void *rec_cur; /* pointer to where next data value goes */ static void *rec_start; /* start of space for data */ %} /* DECLARATIONS */ %token NC_UNLIMITED_K /* keyword for unbounded record dimension */ BYTE_K /* keyword for byte datatype */ CHAR_K /* keyword for char datatype */ SHORT_K /* keyword for short datatype */ INT_K /* keyword for int datatype */ FLOAT_K /* keyword for float datatype */ DOUBLE_K /* keyword for double datatype */ IDENT /* name for a dimension, variable, or attribute */ TERMSTRING /* terminal string */ BYTE_CONST /* byte constant */ CHAR_CONST /* char constant */ SHORT_CONST /* short constant */ INT_CONST /* int constant */ FLOAT_CONST /* float constant */ DOUBLE_CONST /* double constant */ DIMENSIONS /* keyword starting dimensions section, if any */ VARIABLES /* keyword starting variables section, if any */ NETCDF /* keyword declaring netcdf name */ HDF5 /* keyword declaring hdf5 name */ DATA /* keyword starting data section, if any */ FILLVALUE /* fill value, from _FillValue attribute or default */ %start ncdesc /* start symbol for grammar */ %% /* RULES */ ncdesc: NETCDF '{' { init_netcdf(0); } dimsection /* dimension declarations */ vasection /* variable and attribute declarations */ { if (derror_count == 0) define_netcdf(netcdfname); } datasection /* data, variables loaded as encountered */ '}' { if (derror_count == 0) close_netcdf(); } | HDF5 '{' { init_netcdf(1); } dimsection /* dimension declarations */ vasection /* variable and attribute declarations */ { if (derror_count == 0) define_netcdf(netcdfname); } datasection /* data, variables loaded as encountered */ '}' { if (derror_count == 0) close_netcdf(); } ; dimsection: /* empty */ | DIMENSIONS dimdecls ; dimdecls: dimdecline ';' | dimdecls dimdecline ';' ; dimdecline: dimdecl | dimdecline ',' dimdecl ; dimdecl: dimd '=' INT_CONST { if (int_val <= 0) derror("dimension length must be positive"); dims[ndims].size = int_val; ndims++; } | dimd '=' NC_UNLIMITED_K { if (rec_dim != -1) derror("only one NC_UNLIMITED dimension allowed"); rec_dim = ndims; /* the unlimited (record) dimension */ dims[ndims].size = NC_UNLIMITED; ndims++; } ; dimd: dim { if ($1->is_dim == 1) { derror( "duplicate dimension declaration for %s", $1->name); } $1->is_dim = 1; $1->dnum = ndims; /* make sure dims array will hold dimensions */ grow_darray(ndims, /* must hold ndims+1 dims */ &dims); /* grow as needed */ dims[ndims].name = (char *) emalloc(strlen($1->name)+1); (void) strcpy(dims[ndims].name, $1->name); /* name for use in generated Fortran and C variables */ dims[ndims].lname = decodify($1->name); } ; dim: IDENT ; vasection: /* empty */ | VARIABLES vadecls | gattdecls ; vadecls: vadecl ';' | vadecls vadecl ';' ; vadecl: vardecl | attdecl ; gattdecls: gattdecl ';' | gattdecls gattdecl ';' ; gattdecl: attdecl /* causes a shift/reduce conflict */ ; vardecl: type varlist ; type: BYTE_K { type_code = NC_BYTE; } | CHAR_K { type_code = NC_CHAR; } | SHORT_K { type_code = NC_SHORT; } | INT_K { type_code = NC_INT; } | FLOAT_K { type_code = NC_FLOAT; } | DOUBLE_K{ type_code = NC_DOUBLE; } ; varlist: varspec | varlist ',' varspec ; varspec: var { static struct vars dummyvar; dummyvar.name = "dummy"; dummyvar.type = NC_DOUBLE; dummyvar.ndims = 0; dummyvar.dims = 0; dummyvar.fill_value.doublev = NC_FILL_DOUBLE; dummyvar.has_data = 0; nvdims = 0; /* make sure variable not re-declared */ if ($1->is_var == 1) { derror( "duplicate variable declaration for %s", $1->name); } $1->is_var = 1; $1->vnum = nvars; /* make sure vars array will hold variables */ grow_varray(nvars, /* must hold nvars+1 vars */ &vars); /* grow as needed */ vars[nvars] = dummyvar; /* to make Purify happy */ vars[nvars].name = (char *) emalloc(strlen($1->name)+1); (void) strcpy(vars[nvars].name, $1->name); /* name for use in generated Fortran and C variables */ vars[nvars].lname = decodify($1->name); vars[nvars].type = type_code; /* set default fill value. You can override this with * the variable attribute "_FillValue". */ nc_getfill(type_code, &vars[nvars].fill_value); vars[nvars].has_data = 0; /* has no data (yet) */ } dimspec { vars[nvars].ndims = nvdims; nvars++; } ; var: IDENT ; dimspec: /* empty */ | '(' dimlist ')' ; dimlist: vdim | dimlist ',' vdim ; vdim: dim { if (nvdims >= NC_MAX_VAR_DIMS) { derror("%s has too many dimensions",vars[nvars].name); } if ($1->is_dim == 1) dimnum = $1->dnum; else { derror( "%s is not declared as a dimension", $1->name); dimnum = ndims; } if (rec_dim != -1 && dimnum == rec_dim && nvdims != 0) { derror("unlimited dimension must be first"); } grow_iarray(nvdims, /* must hold nvdims+1 ints */ &vars[nvars].dims); /* grow as needed */ vars[nvars].dims[nvdims] = dimnum; nvdims++; } ; attdecl: att { valnum = 0; valtype = NC_UNSPECIFIED; /* get a large block for attributes, realloc later */ att_space = emalloc(MAX_NC_ATTSIZE); /* make all kinds of pointers point to it */ char_valp = (char *) att_space; byte_valp = (signed char *) att_space; short_valp = (short *) att_space; int_valp = (int *) att_space; float_valp = (float *) att_space; double_valp = (double *) att_space; } '=' attvallist { { /* check if duplicate attribute for this var */ int i; for(i=0; iis_var == 1) varnum = $1->vnum; else { derror("%s not declared as a variable, fatal error", $1->name); YYABORT; } } ; attr: IDENT { /* make sure atts array will hold attributes */ grow_aarray(natts, /* must hold natts+1 atts */ &atts); /* grow as needed */ atts[natts].name = (char *) emalloc(strlen($1->name)+1); (void) strcpy(atts[natts].name,$1->name); /* name for use in generated Fortran and C variables */ atts[natts].lname = decodify($1->name); } ; attvallist: aconst | attvallist ',' aconst ; aconst: attconst { if (valtype == NC_UNSPECIFIED) valtype = atype_code; if (valtype != atype_code) derror("values for attribute must be all of same type"); } ; attconst: CHAR_CONST { atype_code = NC_CHAR; *char_valp++ = char_val; valnum++; } | TERMSTRING { atype_code = NC_CHAR; { /* don't null-terminate attribute strings */ size_t len = strlen(termstring); if (len == 0) /* need null if that's only value */ len = 1; (void)strncpy(char_valp,termstring,len); valnum += len; char_valp += len; } } | BYTE_CONST { atype_code = NC_BYTE; *byte_valp++ = byte_val; valnum++; } | SHORT_CONST { atype_code = NC_SHORT; *short_valp++ = short_val; valnum++; } | INT_CONST { atype_code = NC_INT; *int_valp++ = int_val; valnum++; } | FLOAT_CONST { atype_code = NC_FLOAT; *float_valp++ = float_val; valnum++; } | DOUBLE_CONST { atype_code = NC_DOUBLE; *double_valp++ = double_val; valnum++; } ; datasection: /* empty */ | DATA datadecls ; datadecls: datadecl ';' | datadecls datadecl ';' ; datadecl: avar { valtype = vars[varnum].type; /* variable type */ valnum = 0; /* values accumulated for variable */ vars[varnum].has_data = 1; /* compute dimensions product */ var_size = nctypesize(valtype); if (vars[varnum].ndims == 0) { /* scalar */ var_len = 1; } else if (vars[varnum].dims[0] == rec_dim) { var_len = 1; /* one record for unlimited vars */ } else { var_len = dims[vars[varnum].dims[0]].size; } for(dimnum = 1; dimnum < vars[varnum].ndims; dimnum++) var_len = var_len*dims[vars[varnum].dims[dimnum]].size; /* allocate memory for variable data */ if (var_len*var_size != (size_t)(var_len*var_size)) { derror("variable %s too large for memory", vars[varnum].name); exit(9); } rec_len = var_len; rec_start = malloc ((size_t)(rec_len*var_size)); if (rec_start == 0) { derror ("out of memory\n"); exit(3); } rec_cur = rec_start; switch (valtype) { case NC_CHAR: char_valp = (char *) rec_start; break; case NC_BYTE: byte_valp = (signed char *) rec_start; break; case NC_SHORT: short_valp = (short *) rec_start; break; case NC_INT: int_valp = (int *) rec_start; break; case NC_FLOAT: float_valp = (float *) rec_start; break; case NC_DOUBLE: double_valp = (double *) rec_start; break; } } '=' constlist { if (valnum < var_len) { /* leftovers */ nc_fill(valtype, var_len - valnum, rec_cur, vars[varnum].fill_value); } /* put out var_len values */ vars[varnum].nrecs = valnum / rec_len; if (derror_count == 0) put_variable(rec_start); free ((char *) rec_start); } ; constlist: dconst | constlist ',' dconst ; dconst: { if(valnum >= var_len) { if (vars[varnum].dims[0] != rec_dim) { /* not recvar */ derror("too many values for this variable, %d >= %d", valnum, var_len); exit (4); } else { /* a record variable, so grow data container and increment var_len by multiple of record size */ ptrdiff_t rec_inc = (char *)rec_cur - (char *)rec_start; var_len = rec_len * (1 + valnum / rec_len); rec_start = erealloc(rec_start, var_len*var_size); rec_cur = (char *)rec_start + rec_inc; char_valp = (char *) rec_cur; byte_valp = (signed char *) rec_cur; short_valp = (short *) rec_cur; int_valp = (int *) rec_cur; float_valp = (float *) rec_cur; double_valp = (double *) rec_cur; } } not_a_string = 1; } const { if (not_a_string) { switch (valtype) { case NC_CHAR: rec_cur = (void *) char_valp; break; case NC_BYTE: rec_cur = (void *) byte_valp; break; case NC_SHORT: rec_cur = (void *) short_valp; break; case NC_INT: rec_cur = (void *) int_valp; break; case NC_FLOAT: rec_cur = (void *) float_valp; break; case NC_DOUBLE: rec_cur = (void *) double_valp; break; } } } ; const: CHAR_CONST { atype_code = NC_CHAR; switch (valtype) { case NC_CHAR: *char_valp++ = char_val; break; case NC_BYTE: *byte_valp++ = char_val; break; case NC_SHORT: *short_valp++ = char_val; break; case NC_INT: *int_valp++ = char_val; break; case NC_FLOAT: *float_valp++ = char_val; break; case NC_DOUBLE: *double_valp++ = char_val; break; } valnum++; } | TERMSTRING { not_a_string = 0; atype_code = NC_CHAR; { size_t len = strlen(termstring); if(valnum + len > var_len) { if (vars[varnum].dims[0] != rec_dim) { derror("too many values for this variable, %d>%d", valnum+len, var_len); exit (5); } else {/* a record variable so grow it */ ptrdiff_t rec_inc = (char *)rec_cur - (char *)rec_start; var_len += rec_len * (len + valnum - var_len)/rec_len; rec_start = erealloc(rec_start, var_len*var_size); rec_cur = (char *)rec_start + rec_inc; char_valp = (char *) rec_cur; } } switch (valtype) { case NC_CHAR: { int ld; size_t i, sl; (void)strncpy(char_valp,termstring,len); ld = vars[varnum].ndims-1; if (ld > 0) {/* null-fill to size of last dim */ sl = dims[vars[varnum].dims[ld]].size; for (i =len;i next) if (STREQ(sp -> name, sname)) { return sp; } return 0; /* 0 ==> not found */ } YYSTYPE install( /* install sname in symbol table */ char *sname) { YYSTYPE sp; sp = (YYSTYPE) emalloc (sizeof (struct Symbol)); sp -> name = (char *) emalloc (strlen (sname) + 1);/* +1 for '\0' */ (void) strcpy (sp -> name, sname); sp -> next = symlist; /* put at front of list */ sp -> is_dim = 0; sp -> is_var = 0; sp -> is_att = 0; symlist = sp; return sp; } void clearout(void) /* reset symbol table to empty */ { YYSTYPE sp, tp; for (sp = symlist; sp != (YYSTYPE) 0;) { tp = sp -> next; free (sp -> name); free ((char *) sp); sp = tp; } symlist = 0; } minc-2.2.00/progs/mincgen/ncgenyy.l0000644000265600003100000001607212027132663014052 00000000000000%{ /********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Id: ncgenyy.l,v 1.3 2005-06-22 21:02:11 bert Exp $ *********************************************************************/ /* lex specification for tokens for ncgen */ /* Fill value used by ncdump from version 2.4 and later. Should match definition of FILL_STRING in ../ncdump/vardata.h */ #define FILL_STRING "_" #define XDR_INT_MIN (-2147483647-1) #define XDR_INT_MAX 2147483647 char errstr[100]; /* for short error messages */ #include #include #include #include "ncgen.h" #include "genlib.h" #include "ncgentab.h" extern int int_val; extern float float_val; #if !defined (YYSTYPE) && !defined(YYSTYPE_IS_DECLARED) extern void * yylval; #define YYLVAL_NULL ((void *) NULL) #else #define YYLVAL_NULL ((YYSTYPE) NULL) #endif /* YYSTYPE defined */ extern int lineno; extern signed char byte_val; extern short short_val; extern double double_val; extern char *netcdfname; extern char termstring[]; #define YY_BREAK /* defining as nothing eliminates unreachable statement warnings from flex output, but make sure every action ends with "return" or "break"! */ %} %p 6000 escaped \\. nonquotes ([^"\\]|{escaped})* exp ([eE][+-]?[0-9]+) %% \/\/.* { /* comment */ break; } \"{nonquotes}\" { if(yyleng > MAXTRST) { yyerror("string too long, truncated\n"); yytext[MAXTRST-1] = '\0'; } expand_escapes(termstring,(char *)yytext,yyleng); return (TERMSTRING); } float|FLOAT|real|REAL {return (FLOAT_K);} char|CHAR {return (CHAR_K);} byte|BYTE {return (BYTE_K);} short|SHORT {return (SHORT_K);} long|LONG|int|INT|integer|INTEGER {return (INT_K);} double|DOUBLE {return (DOUBLE_K);} unlimited|UNLIMITED {int_val = -1; return (NC_UNLIMITED_K);} dimensions:|DIMENSIONS: {return (DIMENSIONS);} variables:|VARIABLES: {return (VARIABLES);} data:|DATA: {return (DATA);} (netcdf|NETCDF|netCDF)[ \t]+[^\{]+ { char *s = (char*)yytext+strlen("netcdf"); char *t = (char*)yytext+yyleng-1; while (isspace(*s)) s++; while (isspace(*t)) t--; t++; if (t-s+1 < 1) { yyerror("netCDF name required"); return (DATA); /* generate syntax error */ } netcdfname = (char *) emalloc(t-s+1); (void) strncpy(netcdfname, s, t-s); netcdfname[t-s] = '\0'; return (NETCDF); } (hdf5|HDF5)[ \t]+[^\{]+ { char *s = (char*)yytext+strlen("hdf5"); char *t = (char*)yytext+yyleng-1; while (isspace(*s)) s++; while (isspace(*t)) t--; t++; if (t-s+1 < 1) { yyerror("HDF5 name required"); return (DATA); /* generate syntax error */ } netcdfname = (char *) emalloc(t-s+1); (void) strncpy(netcdfname, s, t-s); netcdfname[t-s] = '\0'; return (HDF5); } DoubleInf|NaN|-?Infinity { /* missing value (pre-2.4 backward compatibility) */ if (yytext[0] == '-') { double_val = -NC_FILL_DOUBLE; } else { double_val = NC_FILL_DOUBLE; } return (DOUBLE_CONST); } FloatInf|-?Inff { /* missing value (pre-2.4 backward compatibility) */ if (yytext[0] == '-') { float_val = -NC_FILL_FLOAT; } else { float_val = NC_FILL_FLOAT; } return (FLOAT_CONST); } [A-Za-z_][A-Z.@#\[\]a-z_0-9-]* { if (STREQ((char *)yytext, FILL_STRING)) return (FILLVALUE); if ((yylval = lookup((char *)yytext)) == YYLVAL_NULL) { yylval = install((char *)yytext); } return (IDENT); } \n { lineno++ ; break; } [+-]?[0-9]*[0-9][Bb] { int ii; if (sscanf((char*)yytext, "%d", &ii) != 1) { sprintf(errstr,"bad byte constant: %s",(char*)yytext); yyerror(errstr); } byte_val = ii; if (ii != (int)byte_val) { sprintf(errstr,"byte constant out of range (-128,127): %s",(char*)yytext); yyerror(errstr); } return (BYTE_CONST); } [+-]?[0-9]*\.[0-9]*{exp}?[LlDd]?|[+-]?[0-9]*{exp}[LlDd]? { if (sscanf((char*)yytext, "%le", &double_val) != 1) { sprintf(errstr,"bad long or double constant: %s",(char*)yytext); yyerror(errstr); } return (DOUBLE_CONST); } [+-]?[0-9]*\.[0-9]*{exp}?[Ff]|[+-]?[0-9]*{exp}[Ff] { if (sscanf((char*)yytext, "%e", &float_val) != 1) { sprintf(errstr,"bad float constant: %s",(char*)yytext); yyerror(errstr); } return (FLOAT_CONST); } [+-]?[0-9]+[sS]|0[xX][0-9a-fA-F]+[sS] { if (sscanf((char*)yytext, "%hd", &short_val) != 1) { sprintf(errstr,"bad short constant: %s",(char*)yytext); yyerror(errstr); } return (SHORT_CONST); } [+-]?([1-9][0-9]*|0)[lL]? { char *ptr; errno = 0; double_val = strtod((char*)yytext, &ptr); if (errno != 0 && double_val == 0.0) { sprintf(errstr,"bad numerical constant: %s",(char*)yytext); yyerror(errstr); } if (double_val < XDR_INT_MIN ||double_val > XDR_INT_MAX) { return DOUBLE_CONST; } else { int_val = (int) double_val; return INT_CONST; } } 0[xX]?[0-9a-fA-F]+[lL]? { char *ptr; long long_val; errno = 0; long_val = strtol((char*)yytext, &ptr, 0); if (errno != 0) { sprintf(errstr,"bad long constant: %s",(char*)yytext); yyerror(errstr); } if (long_val < XDR_INT_MIN || long_val > XDR_INT_MAX) { double_val = (double) long_val; return DOUBLE_CONST; } else { int_val = (int) long_val; return INT_CONST; } } \'[^\\]\' { (void) sscanf((char*)&yytext[1],"%c",&byte_val); return (BYTE_CONST); } \'\\[0-7][0-7]?[0-7]?\' { byte_val = (char) strtol((char*)&yytext[2], (char **) 0, 8); return (BYTE_CONST); } \'\\[xX][0-9a-fA-F][0-9a-fA-F]?\' { byte_val = (char) strtol((char*)&yytext[3], (char **) 0, 16); return (BYTE_CONST); } \'\\.\' { switch ((char)yytext[2]) { case 'a': byte_val = '\007'; break; /* not everyone under- * stands '\a' yet */ case 'b': byte_val = '\b'; break; case 'f': byte_val = '\f'; break; case 'n': byte_val = '\n'; break; case 'r': byte_val = '\r'; break; case 't': byte_val = '\t'; break; case 'v': byte_val = '\v'; break; case '\\': byte_val = '\\'; break; case '?': byte_val = '\177'; break; case '\'': byte_val = '\''; break; default: byte_val = (char)yytext[2]; } return (BYTE_CONST); } [ \t\f]+ { /* whitespace */ break; } . return (yytext[0]) ; minc-2.2.00/progs/mincheader/0000755000265600003100000000000012030114721012737 500000000000000minc-2.2.00/progs/mincheader/mincheader0000755000265600003100000000606412030075003014711 00000000000000#! /bin/sh # # Script to view header info of MINC files. # # Usage: mincheader [-data] # Exit status: status of `mincdump' # # # Modifications: # $Log: mincheader,v $ # Revision 6.4 2008-01-04 06:01:23 rotor # * updated shell scripting style and added more verbose help # # Revision 6.3 2004/04/27 15:32:58 bert # Use mincdump instead of ncdump # # Revision 6.2 2000/09/12 15:20:07 neelin # Rewrite in Bourne shell by Steve Robbins. Returns exit status from mincdump. # # Revision 6.1 1999/10/19 14:45:23 neelin # Fixed Log subsitutions for CVS # # Revision 6.0 1997/09/12 13:23:37 neelin # Release of minc version 0.6 # # Revision 5.0 1997/08/21 13:24:37 neelin # Release of minc version 0.5 # # Revision 4.0 1997/05/07 20:00:42 neelin # Release of minc version 0.4 # # Revision 3.0 1995/05/15 19:31:32 neelin # Release of minc version 0.3 # # Revision 2.2 1995/01/25 08:04:41 neelin # Added check for failure to read minc file. # # Revision 2.1 95/01/24 10:19:09 neelin # Added support for compressed files. # # Revision 2.0 94/09/28 10:34:10 neelin # Release of minc version 0.2 # # Revision 1.6 94/09/28 10:34:06 neelin # Pre-release # # Revision 1.5 93/10/14 10:09:35 neelin # Fixed usage error message. # # Revision 1.4 93/08/25 11:24:20 neelin # Added checking for -h or -help options. # # Revision 1.3 93/08/11 15:20:55 neelin # Added RCS logging in source. # set -o errexit set -o nounset # simple little function to emulate perl's die(); die () { echo >&2 "$@" echo "" exit 1 } # create tmpdir tmpdir=${TMPDIR:-/tmp}/mincedit.$$ trap 'rm -rf "$tmpdir"' 0 trap ' exit ' 1 2 15 (umask 077 && mkdir $tmpdir) || { echo "$0: Could not create temporary directory! Exiting." 1>&2 echo "" exit 1 } me=`basename $0` usage="Usage: $me [-data] " # set defaults and then get arguments header_opts='-header_only' header_only=yes while [ $# -gt 0 ] do case "$1" in -h|-he|-hel|-help) echo $usage; echo "" exit 0 ;; -d|-da|-dat|-data) header_opts='-all_data'; header_only=no ;; *) break; esac shift done # only allow one input file and check for it [ $# -eq 1 ] || die $usage [ -f "$1" ] || die "$me: no such file '$1'" tmpfile="$tmpdir/mincheader-$$-tmp" # For a compressed file, dump header only unless directed otherwise dumpfile=`mincexpand "$1" $tmpfile -name_only $header_opts` if [ "$dumpfile" = $tmpfile -a $header_only = yes ] then mincdump -h "$dumpfile" else # Get variables names (excluding image): remove leading "image", remove word # "image", collapse multiple blanks to one, remove leading blanks, remove # trailing blanks, replace blanks with commas vars=`mincinfo -varnames "$dumpfile" | \ sed -e 's/^image //g' \ -e 's/ image / /g' \ -e 's/ */ /g' \ -e 's/^ //' \ -e 's/ $//' \ -e 's/ /,/g'` [ x$vars = x ] || mincdump -v "$vars" "$dumpfile" fi minc-2.2.00/progs/mincheader/mincheader.man10000644000265600003100000000246312027132663015554 00000000000000.\" Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincheader/mincheader.man1,v 6.1 2004-05-20 21:52:08 bert Exp $ .\" .TH MINCHEADER 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincheader - prints out header information for a minc file .SH SYNOPSIS .B mincheader [-data] .SH DESCRIPTION \fIMincheader\fR prints out the header information for a minc file in cdl format (the netCDF text format). \fIMincheader\fR simply calls \fImincdump\fR, writing out all information except the image data. If the input file is compressed, then its header is decompressed and only the header is printed. If the \fB-data\fR option is given, then the whole file is decompressed and all data (except the image) is dumped. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 by Peter Neelin minc-2.2.00/progs/minchistory/0000755000265600003100000000000012030114721013210 500000000000000minc-2.2.00/progs/minchistory/minchistory.man10000644000265600003100000001264412030102322016257 00000000000000.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MINCHISTORY 1" .TH MINCHISTORY 1 "2012-09-24" "perl v5.10.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" \&\fBminchistory\fR \- prints history information for minc files .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBminchistory\fR [options] [ ... ] .PP minchistory will dump the internal history of one or more \s-1MINC\s0 files .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBminchistory\fR is a \fBperl\fR script that prints the history information in a collection of \s-1MINC\s0 files. Most \s-1MINC\s0 files contain an internal \*(L"audit trail\*(R" that lists the commands used to create the \&\s-1MINC\s0 file. This tool provides a convenient way to examine this information. .PP For each file, \fBminchistory\fR prints a title line followed by a series of lines which list the history information for that file. .PP .Vb 5 \& \-\-\- History of \-\-\- \& [01] Wed Oct 13 15:35:35 EST 2004>>>> dicom3_to_minc . \& [02] Wed Oct 13 15:43:34 2004>>> mincreshape +direction \e \& bob\-jones_256x256x256_T1.mnc out.mnc \-dimorder zspace,yspace,xspace \e \& \-clobber .Ve .PP \&\fBminchistory\fR is essentially an alias for the following command with a bit of pretty printing added. .PP .Vb 1 \& mincinfo \-attvalue :history B .Ve .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-v\fR, \fB\-\-verbose\fR" 4 .IX Item "-v, --verbose" Be noisy when doing things .IP "\fB\-\-version\fR" 4 .IX Item "--version" Print version number and exit .IP "\fB\-h\fR, \fB\-\-help\fR" 4 .IX Item "-h, --help" Dump some quick help output .IP "\fB\-\-man\fR" 4 .IX Item "--man" Dump a man page .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fImincinfo\fR\|(1) .SH "AUTHOR" .IX Header "AUTHOR" Andrew Janke \- a.janke@gmail.com .SH "COPYRIGHTS" .IX Header "COPYRIGHTS" Copyright 2000 by Andrew L Janke minc-2.2.00/progs/minchistory/minchistory.in0000755000265600003100000000767412027132663016064 00000000000000#! /usr/bin/env perl # # Simple script to dump history information from a minc file # # Copyright Andrew Janke a.janke@gmail.com # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies. The # author makes no representations about the suitability of this software # for any purpose. It is provided "as is" without express or implied warranty. my($n_columns) = 80; use strict; use warnings "all"; use Getopt::Long; use Pod::Usage; use Text::Format; use File::Basename; my($me, %opt, $cmd_text, $text, $fname, $counter, @tmp, $c); $me = &basename($0); %opt = ( 'help' => 0, 'man' => 0, 'verbose' => 0, 'error_string' => undef, ); # Check arguments &GetOptions( 'help|?' => \$opt{'help'}, 'man' => \$opt{'man'}, 'v|verbose' => \$opt{'verbose'}, 'version' => sub { &print_version_info }, 'e|error_string=s' => \$opt{'error_string'}, ) or pod2usage(-verbose => 1) && exit; # handle -man, -help or missing args pod2usage(-verbose => 1) if $opt{'help'}; pod2usage(-exitstatus => 0, -verbose => 2) if $opt{'man'}; pod2usage(-verbose => 0) && exit if ($#ARGV < 0); #$Usage = "Usage: $me [ ... ]\n\n"; #die $Usage if ($#ARGV < 0); # set up text objects $text = new Text::Format( firstIndent => 0, bodyIndent => 5, columns => $n_columns ); $cmd_text = new Text::Format( firstIndent => 0, bodyIndent => 5, columns => ($n_columns - 2) ); # for each input file foreach $fname (@ARGV){ if(!-e $fname){ warn "$me: Couldn't find $fname\n"; next; } print STDOUT $text->format("--- History of $fname ---\n"); $counter = 1; foreach (`mincinfo -attvalue :history "$fname"`){ chomp; next if $_ eq ''; # add the command number to the front $_ = sprintf("[%02d] ", $counter ++) . $_; # add \'s to the end of each line except the last @tmp = split(/\n/, $cmd_text->format($_)); for($c=0; $c<$#tmp; $c++){ print STDOUT "$tmp[$c] \\\n"; } print STDOUT "$tmp[$#tmp]\n"; } print STDOUT "\n"; } # print version information sub print_version_info { my $PACKAGE = '@PACKAGE_NAME@'; my $VERSION = '@PACKAGE_VERSION@'; my $PACKAGE_BUGREPORT = '@PACKAGE_BUGREPORT@'; print STDOUT "\n$PACKAGE version $VERSION\n". "Comments to $PACKAGE_BUGREPORT\n\n"; exit 0; } __END__ =head1 NAME B - prints history information for minc files =head1 SYNOPSIS B [options] [ ... ] minchistory will dump the internal history of one or more MINC files =head1 DESCRIPTION B is a B script that prints the history information in a collection of MINC files. Most MINC files contain an internal "audit trail" that lists the commands used to create the MINC file. This tool provides a convenient way to examine this information. For each file, B prints a title line followed by a series of lines which list the history information for that file. --- History of --- [01] Wed Oct 13 15:35:35 EST 2004>>>> dicom3_to_minc . [02] Wed Oct 13 15:43:34 2004>>> mincreshape +direction \ bob-jones_256x256x256_T1.mnc out.mnc -dimorder zspace,yspace,xspace \ -clobber B is essentially an alias for the following command with a bit of pretty printing added. mincinfo -attvalue :history B =head1 OPTIONS =over 4 =item B<-v>, B<--verbose> Be noisy when doing things =item B<--version> Print version number and exit =item B<-h>, B<--help> Dump some quick help output =item B<--man> Dump a man page =back =head1 SEE ALSO mincinfo(1) =head1 AUTHOR Andrew Janke - a.janke@gmail.com =head1 COPYRIGHTS Copyright 2000 by Andrew L Janke =cuts minc-2.2.00/progs/mincinfo/0000755000265600003100000000000012030114723012444 500000000000000minc-2.2.00/progs/mincinfo/mincinfo.man10000644000265600003100000001030412027132663014753 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincinfo/mincinfo.man1,v 6.3 2004-05-20 21:52:08 bert Exp $ .\" .TH MINCINFO 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincinfo \- print out specified information about a minc file .SH SYNOPSIS .B mincinfo [] [ ...] .SH DESCRIPTION \fImincinfo\fR will print out either a general description of a minc file (type, sign and range of data, plus a brief description of dimensions and their order), or specific information about dimensions, variables or attributes in the file. This program can be very useful for building shell scripts that access minc files. All information given by \fImincinfo\fR is presented as read from the file with no transformation. This means that start and step values, for example, are not in the world coordinate system. To display the start values for a file in world coordinates, use \fIvoxeltoworld\fR. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. Dimensions, variables and attributes are all specified by name. Attributes are specified by \fIvariable:attribute\fR where \fIvariable\fR can be omitted to specify global attributes. More than one option can be specified, in which case the return value from each option is printed on a separate line (\fB-image_info\fR prints on many lines) in the order of the options on the command line. .TP \fB\-image_info\fR Print out the default general information about the file. This information includes the type, sign and range of the pixel data, the order of the dimensions, and a list of dimensions giving name, length, start and step for each one. .TP \fB\-dimnames\fR Print out a space-separated list of the dimensions in the file. .TP \fB\-varnames\fR Print out a space-separated list of the variables in the file. .TP \fB\-dimlength\fR \fIdimension\fR Print the length of the specified dimension. .TP \fB\-vartype\fR \fIvariable\fR Print the type of the variable. .TP \fB\-vardims\fR \fIvariable\fR Print a space-separated list of the dimensions that subscript the variable (in C order). .TP \fB\-varatts\fR \fIvariable\fR Print a space-separated list of the attribute names for the specified variable. .TP \fB\-varvalues\fR \fIvariable\fR Print a newline-separated list of the values of the specified variable. .TP \fB\-atttype\fR \fIvariable:attribute\fR Print out the type of the specified attribute. .TP \fB\-attvalue\fR \fIvariable:attribute\fR Print out a space-separated list of the values of the specified attribute. .TP \fB\-error_string\fR \fIstring\fR Specifies a string to print out if an error occurs. This will cause the program to exit with normal status. The default is to print an appropriate error message and exit with an error status. .TP \fB\-help\fR Print summary of command-line options and abort. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES Print out standard information about a minc file. .IP mincinfo file.mnc .PP Print out contents of global history attribute. .IP mincinfo file.mnc -attvalue :history .PP Print out step value for x dimension, setting the default value to 1. .IP mincinfo file.mnc -attvalue xspace:step -error 1 .PP Print out the step values for x, y and z, setting the default value to 1. .IP mincinfo file.mnc -error 1 \\ -attvalue xspace:step \\ -attvalue yspace:step \\ -attvalue zspace:step .PP Print out the names of the dimensions subscripting the image variable. .IP mincinfo file.mnc -vardims image .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 by Peter Neelin .SH "SEE ALSO" .LP .BR voxeltoworld (1) minc-2.2.00/progs/mincinfo/mincinfo.c0000644000265600003100000005242012027132663014346 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincinfo @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to dump minc header information to standard output. @METHOD : @GLOBALS : @CALLS : @CREATED : May 19, 1993 (Peter Neelin) @MODIFIED : * $Log: mincinfo.c,v $ * Revision 6.13 2009-04-29 13:58:46 rotor * * fixed a stack smash in mincinfo.c * * Revision 6.12 2008/01/17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.11 2008/01/13 04:30:28 stever * Add braces around static initializers. * * Revision 6.10 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.9 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.8 2006/07/28 18:20:53 baghdadi * *** empty log message *** * * Revision 6.7 2006/07/28 17:51:01 baghdadi * Added option to print version of file * must use -minc_version -image_info * * Revision 6.6 2005/09/14 04:31:17 bert * include config.h * * Revision 6.5 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.4 2001/10/31 19:40:21 neelin * Fixed bug in printing of sign for default output - this was introduced * in the change to miget_datatype. * * Revision 6.3 2001/08/16 16:41:35 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.2 2000/04/25 18:12:05 neelin * Added modified version of patch from Steve Robbins to allow use on * multiple input files. * * Revision 6.1 1999/10/19 14:45:24 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:35 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:36 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:38 neelin * Release of minc version 0.4 * * Revision 3.1 1995/10/04 19:05:25 neelin * Fixed default_min for signed long. * * Revision 3.0 1995/05/15 19:31:31 neelin * Release of minc version 0.3 * * Revision 2.3 1995/02/08 19:31:47 neelin * Moved ARGSUSED statements for irix 5 lint. * * Revision 2.2 1995/02/01 15:29:31 neelin * Fixed call of miexpand_file. * * Revision 2.1 95/01/23 13:47:46 neelin * Changed ncopen, ncclose to miopen, miclose. Added miexpand_file to get * header only when appropriate. * * Revision 2.0 94/09/28 10:34:04 neelin * Release of minc version 0.2 * * Revision 1.10 94/09/28 10:34:00 neelin * Pre-release * * Revision 1.9 93/08/11 15:45:53 neelin * Functions called by ParseArgv must check that nextArg is not NULL. * * Revision 1.8 93/08/11 15:22:19 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define MAX_NUM_OPTIONS 100 /* Name of program, for error reporting */ static char* exec_name; static char *type_names[] = { NULL, "byte", "char", "short", "long", "float", "double" }; /* Types */ typedef enum { ENDLIST, IMAGE_INFO, DIMNAMES, VARNAMES, DIMLENGTH, VARTYPE, VARDIMS, VARATTS, VARVALUES, ATTTYPE, ATTVALUE, MINC_VERSION } Option_code; typedef struct { Option_code code; char *value; } Option_type; /* Macros */ #define REPORT_ERROR \ {int s;if ((s=report_error())!=EXIT_SUCCESS) return s; goto error_label;} #define CHK_ERR(code) if ((code) == MI_ERROR) {REPORT_ERROR} #define RTN_ERR(code) if ((code) == MI_ERROR) {return MI_ERROR;} /* Function prototypes */ static int process_file( char* filename, int header_only ); static int get_option(char *dst, char *key, char *nextarg); static int report_error(void); static int get_attname(int mincid, char *string, int *varid, char *name); static int print_image_info(char *filename, int mincid); /* Variables used for argument parsing */ static char *error_string = NULL; static Option_type option_list[MAX_NUM_OPTIONS] = { { ENDLIST, "" } }; static int length_option_list = 0; /* Argument table */ ArgvInfo argTable[] = { {"-image_info", ARGV_FUNC, (char *) get_option, (char *) IMAGE_INFO, "Print out the default information about the images."}, {"-dimnames", ARGV_FUNC, (char *) get_option, (char *) DIMNAMES, "Print the names of the dimensions in the file."}, {"-varnames", ARGV_FUNC, (char *) get_option, (char *) VARNAMES, "Print the names of the variables in the file."}, {"-dimlength", ARGV_FUNC, (char *) get_option, (char *) DIMLENGTH, "Print the length of the specified dimension."}, {"-vartype", ARGV_FUNC, (char *) get_option, (char *) VARTYPE, "Print the type of the specified variable."}, {"-vardims", ARGV_FUNC, (char *) get_option, (char *) VARDIMS, "Print the dimension names for the specified variable."}, {"-varatts", ARGV_FUNC, (char *) get_option, (char *) VARATTS, "Print the attribute names for the specified variable."}, {"-varvalues", ARGV_FUNC, (char *) get_option, (char *) VARVALUES, "Print the values for the specified variable."}, {"-atttype", ARGV_FUNC, (char *) get_option, (char *) ATTTYPE, "Print the type of the specified attribute (variable:attribute)."}, {"-attvalue", ARGV_FUNC, (char *) get_option, (char *) ATTVALUE, "Print the value(s) of the specified attribute (variable:attribute)."}, {"-error_string", ARGV_STRING, (char *) 0, (char *) &error_string, "Error to print on stdout (default = exit with error status)."}, {"-minc_version", ARGV_FUNC, (char *) get_option, (char *) MINC_VERSION, "Print the minc file version, netcdf or hdf5."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { int ioption, ifile, header_only; int ret_value = EXIT_SUCCESS; exec_name = argv[0]; /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) { (void) fprintf(stderr, "\nUsage: %s [] [ ...]\n", exec_name); (void) fprintf(stderr, " %s -help\n\n", exec_name); exit(EXIT_FAILURE); } /* Check for no print options */ if (option_list[0].code == ENDLIST) { option_list[0].code = IMAGE_INFO; option_list[0].value = NULL; length_option_list = 1; } /* Set error handling */ if (error_string == NULL) ncopts = NC_VERBOSE | NC_FATAL; else ncopts = 0; /* Loop through print options, checking whether we need variable data */ header_only = TRUE; for (ioption=0; ioption < length_option_list; ioption++) { if (option_list[ioption].code == VARVALUES) header_only = FALSE; } for (ifile=1; ifile < argc; ++ifile) { if (process_file( argv[ifile], header_only ) != EXIT_SUCCESS) ret_value = EXIT_FAILURE; if (argc > 2) printf("\n\n"); } return ret_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : print_image_version @INPUT : (boolean) @OUTPUT : (none) @RETURNS : Exit status. @DESCRIPTION: Prints out image netcdf or hdf5 @METHOD : @GLOBALS : @CALLS : @CREATED : Apr 6, 2005 (Leila Baghdadi) @MODIFIED : ---------------------------------------------------------------------------- */ static int print_image_version(int Is_MINC2_File) { if (Is_MINC2_File) { (void) printf("Version: 2 (HDF5)\n"); } else { (void) printf("Version: 1 (netCDF)\n"); } return EXIT_SUCCESS; } /* ----------------------------- MNI Header ----------------------------------- @NAME : process_file @INPUT : filename header_only - TRUE if only header needs to be expanded @OUTPUT : (none) @RETURNS : Exit value for program @DESCRIPTION: Runs mincinfo on one file @METHOD : (Adapted from old main of mincinfo.) @GLOBALS : @CALLS : @CREATED : April 25, 2000 (Steve Robbins) @MODIFIED : ---------------------------------------------------------------------------- */ static int process_file( char* filename, int header_only ) { int mincid, varid, dimid; int ndims, dims[MAX_VAR_DIMS]; nc_type datatype; long length, var_length, row_length; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; int att_length; int idim, iatt, natts, option; int nvars, ivar, ival; char *string; char name[MAX_NC_NAME]; char *cdata; double *ddata; int created_tempfile; char *tempfile; int Is_MINC2_File=0; /* Expand file */ tempfile = miexpand_file(filename, NULL, header_only, &created_tempfile); if (tempfile == NULL) { (void) fprintf(stderr, "%s: Error expanding file \"%s\"\n", exec_name, filename); return EXIT_FAILURE; } /* Open the file */ mincid = miopen(tempfile, NC_NOWRITE); if (created_tempfile) { (void) remove(tempfile); } if (mincid == MI_ERROR) { (void) fprintf(stderr, "%s: Error opening file \"%s\"\n", exec_name, tempfile); return EXIT_FAILURE; } /* check whether the file is Version 2 */ #ifdef MINC2 if (MI2_ISH5OBJ(mincid)) { Is_MINC2_File = 1; } #endif /* Loop through print options */ for (option=0; option < length_option_list; option++) { string = option_list[option].value; switch (option_list[option].code) { case IMAGE_INFO: CHK_ERR(print_image_info(filename, mincid)); break; case DIMNAMES: CHK_ERR(ncinquire(mincid, &ndims, NULL, NULL, NULL)); for (idim=0; idim= MAX_NUM_OPTIONS-1) { (void) fprintf(stderr, "Too many options - maximum is %d.\n", MAX_NUM_OPTIONS - 1); exit(EXIT_FAILURE); } /* Save option */ code = (Option_code) dst; option_list[length_option_list].code = code; if ((code == IMAGE_INFO) | (code == MINC_VERSION) || (code == DIMNAMES) || (code == VARNAMES)){ option_list[length_option_list].value = NULL; return_value = FALSE; } else { /* Check for following argument */ if (nextarg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); return FALSE; } option_list[length_option_list].value = nextarg; return_value = TRUE; } length_option_list++; option_list[length_option_list].code = ENDLIST; return return_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : report_error @INPUT : (none) @OUTPUT : (none) @RETURNS : Exit status. @DESCRIPTION: Prints out the error message @METHOD : @GLOBALS : @CALLS : @CREATED : May 19, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int report_error(void) { if (error_string == NULL) { (void) fprintf(stderr, "Error reading file.\n"); return EXIT_FAILURE; } else { (void) fprintf(stdout, "%s\n", error_string); return EXIT_SUCCESS; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_attname @INPUT : mincid - id of minc file string - string giving varname:attname @OUTPUT : varid - pointer to variale id name - name of attribute @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Gets variable id and attribute name from a string of the form "varname:attname" @METHOD : @GLOBALS : @CALLS : @CREATED : May 19, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_attname(int mincid, char *string, int *varid, char *name) { #define ATT_SEP_CHAR ':' char *attname, varname[MAX_NC_NAME]; int i; /* Get the variable name */ for (i=0; (i < MAX_NC_NAME) && (string[i] != ATT_SEP_CHAR) && (string[i] != '\0'); i++) { varname[i] = string[i]; } if (string[i] != ATT_SEP_CHAR) { if (error_string == NULL) { (void) fprintf(stderr, "Invalid attribute name '%s'\n", string); } return MI_ERROR; } varname[i] = '\0'; attname = &string[i+1]; /* Get varid and name */ if (varname[0] == '\0') { *varid = NC_GLOBAL; } else if ((*varid = ncvarid(mincid, varname)) == MI_ERROR) { return MI_ERROR; } (void) strncpy(name, attname, MAX_NC_NAME-1); name[MAX_NC_NAME-1] = '\0'; return MI_NOERROR; } /* ----------------------------- MNI Header ----------------------------------- @NAME : print_image_info @INPUT : mincid - id of minc file @OUTPUT : (none) @RETURNS : MI_ERROR if an error occurs @DESCRIPTION: Prints information about image data in file. @METHOD : @GLOBALS : @CALLS : @CREATED : May 19, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int print_image_info(char *filename, int mincid) { int imgid, ndims, dim[MAX_VAR_DIMS], varid; nc_type datatype; double valid_range[2]; char *sign_type[] = {MI_UNSIGNED, MI_SIGNED}; int sign_index; int is_signed; long length; int idim; char name[MAX_NC_NAME]; int oldncopts; double dim_start, dim_step; /* Get information about variable */ RTN_ERR(imgid = ncvarid(mincid, MIimage)); RTN_ERR(ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL)); RTN_ERR(miget_datatype(mincid, imgid, &datatype, &is_signed)); RTN_ERR(miget_valid_range(mincid, imgid, valid_range)); /* Get sign index */ sign_index = (is_signed ? 1 : 0); /* Write out image info line */ (void) printf("file: %s\n", filename); (void) printf("image: %s %s %.20g to %.20g\n", sign_type[sign_index], type_names[datatype], valid_range[0], valid_range[1]); /* Write out dimension names */ (void) printf("image dimensions:"); for (idim=0; idim] .mnc .mnc .SH DESCRIPTION \fIMinclookup\fR will perform a lookup table operation on each voxel of a minc file. A lookup table consists of a list of input values with matching output values. Each voxel of the input file is found in the lookup table and the corresponding output value is written out. These output values can be either scalar or vector values so, for example, a colour lookup table would have four columns: one column for input values and one column for each of red, green and blue output values. Lookup tables can take one of two forms: \fIcontinuous\fR or \fIdiscrete\fR. A continuous lookup table is for treating voxel values as continuous (real) values and converting values by doing interpolation between the values given in the lookup table. A discrete lookup table treats input values as integers and deals with them as completely independent entries, doing no interpolation. The most common use of continuous lookup tables is for converting intensity values into RGB colours. To make the lookup tables simpler, the input values are all rescaled into the range zero to one. By default, the smallest value in the file maps to zero and the largest maps to one. This value is then found in the lookup table, usually between two entries in the table (the table is always sorted in ascending order of input values). Linear interpolation is then done on each output column and the resultant value (or values) is written to the output file. If there is more than one output value per input value, then the dimension vector_dimension is added to the output file with length equal to the number of output columns in the lookup table. For input values outside the range zero to one, the nearest table value is used. Discrete lookup tables are usually used for remapping label values. Each input value is treated as an integer (it is not rescaled) and if it is found in the lookup table, then the corresponding value (or values) is written to the output file. If it is not found, then a null value is written out (zero by default). No interpolation is done with discrete lookup tables - to get a non-null output value, there must be an entry in the table. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create a MINC 2.0 format output file. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-no_clobber\fR Synonym for \fB-noclobber\fR. .TP \fB-verbose\fR Print out progress information for each chunk of data copied (default). .TP \fB\-quiet\fR Do not print out progress information. .TP \fB\-buffer_size\fR\ \fIsize\fR Specify the maximum size of the internal buffers (in kbytes). Default is 10 MB. .TP \fB\-filetype\fR Create an output file with the same type as the first input file (default). .TP \fB\-byte\fR Store each voxel as an 8-bit integer. .TP \fB\-short\fR Store each voxel as a 16-bit integer. .TP \fB\-int\fR Store each voxel as a 32-bit integer. .TP \fB\-long\fR Superseded by \fB\-int\fR. .TP \fB\-float\fR Store each voxel in 32-bit floating point format. .TP \fB-double\fR Store each voxel in 64-bit floating point format. .TP \fB\-signed\fR Create an output file with data stored in a signed type. This option is meaningless when used with floating point data formats, which are always signed. .TP \fB\-unsigned\fR Create an output file with data stored in an unsigned type. This option is meaningless when used with floating point data formats. .TP \fB\-valid_range\fR\ \fImin\ max\fR Scale integer voxel values to fall between the values \fImin\fR and \fImax\fR. By default integer voxel values will be scaled to use the entire range of the base type. This option is meaningless when used with floating point data formats. .SH Lookup table options .TP \fB\-gray\fR Use a gray lookup table to write out RGB values (default). .TP \fB\-grey\fR Synonym for \fB-gray\fR. .TP \fB\-hotmetal\fR Use a hot-metal lookup table to write out RGB values. .TP \fB\-spectral\fR Use a spectral (rainbow) lookup table to write out RGB values. .TP \fB\-invert\fR Invert the lookup table so that the maximum value maps to zero and the minimum value maps to one. Applies only to continuous lookup tables. .TP \fB\-noinvert\fR Do not invert the lookup table - the minimum maps to zero and the maximum maps to one (default). .TP \fB\-range\fR\ \fImin\ max\fR Specify the range of values that should map to the range of the lookup table (default is the full range of the input file). .TP \fB\-minimum\fR\ \fImin\fR Specify the input value that maps to the minimum value in the lookup table. .TP \fB\-maximum\fR\ \fImax\fR Specify the input value that maps to the maximum value in the lookup table. .TP \fB\-lookup_table\fR [\fIfile\fR | \fB-\fR] Specify the name of a file containing the lookup table. If \fB-\fR is given, the lookup table is read from the standard input. The file must have at least two columns: The first column gives the input values; the other columns give the corresponding output values. For a continuous lookup table, the first column should contain a value between zero and one inclusive Explicit entries for both zero and one should usually be given. For a discrete lookup table, the first column should contain integer values. If more than one output column is given, then the output file will have the dimension \fBvector_dimension\fR with a length equal to the number of output columns. The lines of the table will be sorted if necessary so that the first column is in ascending order. .TP \fB\-lut_string\fR\ \fIlookup-table-string\fR Specify the complete lookup table as a single string. The semicolon character ";" is used to separate lines. .TP \fB\-continuous\fR The lookup table is continuous (see description above): Input values are treated as continuous (real) values and are rescaled to the range zero to one before being looked up; interpolation is done between values in the table. This is the default behaviour. .TP \fB\-discrete\fR The lookup table is discrete (see description above): Input values are treated as integers and no interpolation is done between input values. .TP \fB\-null_value\fR\ \fInull-value-string\fR Specify a null value to be used with discrete lookup tables when a value is not found in the lookup table. This value must be specified as a comma-separated list of values, with the same number of values as output columns in the lookup table. .SH Generic options for all commands: .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES To get hot-metal RGB images from an MRI file: minclookup -hotmetal input.mnc output.mnc To convert the labels in a minc label file, use -discrete: minclookup -discrete -lookup_table lookupfile \\ in_labels.mnc out_labels.mnc where lookupfile is a file containing entries to map label 2 to 4 and label 3 to 5: 2 4 3 5 You could also specify this lookup table on the command line: minclookup -discrete -lut_string '2 4;3 5' \\ in_labels.mnc out_labels.mnc To get a grey RGB file, with red for values less than the minimum and green for values greater than the minimum, you can give two zero entries and two one entries. The first zero is used for negative values, the second zero is used for interpolation to the next entry. There is no ambiguity about how to handle a value of exactly zero because the first and last values of the table are handled in a special way to make sure that they are treated as within range if this sort of two-entry situation occurs. minclookup -lookup_table - input.mnc output.mnc < #include #include #include #include #include #include #include #include #include #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define DEFAULT_RANGE DBL_MAX #define NCOPTS_DEFAULT NC_VERBOSE | NC_FATAL /* Types */ typedef enum {LU_TABLE, LU_GRAY, LU_HOTMETAL, LU_SPECTRAL} Lookup_Type; /* Lookup table structure */ typedef struct { int nentries; int vector_length; double *table; int free_data; } Lookup_Table; /* Structure for lookup information */ typedef struct { Lookup_Table *lookup_table; double *null_value; int invert; int discrete; double range[2]; } Lookup_Data; /* Structure for sorting the lookup table */ typedef struct { double key; int index; } Sort_Key; /* Function prototypes */ static Lookup_Table *read_lookup_table(char *lookup_file, char *lookup_string); static double *get_values_from_string(char *string, int array_size, double *array, int *nread); static double *get_null_value(int vector_length, char *null_value_string); static void get_full_range(int mincid, double lookup_range[2]); static void do_lookup(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void lookup_in_table(double index, Lookup_Table *lookup_table, int discrete_values, double null_value[], double output_value[]); static char *get_next_line(char *line, int linelen, FILE *fp, char **string); static int sorting_function(const void *value1, const void *value2); /* Lookup tables */ static double gray_lookup_values[] = { 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 }; static Lookup_Table gray_lookup = { sizeof(gray_lookup_values)/sizeof(gray_lookup_values[0])/4, 3, gray_lookup_values, FALSE }; static double spectral_lookup_values[] = { 0.00, 0.0000,0.0000,0.0000, 0.05, 0.4667,0.0000,0.5333, 0.10, 0.5333,0.0000,0.6000, 0.15, 0.0000,0.0000,0.6667, 0.20, 0.0000,0.0000,0.8667, 0.25, 0.0000,0.4667,0.8667, 0.30, 0.0000,0.6000,0.8667, 0.35, 0.0000,0.6667,0.6667, 0.40, 0.0000,0.6667,0.5333, 0.45, 0.0000,0.6000,0.0000, 0.50, 0.0000,0.7333,0.0000, 0.55, 0.0000,0.8667,0.0000, 0.60, 0.0000,1.0000,0.0000, 0.65, 0.7333,1.0000,0.0000, 0.70, 0.9333,0.9333,0.0000, 0.75, 1.0000,0.8000,0.0000, 0.80, 1.0000,0.6000,0.0000, 0.85, 1.0000,0.0000,0.0000, 0.90, 0.8667,0.0000,0.0000, 0.95, 0.8000,0.0000,0.0000, 1.00, 0.8000,0.8000,0.8000 }; static Lookup_Table spectral_lookup = { sizeof(spectral_lookup_values)/sizeof(spectral_lookup_values[0])/4, 3, spectral_lookup_values, FALSE }; static double hotmetal_lookup_values[] = { 0.00, 0.0, 0.0, 0.0, 0.25, 0.5, 0.0, 0.0, 0.50, 1.0, 0.5, 0.0, 0.75, 1.0, 1.0, 0.5, 1.00, 1.0, 1.0, 1.0 }; static Lookup_Table hotmetal_lookup = { sizeof(hotmetal_lookup_values)/sizeof(hotmetal_lookup_values[0])/4, 3, hotmetal_lookup_values, FALSE }; /* Argument variables */ static int clobber = FALSE; static int verbose = TRUE; static nc_type datatype = MI_ORIGINAL_TYPE; static int is_signed = FALSE; static double valid_range[2] = {0.0, 0.0}; static int buffer_size = 10 * 1024; static char *lookup_file = NULL; static char *lookup_string = NULL; static Lookup_Type lookup_type = LU_GRAY; static int invert_table = FALSE; static double lookup_range[2] = {DEFAULT_RANGE, DEFAULT_RANGE}; static double lookup_min = DEFAULT_RANGE; static double lookup_max = DEFAULT_RANGE; static int discrete_lookup = FALSE; static char *null_value_string = NULL; #if MINC2 static int minc2_format = FALSE; #endif /* MINC2 */ /* Argument table */ ArgvInfo argTable[] = { #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &minc2_format, "Produce a MINC 2.0 format output file"}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages (default)."}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out log messages."}, {"-buffer_size", ARGV_INT, (char *) 1, (char *) &buffer_size, "Set the internal buffer size (in kb)."}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Use data type of first file (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Write out byte data."}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Write out short integer data."}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Write out 32-bit integer data."}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int."}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Write out single-precision floating-point data."}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Write out double-precision floating-point data."}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Write signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Write unsigned integer data (default if type specified)."}, {"-valid_range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data."}, {"-gray", ARGV_CONSTANT, (char *) LU_GRAY, (char *) &lookup_type, "Use a grayscale lookup table (default)."}, {"-grey", ARGV_CONSTANT, (char *) LU_GRAY, (char *) &lookup_type, "Use a grayscale lookup table."}, {"-hotmetal", ARGV_CONSTANT, (char *) LU_HOTMETAL, (char *) &lookup_type, "Use a hot metal lookup table."}, {"-spectral", ARGV_CONSTANT, (char *) LU_SPECTRAL, (char *) &lookup_type, "Use a spectral lookup table."}, {"-invert", ARGV_CONSTANT, (char *) TRUE, (char *) &invert_table, "Invert the lookup table (only applies to -continuous)."}, {"-noinvert", ARGV_CONSTANT, (char *) FALSE, (char *) &invert_table, "Don't invert the lookup table."}, {"-range", ARGV_FLOAT, (char *) 2, (char *) lookup_range, "Min and max for lookup table (default from file)."}, {"-minimum", ARGV_FLOAT, (char *) 1, (char *) &lookup_min, "Minimum for continuous lookup table."}, {"-maximum", ARGV_FLOAT, (char *) 1, (char *) &lookup_max, "Maximum for continuous lookup table."}, {"-lookup_table", ARGV_STRING, (char *) 1, (char *) &lookup_file, "File containing the lookup table (use - for stdin)."}, {"-lut_string", ARGV_STRING, (char *) 1, (char *) &lookup_string, "String containing the lookup table, with \";\" to separate lines."}, {"-discrete", ARGV_CONSTANT, (char *) TRUE, (char *) &discrete_lookup, "Lookup table has discrete (integer) entries - range is ignored."}, {"-continuous", ARGV_CONSTANT, (char *) FALSE, (char *) &discrete_lookup, "Lookup table is continuous from 0 to 1 (default)."}, {"-null_value", ARGV_STRING, (char *) 1, (char *) &null_value_string, "Specify a vector value for entries missing from a discrete lookup."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *infile, *outfile; char *arg_string; Loop_Options *loop_options; int inmincid; Lookup_Data lookup_data; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc != 3)) { (void) fprintf(stderr, "\nUsage: %s [options] \n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* Get the appropriate lookup table */ if ((lookup_file != NULL) || (lookup_string != NULL)) { lookup_data.lookup_table = read_lookup_table(lookup_file, lookup_string); } else { switch (lookup_type) { case LU_GRAY: lookup_data.lookup_table = &gray_lookup; break; case LU_HOTMETAL: lookup_data.lookup_table = &hotmetal_lookup; break; case LU_SPECTRAL: lookup_data.lookup_table = &spectral_lookup; break; } } /* Get the null value */ lookup_data.null_value = get_null_value(lookup_data.lookup_table->vector_length, null_value_string); /* Open the input file and get the range */ inmincid = miopen(infile, NC_NOWRITE); if (!discrete_lookup && (lookup_range[0] == DEFAULT_RANGE)) { get_full_range(inmincid, lookup_range); } if (lookup_min != DEFAULT_RANGE) lookup_range[0] = lookup_min; if (lookup_max != DEFAULT_RANGE) lookup_range[1] = lookup_max; /* Set up lookup information */ lookup_data.invert = invert_table; lookup_data.range[0] = lookup_range[0]; lookup_data.range[1] = lookup_range[1]; lookup_data.discrete = discrete_lookup; /* Set up looping options */ loop_options = create_loop_options(); set_loop_clobber(loop_options, clobber); set_loop_verbose(loop_options, verbose); #if MINC2 set_loop_v2format(loop_options, minc2_format); #endif /* MINC2 */ set_loop_datatype(loop_options, datatype, is_signed, valid_range[0], valid_range[1]); set_loop_convert_input_to_scalar(loop_options, TRUE); set_loop_output_vector_size(loop_options, lookup_data.lookup_table->vector_length); set_loop_buffer_size(loop_options, (long) buffer_size * 1024); set_loop_first_input_mincid(loop_options, inmincid); /* Do loop */ voxel_loop(1, &infile, 1, &outfile, arg_string, loop_options, do_lookup, (void *) &lookup_data); /* Free stuff */ if (lookup_data.null_value != NULL) free(lookup_data.null_value); if (lookup_data.lookup_table->free_data) { free(lookup_data.lookup_table->table); free(lookup_data.lookup_table); } exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_lookup_table @INPUT : lookup_filename - name of file from which to read lookup table ("-" means use stdin) lookup_string - string from which to read lookup table if lookup_filename is NULL @OUTPUT : (nothing) @RETURNS : Pointer to lookup table @DESCRIPTION: Routine to read in a lookup table from a file or stdin. If the filename is NULL, then data is read from the lookup_string. @METHOD : @GLOBALS : @CALLS : @CREATED : December 8, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static Lookup_Table *read_lookup_table(char *lookup_filename, char *lookup_string) { Lookup_Table *lookup_table; FILE *fp; double *table, *row, *new_table; int nentries, table_nvalues, nvalues, ivalue, ientry; char line[1000]; Sort_Key *sort_table; int need_sort; int old_offset, new_offset; char *lut_string; /* Check for null file name */ if ((lookup_filename == NULL) && (lookup_string == NULL)) return NULL; /* Open the file */ if (lookup_filename == NULL) { fp = NULL; } else if (strcmp(lookup_filename, "-") == 0) { fp = stdin; } else { fp = fopen(lookup_filename, "r"); if (fp == NULL) { (void) fprintf(stderr, "Unable to open lookup file \"%s\".\n", lookup_filename); exit(EXIT_FAILURE); } } /* Read in the table */ /* Read the first line and get the vector length from that*/ nentries = 0; lut_string = lookup_string; if (get_next_line(line, sizeof(line), fp, &lut_string) == NULL) { if (fp != NULL) (void) fprintf(stderr, "Lookup file %s is empty.\n", lookup_filename); else (void) fprintf(stderr, "Lookup string is empty.\n"); exit(EXIT_FAILURE); } row = get_values_from_string(line, 0, NULL, &table_nvalues); if (table_nvalues < 2) { (void) fprintf(stderr, "First line has fewer than 2 values.\n"); if (row != NULL) free(row); exit(EXIT_FAILURE); } table = malloc(sizeof(*table) * table_nvalues); for (ivalue=0; ivalue < table_nvalues; ivalue++) table[ivalue] = row[ivalue]; nentries++; need_sort = FALSE; while (get_next_line(line, sizeof(line), fp, &lut_string) != NULL) { (void) get_values_from_string(line, table_nvalues, row, &nvalues); if (nvalues != table_nvalues) { (void) fprintf(stderr, "Wrong number of values on line %d.\n", nentries+1); free(row); free(table); exit(EXIT_FAILURE); } table = realloc(table, sizeof(*table) * table_nvalues * (nentries+1)); for (ivalue=0; ivalue < table_nvalues; ivalue++) { table[ivalue + nentries*table_nvalues] = row[ivalue]; } nentries++; /* Check for need to sort */ if (table[(nentries-2)*table_nvalues] > table[(nentries-1)*table_nvalues]) { need_sort = TRUE; } } /* Close the input file */ if (fp != NULL) { (void) fclose(fp); } /* Do sorting if needed */ if (need_sort) { /* Set up sorting table */ sort_table = malloc(sizeof(*sort_table) * nentries); for (ientry=0; ientry < nentries; ientry++) { sort_table[ientry].key = table[ientry*table_nvalues]; sort_table[ientry].index = ientry; } /* Sort the sorting table */ qsort((void *) sort_table, nentries, sizeof(*sort_table), sorting_function); /* Copy the table */ new_table = malloc(sizeof(*table) * table_nvalues * nentries); for (ientry=0; ientry < nentries; ientry++) { new_offset = ientry * table_nvalues; old_offset = sort_table[ientry].index * table_nvalues; for (ivalue=0; ivalue < table_nvalues; ivalue++) { new_table[new_offset + ivalue] = table[old_offset + ivalue]; } } free(table); table = new_table; free(sort_table); } /* Allocate space for the lookup table and set initial values */ lookup_table = malloc(sizeof(*lookup_table)); lookup_table->free_data = TRUE; lookup_table->nentries = nentries; lookup_table->vector_length = table_nvalues - 1; lookup_table->table = table; /* Return the lookup table */ return lookup_table; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_next_line @INPUT : linelen - length of line to read in fp - file pointer or NULL if data should be read from a string string - pointer string containing data @OUTPUT : line - line that has been read in string - pointer is advanced to character following ";" @RETURNS : pointer to line or NULL if end of data occurs @DESCRIPTION: Routine to get the next line from a file or from a string that uses ";" as a line separator. @METHOD : @GLOBALS : @CALLS : @CREATED : July 10, 1996 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ #define LOOKUP_LINE_SEPARATOR ';' static char *get_next_line(char *line, int linelen, FILE *fp, char **string) { int count; /* Read from the file if appropriate */ if (fp != NULL) { return fgets(line, linelen, fp); } /* Otherwise search the string for the ";", copying characters */ else { /* Check for an empty string */ if (**string == '\0') return NULL; /* Loop over characters */ count = 0; while ((**string != '\0') && (**string != LOOKUP_LINE_SEPARATOR)) { if (count < linelen-1) { line[count] = **string; count++; } (*string)++; } /* Terminate the line and move past the ";" */ line[count] = '\0'; if (**string != '\0') (*string)++; /* Return the line */ return line; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : sorting_function @INPUT : value1 - pointer to first value value2 - pointer to second value @OUTPUT : (nothing) @RETURNS : -1, 0 or 1 for value1 <, ==, > value2 @DESCRIPTION: Routine to compare two values for sorting. The value is a pointer to a structure that has a double precision primary key. If that is equal then an integer secondary key is used. @METHOD : @GLOBALS : @CALLS : @CREATED : December 8, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int sorting_function(const void *value1, const void *value2) { Sort_Key *key1, *key2; key1 = (Sort_Key *) value1; key2 = (Sort_Key *) value2; if (key1->key == key2->key) { if (key1->index == key2->index) return 0; else if (key1->index < key2->index) return -1; else return 1; } else if (key1->key < key2->key) return -1; else return 1; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_values_from_string @INPUT : string - string containing values array_size - maximum number of values (<=0 means allocate a new array ) @OUTPUT : array - array into which values are written (can be NULL if array_size <= 0) nread - number of values read @RETURNS : Pointer to array of values @DESCRIPTION: Routine to convert a string to an array of values (floating point). If an existing array is passed in (array_size > 0), then up to array_size values are copied into it. Otherwise, a new array is created. Normally, the number of values read is returned - if an error occurs (non-numeric string for example), then zero is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : December 8, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static double *get_values_from_string(char *string, int array_size, double *array, int *nread) { #define VECTOR_SEPARATOR ',' char *cur, *prev, *end; int num_read, num_alloc; double dvalue; /* Set up variables */ num_read = 0; if (array_size <= 0) { num_alloc = 0; array = NULL; } else { num_alloc = array_size; } /* Skip leading white space */ end = string + strlen(string); cur = string; while (isspace(*cur)) cur++; /* Loop through string looking for doubles */ while (cur!=end) { /* Get double */ prev = cur; dvalue = strtod(prev, &cur); if (cur == prev) { *nread = 0; if (array_size <= 0 && array != NULL) { free(array); } return NULL; } /* Add the value to the list */ num_read++; if (num_read > num_alloc) { if (array_size <= 0) { num_alloc += 1; if (array == NULL) { array = malloc(num_alloc * sizeof(*array)); } else { array = realloc(array, num_alloc * sizeof(*array)); } } else { *nread = num_read; return array; } } array[num_read-1] = dvalue; /* Skip any spaces */ while (isspace(*cur)) cur++; /* Skip an optional comma */ if (*cur == VECTOR_SEPARATOR) cur++; } *nread = num_read; return array; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_null_value @INPUT : vector_length - desired vector length string - string from which we should get null values @OUTPUT : (nothing) @RETURNS : Pointer to array of values @DESCRIPTION: Routine to convert a string to an array of values to be used as a null value for the lookup table. Returns NULL if string is NULL @METHOD : @GLOBALS : @CALLS : @CREATED : December 8, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static double *get_null_value(int vector_length, char *string) { int num_read; double *values; /* Check for NULL string */ if (string == NULL) return NULL; /* Read values */ values = get_values_from_string(string, 0, NULL, &num_read); /* Check the number of values read */ if (num_read != vector_length) { if (values != NULL) free(values); (void) fprintf(stderr, "Null value does not match lookup table (%d values).\n", num_read); exit(EXIT_FAILURE); } return values; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_full_range @INPUT : mincid - id of the input minc file @OUTPUT : range - 2-value array giving real range of input values @RETURNS : (nothing) @DESCRIPTION: Routine to get the full real range of an input file. @METHOD : @GLOBALS : @CALLS : @CREATED : December 8, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_full_range(int mincid, double range[2]) { char *string; int varid; int ivar, idim, ndims; int dim[MAX_VAR_DIMS]; double sign, *extreme, *values; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS], num_values; long ivalue, length; /* Loop over image-min and image-max variables */ range[0] = 0.0; range[1] = 1.0; for (ivar=0; ivar < 2; ivar++) { if (ivar==0) { string = MIimagemin; sign = -1.0; extreme = &range[0]; } else { string = MIimagemax; sign = +1.0; extreme = &range[1]; } ncopts = 0; varid = ncvarid(mincid, string); ncopts = NCOPTS_DEFAULT; if (varid != MI_ERROR) { (void) ncvarinq(mincid, varid, NULL, NULL, &ndims, dim, NULL); num_values = 1; for (idim=0; idim < ndims; idim++) { (void) ncdiminq(mincid, dim[idim], NULL, &length); start[idim] = 0; count[idim] = length; num_values *= length; } if (num_values > 0) { values = malloc(num_values * sizeof(*values)); (void) mivarget(mincid, varid, start, count, NC_DOUBLE, NULL, values); *extreme = values[0]; for (ivalue=0; ivalue < num_values; ivalue++) { if ((values[ivalue] * sign) > (*extreme * sign)) *extreme = values[ivalue]; } free(values); } } /* If variable is found */ } /* Loop over image-min/max */ return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_lookup @INPUT : caller_data - pointer to structure containing lookup info num_voxels - number of voxels to work on input_num_buffers - number of input buffers input_vector_length - length of input vector dimension input_data - vector of pointers to input buffer data output_num_buffers - number of output buffers output_vector_length - length of output vector dimension start - vector specifying start of hyperslab (not used) count - vector specifying count of hyperslab (not used) @OUTPUT : output_data - vector of pointers to output buffer data @RETURNS : (nothing) @DESCRIPTION: Routine to loop through an array of voxels and do a lookup table conversion on them. @METHOD : @GLOBALS : @CALLS : @CREATED : December 8, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_lookup(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Lookup_Data *lookup_data; long ivoxel; double lookup_value, scale, offset, denom; /* Get pointer to lookup info */ lookup_data = (Lookup_Data *) caller_data; /* Check that values correspond */ if ((input_num_buffers != 1) || (output_num_buffers != 1) || (input_vector_length != 1) || (output_vector_length != lookup_data->lookup_table->vector_length)) { (void) fprintf(stderr, "Bad internal values.\n"); exit(EXIT_FAILURE); } /* Calculate a scale and offset for input values */ if (lookup_data->discrete) { scale = 1.0; offset = 0.0; } else { denom = (lookup_data->range[1] - lookup_data->range[0]); if (denom == 0.0) scale = 0.0; else scale = 1.0 / denom; if (!lookup_data->invert) { offset = -lookup_data->range[0] * scale; } else { scale = -scale; offset = -lookup_data->range[1] * scale; } } /* Loop through the voxels */ for (ivoxel=0; ivoxel < num_voxels; ivoxel++) { /* Convert input to a lookup value */ lookup_value = input_data[0][ivoxel] * scale + offset; /* Look it up */ lookup_in_table(lookup_value, lookup_data->lookup_table, lookup_data->discrete, lookup_data->null_value, &output_data[0][ivoxel*output_vector_length]); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : lookup_in_table @INPUT : index - value to look up in table lookup_table - the lookup table (big surprise!) discrete_values - flag indicating whether the table should be considered continuous in the range 0 to 1 (FALSE) or discrete, with integer values that should be rounded (TRUE). If the table is continuous, then interpolation between table entries is done (the first and last values propagate beyond the bounds). If the table is discrete, then the null_value is used for indices that are not found. null_value - array specifying the null values to use if the index is not found in the table. Only applies to discrete valued tables (may be NULL otherwise). @OUTPUT : output_value - vector of output values. @RETURNS : (nothing) @DESCRIPTION: Routine to look up a value in the table. @METHOD : @GLOBALS : @CALLS : @CREATED : December 8, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void lookup_in_table(double index, Lookup_Table *lookup_table, int discrete_values, double null_value[], double output_value[]) { int vector_length, nentries; int start, length, mid; int offset, offset1, offset2, ivalue; double value1, value2, *result, frac, rfrac, denom; /* Check for bad lookup table */ nentries = lookup_table->nentries; vector_length = lookup_table->vector_length; if ((nentries < 1) || (vector_length < 1)) { (void) fprintf(stderr, "Bad table size %d x %d\n", nentries, vector_length); exit(EXIT_FAILURE); } /* Round values if needed */ if (discrete_values) index = rint(index); /* Search the table for the value */ start = 0; length = nentries; while (length > 1) { mid = start + length / 2; offset = mid*(vector_length+1); if (index < lookup_table->table[offset]) { length = mid - start; } else { length = start + length - mid; start = mid; } } /* Add a special check for the end of the table */ if (nentries > 1) { offset1 = vector_length+1; offset2 = (nentries-2) * (vector_length+1); if ((start == 0) && (index == lookup_table->table[offset1])) start = 1; else if ((start == nentries-1) && (index == lookup_table->table[offset2])) start = nentries-2; } /* Save the value */ offset = start*(vector_length+1); if (discrete_values) { if (index == lookup_table->table[offset]) result = &lookup_table->table[offset+1]; else result = null_value; for (ivalue=0; ivalue < vector_length; ivalue++) { if (result != NULL) output_value[ivalue] = result[ivalue]; else output_value[ivalue] = 0.0; } } else { offset1 = offset; if (start < nentries - 1) offset2 = offset + vector_length + 1; else offset2 = offset; value1 = lookup_table->table[offset1]; value2 = lookup_table->table[offset2]; denom = value2 - value1; if (denom != 0.0) frac = (index - value1) / denom; else frac = 0.0; if (frac < 0.0) frac = 0.0; if (frac > 1.0) frac = 1.0; rfrac = 1.0 - frac; for (ivalue=0; ivalue < vector_length; ivalue++) { output_value[ivalue] = rfrac * lookup_table->table[offset1 + 1 + ivalue] + frac * lookup_table->table[offset2 + 1 + ivalue]; } } } minc-2.2.00/progs/mincmakescalar/0000755000265600003100000000000012030114723013614 500000000000000minc-2.2.00/progs/mincmakescalar/mincmakescalar.man10000644000265600003100000001164312027132663017302 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincmakescalar/mincmakescalar.man1,v 6.2 2004-05-20 21:52:08 bert Exp $ .\" .TH MINCMAKESCALAR 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincmakescalar - convert vector minc files to scalar .SH SYNOPSIS .B mincmakescalar [] .mnc .mnc .SH DESCRIPTION .I Mincmakescalar converts vector minc files to scalar minc files. A vector minc file is one that contains the dimension \fIvector_dimension\fR as the fastest varying dimension of the image data and represents vector data at each voxel such as RGB images or gradient volumes. A scalar minc file does not contain the vector dimension and represents grayscale or intensity data. A variety of conversion schemes are possible. The simplest is an average of the components of the vector. The magnitude of the vector at each voxel can also be computed. RGB volumes can be converted to greyscale by a standard linear combination. Finally, the user can supply a list of coefficients for a linear combination of vector components. Some options will require a specific number of components on the input vectors (RGB data should have 3 components and the number of coefficients supplied for the linear combination should match the number of components on the input vectors), but the program will also accept input scalar data and will copy it through without modification. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create a MINC 2.0 format output file. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-no_clobber\fR Synonym for \fB\-noclobber\fR. .TP \fB\-verbose\fR Print out progress information for each chunk of data copied (default). .TP \fB\-quiet\fR Do not print out progress information. .TP \fB-buffer_size\fR\ \fIsize\fR Specify the maximum size of the internal buffers (in kbytes). Default is 10 MB. .TP \fB\-filetype\fR Create an output file with the same type as the first input file (default). .TP \fB\-byte\fR Store output voxels as 8-bit integers. .TP \fB\-short\fR Store output voxels as 16-bit integers. .TP \fB\-int\fR Store output voxels as 32-bit integers .TP \fB\-long\fR Superseded by \fB\-int\fR. .TP \fB\-float\fR Store output voxels as 32-bit floating point numbers. .TP \fB\-double\fR Store output voxels as 64-bit floating point numbers. .TP \fB\-signed\fR Create an output file with data stored in a signed type. This only has an effect if the one of the \fB\-byte\fR, \fB\-short\fR or \fB\-int\fR options is specified. .TP \fB\-unsigned\fR Create an output file with data stored in an unsigned type. This only has an effect if the one of the \fB\-byte\fR, \fB\-short\fR or \fB\-int\fR options is specified. .TP \fB\-valid_range\fR\ \fImin\ max\fR Create an output file with integer data stored in the specified restricted range. This only has an effect if the one of the \fB\-byte\fR, \fB\-short\fR or \fB\-int\fR options is specified. .SH Conversion options .TP \fB\-magnitude\fR Compute the magnitude of each vector (default). .TP \fB\-average\fR Compute the average of the components of each vector. .TP \fB\-rgbtogrey\fR Convert RGB (3-component) files to greyscale using a linear combination with standard set of weighting coefficients. .TP \fB\-rgbtogray\fR Synonym for \fB\-rgbtogrey\fR. .TP \fB\-linear\fR\ \fIc1,c2,c3,...\fR Compute a linear combination of the components of each vector using the specified coefficients (these weights must be given as a comma or space-separated list of numbers in a single command-line argument). The number of coefficients must match the number of components on the input vectors. .SH Generic options for all commands: .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES To convert an RGB file to an grayscale file: mincmakescalar -rgbtogrey rgb.mnc gray.mnc To compute the gradient magnitude from a gradient volume mincmakescalar -magnitude gradient.mnc magnitude.mnc To convert an RGB file to a grayscale file using a different set of weighting factors for red, green and blue: mincmakescalar -linear '0.2,0.5,0.3' rgb.mnc gray.mnc .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1997 by Peter Neelin minc-2.2.00/progs/mincmakescalar/mincmakescalar.c0000644000265600003100000004272412027132663016674 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincmakescalar @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to make a scalar minc file from a vector minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : August 7, 1997 (Peter Neelin) @MODIFIED : * $Log: mincmakescalar.c,v $ * Revision 6.10 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.9 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.8 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.7 2005/08/26 21:07:17 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.6 2005/01/28 19:34:09 bert * Warn user if vector_dimension is not the last dimension in the image * * Revision 6.5 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.4 2004/04/27 15:32:33 bert * Added -2 option * * Revision 6.3 2001/04/24 13:38:43 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.2 2001/04/17 18:40:20 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:25 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:20 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:19 neelin * Release of minc version 0.5 * * Revision 1.2 1997/08/07 16:23:19 neelin * Change -length to -magnitude. * * Revision 1.1 1997/08/07 16:09:07 neelin * Initial revision * ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define DEFAULT_RANGE DBL_MAX #define NCOPTS_DEFAULT NC_VERBOSE | NC_FATAL #define INVALID_DATA (-DBL_MAX) /* Types */ typedef enum {CONV_DEFAULT, CONV_AVERAGE, CONV_MAGNITUDE, CONV_GREY, CONV_LINEAR} Conversion_Type; /* Double_Array structure */ typedef struct { int numvalues; double *values; } Double_Array; /* Structure for program info */ typedef struct { Conversion_Type conversion_type; int num_coefficients; double *linear_coefficients; } Program_Data; /* Function prototypes */ static void do_makescalar(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static int get_double_list(char *dst, char *key, char *nextarg); static long get_vector_length(int mincid); /* Argument variables */ static int clobber = FALSE; #if MINC2 static int v2format = FALSE; #endif /* MINC2 */ static int verbose = TRUE; static nc_type datatype = MI_ORIGINAL_TYPE; static int is_signed = FALSE; static double valid_range[2] = {0.0, 0.0}; static int buffer_size = 10 * 1024; static Conversion_Type conversion_type = CONV_DEFAULT; static Double_Array linear_coefficients = {0, NULL}; /* Argument table */ static ArgvInfo argTable[] = { #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &v2format, "Produce a MINC 2.0 format output file."}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages (default)."}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out log messages."}, {"-buffer_size", ARGV_INT, (char *) 1, (char *) &buffer_size, "Set the internal buffer size (in kb)."}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Use data type of first file (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Write out byte data."}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Write out short integer data."}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Write out 32-bit integer data."}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int."}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Write out single-precision floating-point data."}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Write out double-precision floating-point data."}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Write signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Write unsigned integer data (default if type specified)."}, {"-valid_range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data."}, {"-magnitude", ARGV_CONSTANT, (char *) CONV_MAGNITUDE, (char *) &conversion_type, "Compute magnitude of vectors (default)."}, {"-average", ARGV_CONSTANT, (char *) CONV_AVERAGE, (char *) &conversion_type, "Average components of vectors."}, {"-rgbtogrey", ARGV_CONSTANT, (char *) CONV_GREY, (char *) &conversion_type, "Convert RGB to greyscale."}, {"-rgbtogray", ARGV_CONSTANT, (char *) CONV_GREY, (char *) &conversion_type, "Synonym for rgbtogrey."}, {"-linear", ARGV_FUNC, (char *) get_double_list, (char *) &linear_coefficients, "Specify comma-separated list of coefficients for linear combination."}, {NULL, ARGV_END, NULL, NULL, NULL} }; static const char str_wrong_dimension_order[] = { "Your input file contains an image with a vector dimension, but the\n" "vector dimension isn't the last (i.e. fastest-varying) dimension in\n" "the image. Please restructure the file using mincreshape before\n" "attempting to use mincmakescalar.\n" }; /* Main program */ int main(int argc, char *argv[]) { char *infile, *outfile; char *arg_string; int inmincid; int input_vector_length; int ivalue; Loop_Options *loop_options; Program_Data program_data; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc != 3)) { (void) fprintf(stderr, "\nUsage: %s [options] \n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* Check for conflicting options */ if ((conversion_type != CONV_DEFAULT) && (linear_coefficients.numvalues > 0)) { (void) fprintf(stderr, "Do not specify -linear with other conversion options\n"); exit(EXIT_FAILURE); } /* Set up conversion information */ if (conversion_type == CONV_DEFAULT) conversion_type = CONV_MAGNITUDE; program_data.conversion_type = conversion_type; program_data.num_coefficients = 0; program_data.linear_coefficients = NULL; /* Check for coefficients for linear combination */ if (linear_coefficients.numvalues > 0) { conversion_type = CONV_LINEAR; program_data.conversion_type = conversion_type; program_data.num_coefficients = linear_coefficients.numvalues; program_data.linear_coefficients = malloc(linear_coefficients.numvalues * sizeof(*program_data.linear_coefficients)); for (ivalue=0; ivalue < linear_coefficients.numvalues; ivalue++) { program_data.linear_coefficients[ivalue] = linear_coefficients.values[ivalue]; } } /* Open the input file and get the vector length */ inmincid = miopen(infile, NC_NOWRITE); input_vector_length = get_vector_length(inmincid); if (input_vector_length < 0) { fprintf(stderr, str_wrong_dimension_order); exit(EXIT_FAILURE); } if (input_vector_length < 1) input_vector_length = 1; /* Check that this length is okay */ if ((conversion_type == CONV_GREY) && (input_vector_length != 3) && (input_vector_length > 1)) { (void) fprintf(stderr, "Input file does not contain RGB data\n"); exit(EXIT_FAILURE); } if ((conversion_type == CONV_LINEAR) && (input_vector_length != program_data.num_coefficients) && (input_vector_length > 1)) { (void) fprintf(stderr, "Input vector length does not match number of linear coefficients\n"); exit(EXIT_FAILURE); } /* Set up looping options */ loop_options = create_loop_options(); set_loop_clobber(loop_options, clobber); set_loop_verbose(loop_options, verbose); #if MINC2 set_loop_v2format(loop_options, v2format); #endif /* MINC2 */ set_loop_datatype(loop_options, datatype, is_signed, valid_range[0], valid_range[1]); set_loop_output_vector_size(loop_options, 1); set_loop_buffer_size(loop_options, (long) buffer_size * 1024); set_loop_first_input_mincid(loop_options, inmincid); /* Do loop */ voxel_loop(1, &infile, 1, &outfile, arg_string, loop_options, do_makescalar, (void *) &program_data); /* Free stuff */ if (program_data.linear_coefficients != NULL) { free(program_data.linear_coefficients); } if (linear_coefficients.values != NULL) { free(linear_coefficients.values); } exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_makescalar @INPUT : caller_data - pointer to structure containing lookup info num_voxels - number of voxels to work on input_num_buffers - number of input buffers input_vector_length - length of input vector dimension input_data - vector of pointers to input buffer data output_num_buffers - number of output buffers output_vector_length - length of output vector dimension start - vector specifying start of hyperslab (not used) count - vector specifying count of hyperslab (not used) @OUTPUT : output_data - vector of pointers to output buffer data @RETURNS : (nothing) @DESCRIPTION: Routine to loop through an array of vector values and convert them to scalar. @METHOD : @GLOBALS : @CALLS : @CREATED : August 7, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_makescalar(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Program_Data *program_data; long ivoxel; double *input_vector; double value, result; int ivalue; static double grey_coefficients[3] = {0.299, 0.587, 0.114}; /* Get pointer to lookup info */ program_data = (Program_Data *) caller_data; /* Check that values correspond */ if ((input_num_buffers != 1) || (output_num_buffers != 1) || (output_vector_length != 1)) { (void) fprintf(stderr, "Bad internal values.\n"); exit(EXIT_FAILURE); } if ((program_data->conversion_type == CONV_GREY) && (input_vector_length != 3)) { (void) fprintf(stderr, "Input must have three components for -grey conversion.\n"); exit(EXIT_FAILURE); } /* Loop through the voxels */ for (ivoxel=0; ivoxel < num_voxels; ivoxel++) { /* Handle the special case of scalar input */ if (input_vector_length <= 1) { output_data[0][ivoxel] = input_data[0][ivoxel]; continue; } /* Get location of input value */ input_vector = &input_data[0][ivoxel*input_vector_length]; /* Loop over components of vector */ result = 0.0; for (ivalue=0; ivalue < input_vector_length; ivalue++) { /* Get value and check for invalid values */ value = input_vector[ivalue]; if (value == INVALID_DATA) { result = INVALID_DATA; break; } /* Sum things up according to scheme */ switch (program_data->conversion_type) { case CONV_AVERAGE: result += value; break; case CONV_MAGNITUDE: result += value * value; break; case CONV_GREY: result += grey_coefficients[ivalue] * value; break; case CONV_LINEAR: result += program_data->linear_coefficients[ivalue] * value; break; } } /* End of loop over components */ /* Finish up the calculation */ if (result != INVALID_DATA) { switch (program_data->conversion_type) { case CONV_AVERAGE: result /= (double) input_vector_length; break; case CONV_MAGNITUDE: result = sqrt(result); break; } } /* Save the result */ output_data[0][ivoxel] = result; } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_double_list @INPUT : dst - client data passed by ParseArgv key - matching key in argv nextarg - argument following key in argv @OUTPUT : (none) @RETURNS : TRUE since nextarg is used. @DESCRIPTION: Gets a list (array) of double values. @METHOD : @GLOBALS : @CALLS : @CREATED : March 8, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_double_list(char *dst, char *key, char *nextarg) { #define VECTOR_SEPARATOR ',' int num_elements; int num_alloc; double *double_list; double dvalue; char *cur, *end, *prev; Double_Array *double_array; /* Check for a following argument */ if (nextarg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get pointers to array variables */ double_array = (Double_Array *) dst; /* Set up pointers to end of string and first non-space character */ end = nextarg + strlen(nextarg); cur = nextarg; while (isspace(*cur)) cur++; num_elements = 0; num_alloc = 0; double_list = NULL; /* Loop through string looking for doubles */ while (cur!=end) { /* Get double */ prev = cur; dvalue = strtod(prev, &cur); if (cur == prev) { (void) fprintf(stderr, "expected vector of doubles for \"%s\", but got \"%s\"\n", key, nextarg); exit(EXIT_FAILURE); } /* Add the value to the list */ num_elements++; if (num_elements > num_alloc) { num_alloc += 20; if (double_list == NULL) { double_list = malloc(num_alloc * sizeof(*double_list)); } else { double_list = realloc(double_list, num_alloc * sizeof(*double_list)); } } double_list[num_elements-1] = dvalue; /* Skip any spaces */ while (isspace(*cur)) cur++; /* Skip an optional comma */ if (*cur == VECTOR_SEPARATOR) cur++; } /* Update the global variables */ double_array->numvalues = num_elements; if (double_array->values != NULL) { free(double_array->values); } double_array->values = double_list; return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_vector_length @INPUT : mincid - minc file id @OUTPUT : (none) @RETURNS : Length of vector dimension or zero if no such dimension. @DESCRIPTION: Routine to get the length of the vector dimension in a minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static long get_vector_length(int mincid) { int imgid; int ndims; int dim[MAX_VAR_DIMS]; char dimname[MAX_NC_NAME]; long vector_length; int i; /* Get image variable id */ imgid = ncvarid(mincid, MIimage); /* Get the image dimension info */ (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Check for vector dimension */ (void) ncdiminq(mincid, dim[ndims-1], dimname, &vector_length); if ((strcmp(dimname, MIvector_dimension) != 0) || (ndims <= 2)) { vector_length = 0; /* New deal - check for an actual vector_dimension anywhere in the * file. */ for (i = 0; i < ndims; i++) { ncdiminq(mincid, dim[i], dimname, NULL); if (!strcmp(dimname, MIvector_dimension)) { vector_length = -1; break; } } } return vector_length; } minc-2.2.00/progs/mincmakevector/0000755000265600003100000000000012030114723013651 500000000000000minc-2.2.00/progs/mincmakevector/mincmakevector.man10000644000265600003100000000657512027132663017404 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincmakevector/mincmakevector.man1,v 6.2 2004-05-20 21:52:08 bert Exp $ .\" .TH MINCMAKEVECTOR 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincmakevector - convert a list of scalar minc files into one vector file .SH SYNOPSIS .B mincmakevector [] .mnc [...] .mnc .SH DESCRIPTION .I Mincmakevector converts a list of scalar minc files into one vector minc file. A vector minc file is one that contains the dimension \fIvector_dimension\fR as the fastest varying dimension of the image data and represents vector data at each voxel such as RGB images or gradient volumes. A scalar minc file does not contain the vector dimension and represents grayscale or intensity data. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create a MINC 2.0 format output file. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-no_clobber\fR Synonym for \fB\-noclobber\fR. .TP \fB\-verbose\fR Print out progress information for each chunk of data copied (default). .TP \fB\-quiet\fR Do not print out progress information. .TP \fB-buffer_size\fR\ \fIsize\fR Specify the maximum size of the internal buffers (in kbytes). Default is 10 MB. .TP \fB\-filetype\fR Create an output file with the same type as the first input file (default). .TP \fB\-byte\fR Store output voxels as 8-bit integers. .TP \fB\-short\fR Store output voxels as 16-bit integers. .TP \fB\-int\fR Store output voxels as 32-bit integers .TP \fB\-long\fR Superseded by \fB\-int\fR. .TP \fB\-float\fR Store output voxels as 32-bit floating point numbers. .TP \fB\-double\fR Store output voxels as 64-bit floating point numbers. .TP \fB\-signed\fR Create an output file with data stored in a signed type. This only has an effect if the one of the \fB\-byte\fR, \fB\-short\fR or \fB\-int\fR options is specified. .TP \fB\-unsigned\fR Create an output file with data stored in an unsigned type. This only has an effect if the one of the \fB\-byte\fR, \fB\-short\fR or \fB\-int\fR options is specified. .TP \fB\-valid_range\fR\ \fImin\ max\fR Create an output file with integer data stored in the specified restricted range. This only has an effect if the one of the \fB\-byte\fR, \fB\-short\fR or \fB\-int\fR options is specified. .SH Generic options for all commands: .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES To convert files containing red, green and blue colour components into an RGB file: mincmakevector red.mnc green.mnc blue.mnc rgb.mnc .SH AUTHOR Peter Neelin .SH COPYRIGHTS .ps 18 Copyright 1997 by Peter Neelin minc-2.2.00/progs/mincmakevector/mincmakevector.c0000644000265600003100000002347712027132663016772 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincmakevector @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to make a vector minc file from a series of scalar minc files. @METHOD : @GLOBALS : @CALLS : @CREATED : August 11, 1997 (Peter Neelin) @MODIFIED : * $Log: mincmakevector.c,v $ * Revision 6.10 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.9 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.8 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.7 2005/08/26 21:07:17 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.6 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.5 2004/04/30 19:53:30 bert * Remove unused variable * * Revision 6.4 2004/04/27 15:32:15 bert * Added -2 option * * Revision 6.3 2001/04/24 13:38:44 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.2 2001/04/17 18:40:21 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:25 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:31 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:32 neelin * Release of minc version 0.5 * * Revision 1.1 1997/08/12 19:03:46 neelin * Initial revision * ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define DEFAULT_RANGE DBL_MAX #define NCOPTS_DEFAULT NC_VERBOSE | NC_FATAL #define INVALID_DATA (-DBL_MAX) /* Structure for program info */ typedef struct { int dummy; } Program_Data; /* Function prototypes */ static void do_makevector(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static long get_vector_length(int mincid); /* Argument variables */ static int clobber = FALSE; static int verbose = TRUE; #if MINC2 static int v2format = FALSE; #endif /* MINC2 */ static nc_type datatype = MI_ORIGINAL_TYPE; static int is_signed = FALSE; static double valid_range[2] = {0.0, 0.0}; static int buffer_size = 10 * 1024; /* Argument table */ static ArgvInfo argTable[] = { #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &v2format, "Produce a MINC 2.0 format output file."}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages (default)."}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out log messages."}, {"-buffer_size", ARGV_INT, (char *) 1, (char *) &buffer_size, "Set the internal buffer size (in kb)."}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Use data type of first file (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Write out byte data."}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Write out short integer data."}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Write out 32-bit integer data."}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int."}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Write out single-precision floating-point data."}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Write out double-precision floating-point data."}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Write signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Write unsigned integer data (default if type specified)."}, {"-valid_range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char **input_files; char *output_file; char *arg_string; int num_input_files; int inmincid; Loop_Options *loop_options; Program_Data program_data; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc < 3)) { (void) fprintf(stderr, "\nUsage: %s [options] [...] \n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } input_files = &argv[1]; num_input_files = argc - 2; output_file = argv[argc-1]; /* Open the first input file and get the vector length */ inmincid = miopen(input_files[0], NC_NOWRITE); if (get_vector_length(inmincid) > 1) { (void) fprintf(stderr, "Input file %s is not a scalar file\n", input_files[0]); exit(EXIT_FAILURE); } /* Set up looping options */ loop_options = create_loop_options(); set_loop_clobber(loop_options, clobber); set_loop_verbose(loop_options, verbose); #if MINC2 set_loop_v2format(loop_options, v2format); #endif /* MINC2 */ set_loop_datatype(loop_options, datatype, is_signed, valid_range[0], valid_range[1]); set_loop_output_vector_size(loop_options, num_input_files); set_loop_buffer_size(loop_options, (long) buffer_size * 1024); set_loop_first_input_mincid(loop_options, inmincid); set_loop_accumulate(loop_options, TRUE, 0, NULL, NULL); /* Do loop */ voxel_loop(num_input_files, input_files, 1, &output_file, arg_string, loop_options, do_makevector, (void *) &program_data); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_makevector @INPUT : caller_data - pointer to structure containing lookup info num_voxels - number of voxels to work on input_num_buffers - number of input buffers input_vector_length - length of input vector dimension input_data - vector of pointers to input buffer data output_num_buffers - number of output buffers output_vector_length - length of output vector dimension start - vector specifying start of hyperslab (not used) count - vector specifying count of hyperslab (not used) @OUTPUT : output_data - vector of pointers to output buffer data @RETURNS : (nothing) @DESCRIPTION: Routine to copy values from scalar files into a vector. @METHOD : @GLOBALS : @CALLS : @CREATED : August 11, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_makevector(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { long ivoxel, ovoxel; int current_input_file; /* Check that values correspond */ if ((input_num_buffers != 1) || (output_num_buffers != 1) || (input_vector_length != 1)) { (void) fprintf(stderr, "Bad internal values.\n"); exit(EXIT_FAILURE); } /* Figure out which file we are looking at */ current_input_file = get_info_current_file(loop_info); /* Loop through the voxels */ for (ivoxel=0, ovoxel = current_input_file; ivoxel < num_voxels; ivoxel++, ovoxel += output_vector_length) { output_data[0][ovoxel] = input_data[0][ivoxel]; } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_vector_length @INPUT : mincid - minc file id @OUTPUT : (none) @RETURNS : Length of vector dimension or zero if no such dimension. @DESCRIPTION: Routine to get the length of the vector dimension in a minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : November 30, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static long get_vector_length(int mincid) { int imgid; int ndims; int dim[MAX_VAR_DIMS]; char dimname[MAX_NC_NAME]; long vector_length; /* Get image variable id */ imgid = ncvarid(mincid, MIimage); /* Get the image dimension info */ (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Check for vector dimension */ (void) ncdiminq(mincid, dim[ndims-1], dimname, &vector_length); if ((strcmp(dimname, MIvector_dimension) != 0) || (ndims <= 2)) { vector_length = 0; } return vector_length; } minc-2.2.00/progs/mincmath/0000755000265600003100000000000012030114723012442 500000000000000minc-2.2.00/progs/mincmath/mincmath.man10000644000265600003100000002236512027132663014761 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincmath/mincmath.man1,v 6.3 2004-05-20 21:52:08 bert Exp $ .\" .TH MINCMATH 1 "$Date: 2004-05-20 21:52:08 $" "" "MINC User's Guide" .SH NAME mincmath - perform simple math operations on minc files .SH SYNOPSIS .B mincmath [] .mnc [.mnc...] .mnc .SH DESCRIPTION \fIMincmath\fR will perform simple, voxel-by-voxel math operations, on one or more minc files of the same shape and having the same coordinate sampling, producing a single output file. Operations can be unary (operate on one file), binary (two input files) or cumulative (operate on two or more input files). Cumulative operations can also be performed across a specified dimension of the input files. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create a MINC 2.0 format output file. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-no_clobber\fR Synonym for \fB\-noclobber\fR. .TP \fB\-verbose\fR Print out progress information for each chunk of data copied (default). .TP \fB\-quiet\fR Do not print out progress information. .TP \fB\-debug\fR Print out debugging information. .TP \fB\-filelist\fR\ \fIfilename\fR Specify a file containing a list of input file names. If "-" is given, then file names are read from the standard input. If this option is given, then there should be no input file names specified on the command line. Empty lines in the input file are ignored. .TP \fB\-copy_header\fR Copy all of the header information from the first input file (default for one input file). .TP \fB\-nocopy_header\fR Do not copy all of the header from the first input file; copy only coordinate information (default for more than one input file). .TP \fB\-filetype\fR Create an output file with the same type as the first input file (default). .TP \fB\-byte\fR Store output voxels in 8-bit integer format. .TP \fB\-short\fR Store output voxels in 16-bit integer format. .TP \fB-int\fR Store output voxels in 32-bit integer format. .TP \fB-long\fR Superseded by \fB\-int\fR. .TP \fB-float\fR Store output voxels in 32-bit floating point format. .TP \fB-double\fR Store output voxels in 64-bit floating point format. .TP \fB\-signed\fR Use signed, two's complement integer format. Applies only if the output voxel type is specified to be an integer type (one of \fB\-byte\fR, \fB\-short\fR, \fB\-int\fR or \fB-long\fR). .TP \fB\-unsigned\fR Use unsigned integer format. Applies only if the output voxel type is specified to be an integer type (one of \fB\-byte\fR, \fB\-short\fR, \fB\-int\fR or \fB-long\fR). .TP \fB\-range\fR \fImin max\fR Restrict the valid range of integer data. Applies only if one of the \fB-byte\fR, \fB-short\fR, \fB-int\fR or \fB\-long\fR options is specified. .TP \fB\-max_buffer_size_in_kb\fR \fIsize\fR Specify the maximum size of the internal buffers (in kbytes). Default is 4096 (4MB). .TP \fB\-dimension\fR\ \fIdimname\fR Specify a dimension along which we wish to perform a cumulative operation. .TP \fB\-check_dimensions\fR Check that all input files have matching sampling in world dimensions (default). .TP \fB\-nocheck_dimensions\fR Ignore any differences in world dimensions sampling for input files . .TP \fB\-propagate_nan\fR Invalid data (Not-A-Number or NaN) at a voxel in any of the input files will produce invalid data in the output file at that voxel (default). .TP \fB\-ignore_nan\fR For cumulative operations, invalid data (NaN) in an input file is ignored, ie. treated as though it is not present. .TP \fB\-nan\fR When an illegal operation is attempted at a voxel (such as divide by zero), invalid data (NaN) is stored in the output file (default). Having no valid input data for a cumulative operation is also considered an illegal operation when \fB\-ignore_nan\fR is used. .TP \fB\-zero\fR When an illegal operation is attempted at a voxel (such as divide by zero), value zero is stored in the output file. .TP \fB\-illegal_value\fR\ \fIvalue\fR When an illegal operation is attempted at a voxel (such as divide by zero), the specified value is stored in the output file. .SH Options for specifying constants .TP \fB\-constant\fR\ \fIvalue\fR Specify a single constant. .TP \fB\-const\fR\ \fIvalue\fR Synonym for \fB\-constant\fR. .TP \fB\-const2\fR\ \fIvalue1 value2\fR Specify two constants. .SH Operations .TP \fB\-add\fR Cumulatively add two or more volumes, or add a volume and a constant. .TP \fB\-sub\fR Subtract two volumes or a volume minus a constant. .TP \fB\-mult\fR Cumulatively multiply two or more volumes, or multiply a volume and a constant. .TP \fB\-div\fR Divide two volumes or a volume divided by a constant. .TP \fB\-invert\fR Calculate 1/x at each voxel, where x is the input voxel value. If a constant c is specified (with -constant), then calculate c/x at each voxel. .TP \fB\-sqrt\fR Calculate the square root of a volume. .TP \fB\-square\fR Calculate the square of a volume. .TP \fB\-abs\fR Calculate the absolute value of a volume. .TP \fB\-maximum\fR Calculate the maximum of a series of volumes. .TP \fB\-minimum\fR Calculate the minimum of a series of volumes. .TP \fB\-exp\fR Calculate \fIc2*exp(c1*x)\fR at each voxel of a volume, where \fIx\fR is the voxel value and \fIc1\fR and \fIc2\fR are constants specified by \fB\-constant c1\fR or \fB\-const2 c1 c2\fR. The default value for these constants is 1.0. .TP \fB\-log\fR Calculate \fIlog(x/c2)/c1\fR for each voxel of a volume, where \fIx\fR is the voxel value and \fIc1\fR and \fIc2\fR are constants specified by \fB\-constant c1\fR or \fB\-const2 c1 c2\fR. The default value for these constants is 1.0. .TP \fB\-scale\fR Scale a volume either by multiplying by a single constant (use -constant) or by multiplying by the first constant and adding the second (use -const2). .TP \fB\-clamp\fR Clamp a volume to lie between two values specified with \fB-const2\fR. .TP \fB\-segment\fR Segment (binarize) a volume so that values within the range specified by \fB\-const2\fR give value 1 and those outside it give value 0. .TP \fB\-nsegment\fR Opposite of \fB\-segment\fR: values within the range specified by \fB\-const2\fR give value 0 and those outside it give value 1. .TP \fB\-percentdiff\fR Calculate the percent difference between two volumes (normalized to the first volume). If the first volume is less than a threshold (or zero), then the value specified by \fB\-nan\fR or \fB\-zero\fR is used. The threshold is specified using \fB\-constant\fR, with a default of zero. .TP \fB\-pd\fR Synonym for \fB\-percentdiff\fR. .TP \fB\-eq\fR Test for equality of two volumes or a volume and a constant. Values are rounded to the nearest integer before performing the test. Output 1 for true and 0 for false at each voxel. .TP \fB\-ne\fR Test for inequality of two volumes or a volume and a constant. Values are rounded to the nearest integer before performing the test. Output 1 for true and 0 for false at each voxel. .TP \fB\-gt\fR Test for volume 1 > volume 2 or a volume > a constant. Output 1 for true and 0 for false at each voxel. .TP \fB\-ge\fR Test for volume 1 >= volume 2 or a volume >= a constant. Output 1 for true and 0 for false at each voxel. .TP \fB\-lt\fR Test for volume 1 < volume 2 or a volume < a constant. Output 1 for true and 0 for false at each voxel. .TP \fB\-le\fR Test for volume 1 <= volume 2 or a volume <= a constant. Output 1 for true and 0 for false at each voxel. .TP \fB\-and\fR Test for volume 1 && volume 2 or a volume && a constant. Values are rounded to the nearest integer before performing the test. Output 1 for true and 0 for false at each voxel. .TP \fB\-or\fR Test for volume 1 || volume 2 or a volume || a constant. Values are rounded to the nearest integer before performing the test. Output 1 for true and 0 for false at each voxel. .TP \fB\-not\fR Perform logical negation on a volume: convert non-zero to zero and zero to one. Values are rounded to the nearest integer before the negation. .TP \fB\-isnan\fR Test a volume for invalid values (NaN). Output 1 for invalid values and 0 for valid values. .TP \fB\-nisnan\fR Opposite of -isnan. Output 0 for invalid values and 1 for valid values. .TP \fB\-count_valid\fR Count the number of valid voxels across a series of volumes. If none of the volumes has valid data, then zero is written out (ie. \fB\-zero\fR and \fB\-ignore_nan\fR are always assumed, unlike other cumulative operations). .SH Generic options for all commands: .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1995 by Peter Neelin .SH "SEE ALSO" .LP .BR minccalc (1) minc-2.2.00/progs/mincmath/mincmath.c0000644000265600003100000010410712027132663014342 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincmath @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to do simple math on minc files @METHOD : @GLOBALS : @CALLS : @CREATED : April 28, 1995 (Peter Neelin) @MODIFIED : * $Log: mincmath.c,v $ * Revision 6.15 2009-01-20 11:58:13 rotor * * CMakeLists.txt: updated version * * Updated Changelog to include releases * * Warning cleanups below * * conversion/dcm2mnc/minc_file.c: fixed printf type * * conversion/dcm2mnc/siemens_to_dicom.c: fixed printf type * * conversion/ecattominc/machine_indep.c: added string.h and fixed * 2 fprintf missing format args * * conversion/micropet/upet2mnc.c: fixed two fprintf format args * * conversion/minctoecat/ecat_write.c: added string.h * * conversion/minctoecat/minctoecat.c: added missing argument to fprintf * * conversion/nifti1/mnc2nii.c: fixed incorrect printf type * * progs/mincview/invert_raw_image.c: added fwrite checking * * Revision 6.14 2008/01/17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.13 2008/01/13 04:30:28 stever * Add braces around static initializers. * * Revision 6.12 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.11 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.10 2005/08/26 21:07:17 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.9 2004/12/14 23:40:07 bert * Get rid of c99 compilation problems * * Revision 6.8 2004/12/03 21:56:51 bert * Include config.h * * Revision 6.7 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.6 2004/04/27 15:31:45 bert * Added -2 option * * Revision 6.5 2001/04/24 13:38:44 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.4 2001/04/17 18:40:22 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.3 2001/01/15 14:58:43 neelin * Modified description of -segment option. * * Revision 6.2 2000/07/07 13:19:54 neelin * Added option -filelist to read file names from a file. This gets around * command-line length limits. * * Revision 6.1 1999/10/19 14:45:26 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:17 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:16 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:02:04 neelin * Release of minc version 0.4 * * Revision 3.5 1997/04/24 13:48:51 neelin * Fixed handling of invalid or uninitialized data for cumulative operations. * Added options -illegal_value and -count_valid. * * Revision 3.4 1997/04/23 19:34:56 neelin * Added options -maximum, -minimum, -abs. * * Revision 3.3 1996/01/17 21:24:06 neelin * Added -exp and -log options. * * Revision 3.2 1996/01/16 13:29:31 neelin * Added -invert option. * * Revision 3.1 1995/12/13 16:22:24 neelin * Added -check_dimensions and -nocheck_dimensions options. * * Revision 3.0 1995/05/15 19:32:42 neelin * Release of minc version 0.3 * * Revision 1.2 1995/05/03 16:13:46 neelin * Changed default for -copy/-nocopy to depend on number of input files. * * Revision 1.1 1995/05/03 13:19:56 neelin * Initial revision * ---------------------------------------------------------------------------- */ #define _GNU_SOURCE 1 #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "read_file_names.h" /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Data values for invalid data and for uninitialized data */ #define INVALID_DATA -DBL_MAX #define UNINITIALIZED_DATA DBL_MAX /* Values for representing default case for command-line options */ #define DEFAULT_DBL DBL_MAX #define DEFAULT_BOOL -1 /* Typedefs */ typedef enum { UNSPECIFIED_OP = 0, ADD_OP, SUB_OP, MULT_OP, DIV_OP, SQRT_OP, SQUARE_OP, SCALE_OP, CLAMP_OP, SEGMENT_OP, NSEGMENT_OP, PERCENTDIFF_OP, EQ_OP, NE_OP, GT_OP, GE_OP, LT_OP, LE_OP, AND_OP, OR_OP, NOT_OP, ISNAN_OP, NISNAN_OP, INVERT_OP, EXP_OP, LOG_OP, MAX_OP, MIN_OP, ABS_OP, COUNT_OP } Operation; typedef enum { ILLEGAL_NUMOP, UNARY_NUMOP, BINARY_NUMOP, NARY_NUMOP } Num_Operands; /* Table that matches [Operation][Number of constants (0,1,2)] to a number of volume operands */ Num_Operands OperandTable[][3] = { { ILLEGAL_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* UNSPECIFIED_OP */ { NARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* ADD_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* SUB_OP */ { NARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* MULT_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* DIV_OP */ { UNARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* SQRT_OP */ { UNARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* SQUARE_OP */ { ILLEGAL_NUMOP, UNARY_NUMOP, UNARY_NUMOP }, /* SCALE_OP */ { ILLEGAL_NUMOP, ILLEGAL_NUMOP, UNARY_NUMOP }, /* CLAMP_OP */ { ILLEGAL_NUMOP, ILLEGAL_NUMOP, UNARY_NUMOP }, /* SEGMENT_OP */ { ILLEGAL_NUMOP, ILLEGAL_NUMOP, UNARY_NUMOP }, /* NSEGMENT_OP */ { BINARY_NUMOP, BINARY_NUMOP, ILLEGAL_NUMOP }, /* PERCENTDIFF_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* EQ_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* NE_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* GT_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* GE_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* LT_OP */ { BINARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* LE_OP */ { NARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* AND_OP */ { NARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* OR_OP */ { UNARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* NOT_OP */ { UNARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* ISNAN_OP */ { UNARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* NISNAN_OP */ { UNARY_NUMOP, UNARY_NUMOP, ILLEGAL_NUMOP }, /* INVERT_OP */ { UNARY_NUMOP, UNARY_NUMOP, UNARY_NUMOP }, /* EXP_OP */ { UNARY_NUMOP, UNARY_NUMOP, UNARY_NUMOP }, /* LOG_OP */ { NARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* MAX_OP */ { NARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* MIN_OP */ { UNARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* ABS_OP */ { NARY_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP }, /* COUNT_OP */ { ILLEGAL_NUMOP, ILLEGAL_NUMOP, ILLEGAL_NUMOP } /* nothing */ }; /* Structure for window information */ typedef struct { Operation operation; Num_Operands num_operands; int num_constants; double constants[2]; int propagate_nan; double illegal_value; } Math_Data; /* Function prototypes */ static void do_math(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void accum_math(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void start_math(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); static void end_math(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); /* Argument variables */ static int clobber = FALSE; static int verbose = TRUE; static int debug = FALSE; static nc_type datatype = MI_ORIGINAL_TYPE; static int is_signed = FALSE; static double valid_range[2] = {0.0, 0.0}; static int copy_all_header = DEFAULT_BOOL; static char *loop_dimension = NULL; static int max_buffer_size_in_kb = 4 * 1024; static double constant = DEFAULT_DBL; static double constant2[2] = {DEFAULT_DBL, DEFAULT_DBL}; static Operation operation = UNSPECIFIED_OP; static int propagate_nan = TRUE; static int use_nan_for_illegal_values = TRUE; static double value_for_illegal_operations = DEFAULT_DBL; static int check_dim_info = TRUE; static char *filelist = NULL; #if MINC2 static int minc2_format = FALSE; #endif /* MINC2 */ /* Argument table */ static ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "General options:"}, #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &minc2_format, "Produce a MINC 2.0 format output file"}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-no_clobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Synonym for -noclobber."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages (default)."}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out log messages."}, {"-debug", ARGV_CONSTANT, (char *) TRUE, (char *) &debug, "Print out debugging messages."}, {"-filelist", ARGV_STRING, (char *) 1, (char *) &filelist, "Specify the name of a file containing input file names (- for stdin)."}, {"-copy_header", ARGV_CONSTANT, (char *) TRUE, (char *) ©_all_header, "Copy all of the header from the first file."}, {"-nocopy_header", ARGV_CONSTANT, (char *) FALSE, (char *) ©_all_header, "Do not copy all of the header from the first file."}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Use data type of first file (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Write out byte data."}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Write out short integer data."}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Write out 32-bit integer data."}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int."}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Write out single-precision floating-point data."}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Write out double-precision floating-point data."}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Write signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Write unsigned integer data (default if type specified)."}, {"-range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data."}, {"-max_buffer_size_in_kb", ARGV_INT, (char *) 1, (char *) &max_buffer_size_in_kb, "Specify the maximum size of the internal buffers (in kbytes)."}, {"-dimension", ARGV_STRING, (char *) 1, (char *) &loop_dimension, "Specify a dimension along which we wish to perform a calculation."}, {"-check_dimensions", ARGV_CONSTANT, (char *) TRUE, (char *) &check_dim_info, "Check that files have matching dimensions (default)."}, {"-nocheck_dimensions", ARGV_CONSTANT, (char *) FALSE, (char *) &check_dim_info, "Do not check that files have matching dimensions."}, {"-ignore_nan", ARGV_CONSTANT, (char *) FALSE, (char *) &propagate_nan, "Ignore invalid data (NaN) for accumulations."}, {"-propagate_nan", ARGV_CONSTANT, (char *) TRUE, (char *) &propagate_nan, "Invalid data in any file at a voxel produces a NaN (default)."}, {"-nan", ARGV_CONSTANT, (char *) TRUE, (char *) &use_nan_for_illegal_values, "Output NaN when an illegal operation is done (default)."}, {"-zero", ARGV_CONSTANT, (char *) FALSE, (char *) &use_nan_for_illegal_values, "Output zero when an illegal operation is done."}, {"-illegal_value", ARGV_FLOAT, (char *) 1, (char *) &value_for_illegal_operations, "Value to write out when an illegal operation is done."}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Options for specifying constants:"}, {"-constant", ARGV_FLOAT, (char *) 1, (char *) &constant, "Specify a constant argument."}, {"-const", ARGV_FLOAT, (char *) 1, (char *) &constant, "Synonym for -constant."}, {"-const2", ARGV_FLOAT, (char *) 2, (char *) constant2, "Specify two constant arguments."}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Operations:"}, {"-add", ARGV_CONSTANT, (char *) ADD_OP, (char *) &operation, "Add N volumes or volume + constant."}, {"-sub", ARGV_CONSTANT, (char *) SUB_OP, (char *) &operation, "Subtract 2 volumes or volume - constant."}, {"-mult", ARGV_CONSTANT, (char *) MULT_OP, (char *) &operation, "Multiply N volumes or volume * constant."}, {"-div", ARGV_CONSTANT, (char *) DIV_OP, (char *) &operation, "Divide 2 volumes or volume / constant."}, {"-invert", ARGV_CONSTANT, (char *) INVERT_OP, (char *) &operation, "Calculate 1/x at each voxel (use -constant for c/x)."}, {"-sqrt", ARGV_CONSTANT, (char *) SQRT_OP, (char *) &operation, "Take square root of a volume."}, {"-square", ARGV_CONSTANT, (char *) SQUARE_OP, (char *) &operation, "Take square of a volume."}, {"-abs", ARGV_CONSTANT, (char *) ABS_OP, (char *) &operation, "Take absolute value of a volume."}, {"-max", ARGV_CONSTANT, (char *) MAX_OP, (char *) &operation, "Synonym for -maximum."}, {"-maximum", ARGV_CONSTANT, (char *) MAX_OP, (char *) &operation, "Find maximum of N volumes."}, {"-minimum", ARGV_CONSTANT, (char *) MIN_OP, (char *) &operation, "Find minimum of N volumes."}, {"-exp", ARGV_CONSTANT, (char *) EXP_OP, (char *) &operation, "Calculate c2*exp(c1*x). The constants c1 and c2 default to 1."}, {"-log", ARGV_CONSTANT, (char *) LOG_OP, (char *) &operation, "Calculate log(x/c2)/c1. The constants c1 and c2 default to 1."}, {"-scale", ARGV_CONSTANT, (char *) SCALE_OP, (char *) &operation, "Scale a volume: volume * c1 + c2."}, {"-clamp", ARGV_CONSTANT, (char *) CLAMP_OP, (char *) &operation, "Clamp a volume to lie between two values."}, {"-segment", ARGV_CONSTANT, (char *) SEGMENT_OP, (char *) &operation, "Segment a volume using range of -const2: within range = 1, outside range = 0."}, {"-nsegment", ARGV_CONSTANT, (char *) NSEGMENT_OP, (char *) &operation, "Opposite of -segment: within range = 0, outside range = 1."}, {"-percentdiff", ARGV_CONSTANT, (char *) PERCENTDIFF_OP, (char *) &operation, "Percent difference between 2 volumes, thresholded (const def=0.0)."}, {"-pd", ARGV_CONSTANT, (char *) PERCENTDIFF_OP, (char *) &operation, "Synonym for -percentdiff."}, {"-eq", ARGV_CONSTANT, (char *) EQ_OP, (char *) &operation, "Test for integer vol1 == vol2 or vol1 == const."}, {"-ne", ARGV_CONSTANT, (char *) NE_OP, (char *) &operation, "Test for integer vol1 != vol2 or vol1 != const."}, {"-gt", ARGV_CONSTANT, (char *) GT_OP, (char *) &operation, "Test for vol1 > vol2 or vol1 > const."}, {"-ge", ARGV_CONSTANT, (char *) GE_OP, (char *) &operation, "Test for vol1 >= vol2 or vol1 >= const."}, {"-lt", ARGV_CONSTANT, (char *) LT_OP, (char *) &operation, "Test for vol1 < vol2 or vol1 < const."}, {"-le", ARGV_CONSTANT, (char *) LE_OP, (char *) &operation, "Test for vol1 <= vol2 or vol1 <= const."}, {"-and", ARGV_CONSTANT, (char *) AND_OP, (char *) &operation, "Calculate vol1 && vol2 (&& ...)."}, {"-or", ARGV_CONSTANT, (char *) OR_OP, (char *) &operation, "Calculate vol1 || vol2 (|| ...)."}, {"-not", ARGV_CONSTANT, (char *) NOT_OP, (char *) &operation, "Calculate !vol1."}, {"-isnan", ARGV_CONSTANT, (char *) ISNAN_OP, (char *) &operation, "Test for NaN values in vol1."}, {"-nisnan", ARGV_CONSTANT, (char *) NISNAN_OP, (char *) &operation, "Negation of -isnan."}, {"-count_valid", ARGV_CONSTANT, (char *) COUNT_OP, (char *) &operation, "Count the number of valid values in N volumes."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char **infiles, **outfiles; int nfiles, nout; char *arg_string; Math_Data math_data; Loop_Options *loop_options; char *pname; int num_constants; Num_Operands num_operands; VoxelFunction math_function; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ pname = argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) { (void) fprintf(stderr, "\nUsage: %s [options] [ ...] \n", pname); (void) fprintf(stderr, " %s -help\n\n", pname); exit(EXIT_FAILURE); } nout = 1; outfiles = &argv[argc-1]; /* Get the list of input files either from the command line or from a file, or report an error if both are specified */ nfiles = argc - 2; if (filelist == NULL) { infiles = &argv[1]; } else if (nfiles <= 0) { infiles = read_file_names(filelist, &nfiles); if (infiles == NULL) { (void) fprintf(stderr, "Error reading in file names from file \"%s\"\n", filelist); exit(EXIT_FAILURE); } } else { (void) fprintf(stderr, "Do not specify both -filelist and input file names\n"); exit(EXIT_FAILURE); } /* Make sure that we have something to process */ if (nfiles == 0) { (void) fprintf(stderr, "No input files specified\n"); exit(EXIT_FAILURE); } /* Handle special case of COUNT_OP - it always assume -ignore_nan and -zero */ if (operation == COUNT_OP) { propagate_nan = FALSE; value_for_illegal_operations = 0.0; } /* Check that the arguments make sense */ if ((constant != DEFAULT_DBL) && (constant2[0] != DEFAULT_DBL)) { (void) fprintf(stderr, "%s: Specify only one of -constant or -const2\n", pname); exit(EXIT_FAILURE); } if (constant != DEFAULT_DBL) num_constants = 1; else if (constant2[0] != DEFAULT_DBL) num_constants = 2; else num_constants = 0; num_operands = OperandTable[operation][num_constants]; if (num_operands == ILLEGAL_NUMOP) { (void) fprintf(stderr, "%s: Operation and constants do not match.\n", pname); exit(EXIT_FAILURE); } if ((num_operands != NARY_NUMOP) && (loop_dimension != NULL)) { (void) fprintf(stderr, "%s: Use -dimension only for cumulative ops.\n", pname); exit(EXIT_FAILURE); } if ((num_operands == UNARY_NUMOP) && (nfiles != 1)) { (void) fprintf(stderr, "%s: Expected only one input file.\n", pname); exit(EXIT_FAILURE); } if ((num_operands == BINARY_NUMOP) && (nfiles != 2)) { (void) fprintf(stderr, "%s: Expected two input files.\n", pname); exit(EXIT_FAILURE); } if ((num_operands == NARY_NUMOP) && (nfiles < 1) && (loop_dimension == NULL)) { (void) fprintf(stderr, "%s: Expected at least one input files.\n", pname); exit(EXIT_FAILURE); } /* Set default copy_all_header according to number of input files */ if (copy_all_header == DEFAULT_BOOL) copy_all_header = (nfiles == 1); /* Set up math data structure */ math_data.operation = operation; math_data.num_operands = num_operands; math_data.propagate_nan = propagate_nan; math_data.num_constants = num_constants; switch (num_constants) { case 1: math_data.constants[0] = constant; break; case 2: math_data.constants[0] = constant2[0]; math_data.constants[1] = constant2[1]; break; } if (value_for_illegal_operations != DEFAULT_DBL) math_data.illegal_value = value_for_illegal_operations; else if (use_nan_for_illegal_values) math_data.illegal_value = INVALID_DATA; else math_data.illegal_value = 0.0; /* Do math */ loop_options = create_loop_options(); set_loop_verbose(loop_options, verbose); set_loop_clobber(loop_options, clobber); #if MINC2 set_loop_v2format(loop_options, minc2_format); #endif /* MINC2 */ set_loop_datatype(loop_options, datatype, is_signed, valid_range[0], valid_range[1]); if (num_operands == NARY_NUMOP) { math_function = accum_math; set_loop_accumulate(loop_options, TRUE, 0, start_math, end_math); } else { math_function = do_math; } set_loop_copy_all_header(loop_options, copy_all_header); set_loop_dimension(loop_options, loop_dimension); set_loop_buffer_size(loop_options, (long) 1024 * max_buffer_size_in_kb); set_loop_check_dim_info(loop_options, check_dim_info); voxel_loop(nfiles, infiles, nout, outfiles, arg_string, loop_options, math_function, (void *) &math_data); free_loop_options(loop_options); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_math @INPUT : Standard for voxel loop @OUTPUT : Standard for voxel loop @RETURNS : (nothing) @DESCRIPTION: Routine doing math operations. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_math(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Math_Data *math_data; long ivox; double value1, value2; double illegal_value; Operation operation; int num_constants, iconst; double constants[2]; /* Get pointer to window info */ math_data = (Math_Data *) caller_data; /* Check arguments */ if ((input_num_buffers > 2) || (output_num_buffers != 1) || (output_vector_length != input_vector_length)) { (void) fprintf(stderr, "Bad arguments to do_math!\n"); exit(EXIT_FAILURE); } /* Get info */ operation = math_data->operation; num_constants = math_data->num_constants; for (iconst=0; iconst < sizeof(constants)/sizeof(constants[0]); iconst++) { if (iconst < num_constants) constants[iconst] = math_data->constants[iconst]; else if ((operation == INVERT_OP) || (operation == EXP_OP) || (operation == LOG_OP)) constants[iconst] = 1.0; else constants[iconst] = 0.0; } illegal_value = math_data->illegal_value; /* Set default second value */ value2 = constants[0]; /* Loop through the voxels */ for (ivox=0; ivox < num_voxels*input_vector_length; ivox++) { value1 = input_data[0][ivox]; if (input_num_buffers == 2) value2 = input_data[1][ivox]; if ((value1 == INVALID_DATA) || (value2 == INVALID_DATA)) { switch(operation) { case ISNAN_OP: output_data[0][ivox] = 1.0; break; case NISNAN_OP: output_data[0][ivox] = 0.0; break; default: output_data[0][ivox] = INVALID_DATA; break; } } else { switch (operation) { case ADD_OP: output_data[0][ivox] = value1 + value2; break; case SUB_OP: output_data[0][ivox] = value1 - value2; break; case MULT_OP: output_data[0][ivox] = value1 * value2; break; case DIV_OP: if (value2 != 0.0) output_data[0][ivox] = value1 / value2; else output_data[0][ivox] = illegal_value; break; case INVERT_OP: if (value1 == 0.0) output_data[0][ivox] = illegal_value; else output_data[0][ivox] = value2 / value1; break; case SQRT_OP: if (value1 < 0.0) output_data[0][ivox] = illegal_value; else output_data[0][ivox] = sqrt(value1); break; case SQUARE_OP: output_data[0][ivox] = value1 * value1; break; case ABS_OP: if (value1 < 0.0) output_data[0][ivox] = -value1; else output_data[0][ivox] = value1; break; case EXP_OP: output_data[0][ivox] = constants[1] * exp(value1 * constants[0]); break; case LOG_OP: if ((value1 <= 0.0) || (constants[1] <= 0.0) || (constants[0] == 0.0)) output_data[0][ivox] = illegal_value; else output_data[0][ivox] = log(value1/constants[1])/constants[0]; break; case SCALE_OP: output_data[0][ivox] = value1 * constants[0] + constants[1]; break; case CLAMP_OP: if (value1 < constants[0]) value1 = constants[0]; else if (value1 > constants[1]) value1 = constants[1]; output_data[0][ivox] = value1; break; case SEGMENT_OP: if ((value1 < constants[0]) || (value1 > constants[1])) output_data[0][ivox] = 0.0; else output_data[0][ivox] = 1.0; break; case NSEGMENT_OP: if ((value1 < constants[0]) || (value1 > constants[1])) output_data[0][ivox] = 1.0; else output_data[0][ivox] = 0.0; break; case PERCENTDIFF_OP: if ((value1 < constants[0]) || (value1 == 0.0)) output_data[0][ivox] = illegal_value; else { output_data[0][ivox] = 100.0 * (value1 - value2) / value1; } break; case EQ_OP: output_data[0][ivox] = (((rint(value1)-rint(value2)) == 0.0) ? 1.0 : 0.0); break; case NE_OP: output_data[0][ivox] = (((rint(value1)-rint(value2)) != 0.0) ? 1.0 : 0.0); break; case GT_OP: output_data[0][ivox] = value1 > value2; break; case GE_OP: output_data[0][ivox] = value1 >= value2; break; case LT_OP: output_data[0][ivox] = value1 < value2; break; case LE_OP: output_data[0][ivox] = value1 <= value2; break; case AND_OP: output_data[0][ivox] = (((rint(value1) != 0.0) && (rint(value2) != 0.0)) ? 1.0 : 0.0); break; case OR_OP: output_data[0][ivox] = (((rint(value1) != 0.0) || (rint(value2) != 0.0)) ? 1.0 : 0.0); break; case NOT_OP: output_data[0][ivox] = ((rint(value1) == 0.0) ? 1.0 : 0.0); break; case ISNAN_OP: output_data[0][ivox] = 0.0; /* To get here, value is not nan */ break; case NISNAN_OP: output_data[0][ivox] = 1.0; break; default: (void) fprintf(stderr, "Bad op in do_math!\n"); exit(EXIT_FAILURE); } } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : accum_math @INPUT : Standard for voxel loop @OUTPUT : Standard for voxel loop @RETURNS : (nothing) @DESCRIPTION: Routine for doing accumulation math operations. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void accum_math(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Math_Data *math_data; long ivox; double value, oldvalue; Operation operation; int propagate_nan; /* Get pointer to window info */ math_data = (Math_Data *) caller_data; /* Check arguments */ if ((input_num_buffers != 1) || (output_num_buffers != 1) || (output_vector_length != input_vector_length)) { (void) fprintf(stderr, "Bad arguments to accum_math!\n"); exit(EXIT_FAILURE); } /* Get info */ operation = math_data->operation; propagate_nan = math_data->propagate_nan; /* Loop through the voxels */ for (ivox=0; ivox < num_voxels*input_vector_length; ivox++) { /* Get previous value and the next value */ oldvalue = output_data[0][ivox]; value = input_data[0][ivox]; /* If the new data is invalid, then either mark the output as invalid or ignore it */ if (value == INVALID_DATA) { if (propagate_nan) { output_data[0][ivox] = INVALID_DATA; } } /* If we haven't set anything yet, then just copy the new value */ else if (oldvalue == UNINITIALIZED_DATA) { output_data[0][ivox] = input_data[0][ivox]; } /* Do the operation if the old data and the new data are valid */ else if (oldvalue != INVALID_DATA) { switch (operation) { case ADD_OP: output_data[0][ivox] = oldvalue + value; break; case MULT_OP: output_data[0][ivox] = oldvalue * value; break; case AND_OP: output_data[0][ivox] = (((oldvalue != 0.0) && (rint(value) != 0.0)) ? 1.0 : 0.0); break; case OR_OP: output_data[0][ivox] = (((oldvalue != 0.0) || (rint(value) != 0.0)) ? 1.0 : 0.0); break; case MAX_OP: if (value > oldvalue) output_data[0][ivox] = value; break; case MIN_OP: if (value < oldvalue) output_data[0][ivox] = value; break; case COUNT_OP: output_data[0][ivox]++; break; default: (void) fprintf(stderr, "Bad op in accum_math!\n"); exit(EXIT_FAILURE); } } } /* Loop over voxels */ return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : start_math @INPUT : Standard for voxel loop @OUTPUT : Standard for voxel loop @RETURNS : (nothing) @DESCRIPTION: Start routine for math accumulation. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void start_math(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Math_Data *math_data; long ivox; /* Get pointer to window info */ math_data = (Math_Data *) caller_data; /* Check arguments */ if (output_num_buffers != 1) { (void) fprintf(stderr, "Bad arguments to start_math!\n"); exit(EXIT_FAILURE); } /* Get info */ operation = math_data->operation; /* Loop through the voxels, marking them all as uninitialized. We treat COUNT_OP as a special case since it always has a value. This is especially important to prevent it from going through the code in accum_math for handling the first valid voxel which just assigns the first value. */ for (ivox=0; ivox < num_voxels*output_vector_length; ivox++) { switch (operation) { case COUNT_OP: output_data[0][ivox] = 0.0; break; default: output_data[0][ivox] = UNINITIALIZED_DATA; break; } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : end_math @INPUT : Standard for voxel loop @OUTPUT : Standard for voxel loop @RETURNS : (nothing) @DESCRIPTION: Start routine for math accumulation. @METHOD : @GLOBALS : @CALLS : @CREATED : April 25, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void end_math(void *caller_data, long num_voxels, int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Math_Data *math_data; long ivox; double value; double illegal_value; /* Get pointer to window info */ math_data = (Math_Data *) caller_data; /* Check arguments */ if (output_num_buffers != 1) { (void) fprintf(stderr, "Bad arguments to end_math!\n"); exit(EXIT_FAILURE); } /* Get info */ operation = math_data->operation; illegal_value = math_data->illegal_value; /* Loop through the voxels, checking for uninitialized values */ for (ivox=0; ivox < num_voxels*output_vector_length; ivox++) { value = output_data[0][ivox]; if ((value == UNINITIALIZED_DATA) || (value == INVALID_DATA)) { output_data[0][ivox] = illegal_value; } } return; } minc-2.2.00/progs/minc_modify_header/0000755000265600003100000000000012030114723014447 500000000000000minc-2.2.00/progs/minc_modify_header/minc_modify_header.man10000644000265600003100000000743112027132662020767 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/minc_modify_header/minc_modify_header.man1,v 6.4 2004-05-25 21:33:11 bert Exp $ .\" .TH MINC_MODIFY_HEADER 1 "$Date: 2004-05-25 21:33:11 $" "" "MINC User's Guide" .SH NAME minc_modify_header - modify the attributes in the header of a minc file .SH SYNOPSIS .B minc_modify_header [] .mnc .SH DESCRIPTION \fIMinc_modify_header\fR allows the modification, insertion or deletion of attributes in a minc file. If possible, the file is modified in place, without copying the data. This will happen when inserting (modifying) an attribute that already exists and that ends up being the same length or shorter in the new file. If an attribute is deleted or lengthened, then a complete copy of the data is made, resulting in a completely new file that replaces the original. If the file is compressed, then it is first decompressed into a file whose name is either the same as that of the original file up to the ".mnc" extension or the same minus the compression extension (".bz", ".bz2", ".gz", ".Z", ".z" or ".zip"). The new file will not be re-compressed. Care is taken to completely overwrite any existing attribute when inserting a new attribute so that information is guaranteed to be removed from the file. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .TP \fB\-sinsert\fR \fIvar:attr=value\fR Insert a string attribute into the header. If the attribute does not exist or the new string is longer than the existing one, then all data in the file will be copied. .TP \fB\-sappend\fR \fIvar:attr=value\fR Similar to \fB\-sinsert\fR, but appends the string to the attribute's value. If the attribute already exists it must be of string type. .TP \fB\-dinsert\fR \fIvar:attr=value(,...)\fR Insert a double precision attribute into the header. If the attribute does not exist or the new attribute is longer than the existing one, then all data in the file will be copied. A comma-separated array of values can be specified. .TP \fB\-dappend\fR \fIvar:attr=value(,...)\fR Similar to \fB\-dinsert\fR, but appends the list of double precision values to the attribute's value. If the attribute already exists it must be of double precision type. .TP \fB-delete\fR \fIvar:attr\fR Delete an attribute from the header. USE OF THIS OPTION WILL FORCE A COMPLETE COPY OF ALL DATA TO BE MADE. Use \fB-sinsert\fR with an empty string to delete information without copying data (the attribute will continue to exist). .TP \fB-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES: .PP To replace the patient name with an identifier string: .IP minc_modify_header file.mnc -sinsert 'patient:full_name=C02-F0023' .PP To delete the patient name completely (forcing a copy of all data): .IP minc_modify_header file.mnc -delete 'patient:full_name' .PP To hide the patient name without copying data, assuming that we know that the attribute exists (the attribute will remain in the file, but it will be empty): .IP minc_modify_header file.mnc -sinsert 'patient:full_name=' .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1995 by Peter Neelin minc-2.2.00/progs/minc_modify_header/minc_modify_header.c0000644000265600003100000004261212027132662020355 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_modify_header @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : error status @DESCRIPTION: Modifies the header of a minc file, in place if possible. @METHOD : @GLOBALS : @CALLS : @CREATED : March 31, 1995 (Peter Neelin) @MODIFIED : * $Log: minc_modify_header.c,v $ * Revision 6.13 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.12 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.11 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.10 2004/11/01 22:38:38 bert * Eliminate all references to minc_def.h * * Revision 6.9 2004/06/11 15:19:34 bert * Fix attribute append operation * * Revision 6.8 2004/05/25 21:33:51 bert * Add -dappend and -sappend * * Revision 6.7 2004/02/02 18:27:06 bert * Include config.h * * Revision 6.6 2003/11/14 16:52:24 stever * More last-minute fixes. * * Revision 6.5 2001/04/17 18:40:16 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.4 2000/12/13 16:19:37 neelin * Removed debugging statements * * Revision 6.3 2000/11/03 16:35:40 neelin * Modified -dinsert option to allow multiple double values to be * inserted in an attribute. * * Revision 6.2 2000/09/13 14:12:35 neelin * Added support for bzipped files (thanks to Steve Robbins). * * Revision 6.1 1999/10/19 14:45:17 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:07 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:06 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:35 neelin * Release of minc version 0.4 * * Revision 3.1 1995/11/16 13:16:19 neelin * Added include of math.h to get declaration of strtod under SunOs * * Revision 3.0 1995/05/15 19:32:21 neelin * Release of minc version 0.3 * * Revision 1.2 1995/04/04 19:10:56 neelin * Fixed handling of compressed files. * * Revision 1.1 1995/04/04 15:51:42 neelin * Initial revision * @COPYRIGHT : Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "config.h" #include #include #include #include #include #include #include /* Constants */ #define MINC_EXTENSION ".mnc" #define BZIP_EXTENSION ".bz" #define BZIP2_EXTENSION ".bz2" #define GZIP_EXTENSION ".gz" #define COMPRESS_EXTENSION ".Z" #define PACK_EXTENSION ".z" #define ZIP_EXTENSION ".zip" #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif /* Typedefs */ typedef enum { Insert_attribute, Delete_attribute, Append_attribute } Attribute_Action; /* Functions */ int get_attribute(char *dst, char *key, char *nextarg); /* Argument variables */ int attribute_list_size = 0; int attribute_list_alloc = 0; struct { Attribute_Action action; char *variable; char *attribute; char *value; int num_doubles; double *double_values; } *attribute_list = NULL; /* Argument table */ static ArgvInfo argTable[] = { {NULL, ARGV_HELP, NULL, NULL, "Options for specifying attribute values by name."}, {"-sinsert", ARGV_FUNC, (char *) get_attribute, NULL, "Insert string attribute (:=)."}, {"-dinsert", ARGV_FUNC, (char *) get_attribute, NULL, "Insert a double precision attribute (:=(,...))."}, {"-delete", ARGV_FUNC, (char *) get_attribute, NULL, "Delete an attribute (:)."}, {"-sappend", ARGV_FUNC, (char *) get_attribute, NULL, "Append string attribute (:=)."}, {"-dappend", ARGV_FUNC, (char *) get_attribute, NULL, "Append a double precision attribute (:=(,...))."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *pname; char *filename, *tempfile, *newfile; char string[1024]; char *variable_name, *attribute_name; int created_tempfile; int done_redef; int iatt; int mincid, varid; int variable_exists, attribute_exists; nc_type attribute_type, new_type; int attribute_length, new_length; void *new_value; int total_length, alloc_length, ival; char *zeros; int old_ncopts; /* Parse the command line */ pname=argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || (argc != 2)) { (void) fprintf(stderr, "\nUsage: %s [] \n", pname); (void) fprintf(stderr, " %s [-help]\n\n", pname); exit(EXIT_FAILURE); } filename = argv[1]; /* Create temp file name. First try looking for minc extension, then a compression extension. Chop off the unwanted extension. */ (void) strncpy(string, filename, sizeof(string)-1); tempfile = strstr(string, MINC_EXTENSION); if (tempfile != NULL) { tempfile += strlen(MINC_EXTENSION); if (*tempfile == '\0') tempfile = NULL; } else { tempfile = strstr(string, GZIP_EXTENSION); if (tempfile == NULL) tempfile = strstr(string, BZIP_EXTENSION); if (tempfile == NULL) tempfile = strstr(string, BZIP2_EXTENSION); if (tempfile == NULL) tempfile = strstr(string, COMPRESS_EXTENSION); if (tempfile == NULL) tempfile = strstr(string, PACK_EXTENSION); if (tempfile == NULL) tempfile = strstr(string, ZIP_EXTENSION); } if (tempfile != NULL) { *tempfile = '\0'; tempfile = string; } /* If tempfile == NULL, then either we have a minc file or we don't know how to edit the file in place. Check that it is a minc file. */ if (tempfile == NULL) { newfile = miexpand_file(filename, tempfile, TRUE, &created_tempfile); if (created_tempfile) { if (newfile != NULL) { (void) remove(newfile); free(newfile); } (void) fprintf(stderr, "Cannot edit file \"%s\" in place.\n", filename); exit(EXIT_FAILURE); } } /* Expand the file. */ newfile = miexpand_file(filename, tempfile, FALSE, &created_tempfile); if (newfile == NULL) { (void) fprintf(stderr, "Error decompressing file \"%s\"\n", filename); exit(EXIT_FAILURE); } /* If a new file was created, get rid of the old one */ if (created_tempfile) { (void) remove(filename); } /* Open the file */ mincid = miopen(newfile, NC_WRITE); /* Loop through attribute list, modifying values */ done_redef = FALSE; ncopts = NC_VERBOSE; zeros = NULL; alloc_length = 0; for (iatt=0; iatt < attribute_list_size; iatt++) { /* Get variable and attribute name */ variable_name = attribute_list[iatt].variable; attribute_name = attribute_list[iatt].attribute; /* Check for attribute existence */ if (strlen(variable_name) == 0) { varid = NC_GLOBAL; variable_exists = TRUE; } else { old_ncopts = ncopts; ncopts = 0; varid = ncvarid(mincid, variable_name); ncopts = old_ncopts; variable_exists = (varid != MI_ERROR); } attribute_type = NC_CHAR; attribute_length = 0; if (variable_exists) { old_ncopts = ncopts; ncopts = 0; attribute_exists = (ncattinq(mincid, varid, attribute_name, &attribute_type, &attribute_length) != MI_ERROR); ncopts = old_ncopts; } else attribute_exists = FALSE; /* Are we inserting or deleting? */ switch (attribute_list[iatt].action) { case Insert_attribute: case Append_attribute: if (attribute_list[iatt].value != NULL) { new_type = NC_CHAR; new_length = strlen(attribute_list[iatt].value)+1; new_value = (void *) attribute_list[iatt].value; } else { new_type = NC_DOUBLE; new_length = attribute_list[iatt].num_doubles; new_value = (void *) attribute_list[iatt].double_values; } /* For append we have to copy the entire attribute, if it * already exists. */ if (attribute_list[iatt].action == Append_attribute && attribute_exists) { char *tmp_value; /* Verify that the existing type matches the newly * requested type. Don't allow a -dappend on a * string attribute, for example. */ if (new_type != attribute_type) { fprintf(stderr, "Can't append %s data to %s attribute %s:%s.\n", (new_type == NC_DOUBLE) ? "double" : "string", (attribute_type == NC_DOUBLE) ? "double" : "string", variable_name, attribute_name); exit(EXIT_FAILURE); } new_type = attribute_type; tmp_value = malloc((attribute_length + new_length) * nctypelen(new_type)); ncattget(mincid, varid, attribute_name, tmp_value); /* For string attributes, remove any trailing null * character before appending. */ if (new_type == NC_CHAR && tmp_value[attribute_length-1] == 0) { attribute_length--; } memcpy(tmp_value + attribute_length * nctypelen(new_type), new_value, new_length * nctypelen(new_type)); new_length += attribute_length; new_value = (void *) tmp_value; } total_length = attribute_length*nctypelen(attribute_type); if (!attribute_exists || (total_length < new_length*nctypelen(new_type))) { if (! done_redef) { done_redef = TRUE; (void) ncredef(mincid); } } else if (!done_redef && attribute_exists && (total_length > 0)) { if (total_length > alloc_length) { if (zeros != NULL) free(zeros); zeros = malloc(total_length); alloc_length = total_length; for (ival=0; ival < alloc_length; ival++) zeros[ival] = '\0'; } (void) ncattput(mincid, varid, attribute_name, NC_CHAR, total_length, zeros); (void) ncsync(mincid); } if (!variable_exists) { old_ncopts = ncopts; ncopts = 0; varid = micreate_group_variable(mincid, variable_name); ncopts = old_ncopts; if (varid == MI_ERROR) { varid = ncvardef(mincid, variable_name, NC_INT, 0, NULL); } variable_exists = (varid != MI_ERROR); } if (variable_exists) { (void) ncattput(mincid, varid, attribute_name, new_type, new_length, new_value); } break; case Delete_attribute: if (attribute_exists) { if (! done_redef) { done_redef = TRUE; (void) ncredef(mincid); } (void) ncattdel(mincid, varid, attribute_name); } break; default: (void) fprintf(stderr, "Program error: unknown action %d\n", (int) attribute_list[iatt].action); exit(EXIT_FAILURE); } } ncopts = NC_VERBOSE | NC_FATAL; /* Close the file */ (void) miclose(mincid); /* Free stuff */ free(newfile); if (zeros != NULL) free(zeros); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_attribute @INPUT : dst - client data passed by ParseArgv key - matching key in argv nextarg - argument following key in argv @OUTPUT : (none) @RETURNS : TRUE because nextarg is used. @DESCRIPTION: Gets attributes from command line. Syntax for argument is ":=". Numeric values are converted to double precision. @METHOD : @GLOBALS : @CALLS : @CREATED : May 3, 1994 (Peter Neelin) @MODIFIED : March 31, 1995 (P.N) - grabbed from rawtominc ---------------------------------------------------------------------------- */ int get_attribute(char *dst, char *key, char *nextarg) /* ARGSUSED */ { int need_double; Attribute_Action action; char *format; char *variable; char *attribute; char *value; char *end, *cur; double *dvalues; int num_doubles, ivalue; /* Check the key */ if (strcmp(key, "-sinsert") == 0) { action = Insert_attribute; need_double = FALSE; format = ":="; } else if (strcmp(key, "-dinsert") == 0) { action = Insert_attribute; need_double = TRUE; format = ":="; } else if (strcmp(key, "-delete") == 0) { action = Delete_attribute; need_double = FALSE; format = ":"; } else if (strcmp(key, "-sappend") == 0) { action = Append_attribute; need_double = FALSE; format = ":="; } else if (strcmp(key, "-dappend") == 0) { action = Append_attribute; need_double = TRUE; format = ":="; } /* Check for a following argument */ if (nextarg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get the variable name */ variable = nextarg; attribute = strchr(variable, ':'); if (attribute == NULL) { (void) fprintf(stderr, "%s option requires argument %s\n", key, format); exit(EXIT_FAILURE); } *attribute = '\0'; attribute++; /* Get the value */ value = NULL; num_doubles = 0; dvalues = NULL; if (action == Insert_attribute || action == Append_attribute) { value = strchr(attribute, '='); if (value == NULL) { (void) fprintf(stderr, "%s option requires argument :=\n", key); exit(EXIT_FAILURE); } *value = '\0'; value++; /* Convert to double precision */ if (need_double) { /* Count the commas */ num_doubles = 1; for (cur=value; *cur != '\0'; cur++) { if (*cur == ',') num_doubles++; } /* Allocate a list */ dvalues = malloc(sizeof(*dvalues) * num_doubles); /* Loop over values */ cur = value; for (ivalue=0; ivalue < num_doubles; ivalue++) { /* Get the value */ dvalues[ivalue] = strtod(cur, &end); if (end == cur) { (void) fprintf(stderr, "\"%s\" option requires a numeric argument\n", key); exit(EXIT_FAILURE); } cur = end; /* Skip whitespace and the comma */ while (isspace((int) *cur)) {cur++;} if ((*cur != '\0') && (*cur != ',')) { (void) fprintf(stderr, "\"%s\" option requires a numeric argument\n", key); exit(EXIT_FAILURE); } else if (*cur == ',') { cur++; } } /* End of loop over double values */ /* Clear the value string */ value = NULL; } /* Endif need_double */ } /* Endif insert */ /* Save the information */ attribute_list_size++; if (attribute_list_size > attribute_list_alloc) { attribute_list_alloc += 10; if (attribute_list == NULL) { attribute_list = malloc(attribute_list_alloc * sizeof(*attribute_list)); } else { attribute_list = realloc(attribute_list, attribute_list_alloc * sizeof(*attribute_list)); } } attribute_list[attribute_list_size-1].action = action; attribute_list[attribute_list_size-1].variable = variable; attribute_list[attribute_list_size-1].attribute = attribute; attribute_list[attribute_list_size-1].value = value; attribute_list[attribute_list_size-1].num_doubles = num_doubles; attribute_list[attribute_list_size-1].double_values = dvalues; return TRUE; } minc-2.2.00/progs/mincmorph/0000755000265600003100000000000012030114723012636 500000000000000minc-2.2.00/progs/mincmorph/kernel_io.h0000644000265600003100000000164412030075003014700 00000000000000/* kernel_io.h */ #ifndef KERNEL_IO #define KERNEL_IO #define KERNEL_DIMS 5 /* inbuilt kernels */ extern int n_inbuilt_kern; typedef enum { K_NULL = 0, K_2D04, K_2D08, K_3D06, K_3D26 } kern_types; /* Structure for Kernel information */ typedef struct { int nelems; int pre_pad[KERNEL_DIMS]; int post_pad[KERNEL_DIMS]; VIO_Real **K; } Kernel; /* returns a new B_Matrix struct (pointer) */ Kernel *new_kernel(int nelems); /* reads in a B_Matrix from a file (pointer) */ VIO_Status input_kernel(const char *kernel_file, Kernel * kernel); /* pretty print a kernel */ int print_kernel(Kernel * kernel); /* calculate start and step offsets for this kernel */ int setup_pad_values(Kernel * kernel); /* return the default kernel(s) */ Kernel *get_2D04_kernel(void); Kernel *get_2D08_kernel(void); Kernel *get_3D06_kernel(void); Kernel *get_3D26_kernel(void); #endif minc-2.2.00/progs/mincmorph/kernel_ops.h0000644000265600003100000000146512030075003015073 00000000000000/* kernel_ops.h */ #ifndef KERNEL_OPS #define KERNEL_OPS #include #include "kernel_io.h" /* kernel functions */ VIO_Volume *binarise(VIO_Volume * vol, double floor, double ceil, double fg, double bg); VIO_Volume *clamp(VIO_Volume * vol, double floor, double ceil, double bg); VIO_Volume *pad(Kernel * K, VIO_Volume * vol, double bg); VIO_Volume *erosion_kernel(Kernel * K, VIO_Volume * vol); VIO_Volume *dilation_kernel(Kernel * K, VIO_Volume * vol); VIO_Volume *median_dilation_kernel(Kernel * K, VIO_Volume * vol); VIO_Volume *convolve_kernel(Kernel * K, VIO_Volume * vol); VIO_Volume *distance_kernel(Kernel * K, VIO_Volume * vol, double bg); VIO_Volume *group_kernel(Kernel * K, VIO_Volume * vol, double bg); VIO_Volume *lcorr_kernel(Kernel * K, VIO_Volume * vol, VIO_Volume *cmp); #endif minc-2.2.00/progs/mincmorph/mincmorph.c0000644000265600003100000005377012030075003014727 00000000000000/* mincmorph.c Copyright 2006-2012 Andrew Janke - a.janke@gmail.com Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and the University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ #include #include #include #include #include #include #include #include #include #include #include "kernel_io.h" #include "kernel_ops.h" #define INTERNAL_PREC NC_FLOAT /* should be NC_FLOAT or NC_DOUBLE */ #define DEF_DOUBLE -DBL_MAX /* function prototypes */ char *get_real_from_string(char *string, double *value); char *get_string_from_string(char *string, char **value); void calc_volume_range(VIO_Volume * vol, double *min, double *max); /* kernel names for pretty output */ char *KERN_names[] = { "NULL", "2D04", "2D08", "3D06", "3D26" }; /* typedefs */ typedef enum { UNDEF = 0, BINARISE, CLAMP, PAD, ERODE, DILATE, MDILATE, OPEN, CLOSE, LPASS, HPASS, CONVOLVE, DISTANCE, GROUP, READ_KERNEL, WRITE, LCORR } op_types; typedef struct { op_types type; char op_c; char *kernel_fn; kern_types kernel_id; char *cmpfile; char *outfile; double range[2]; double foreground; double background; } Operation; /* Argument variables */ int verbose = FALSE; int clobber = FALSE; int is_signed = FALSE; nc_type dtype = NC_SHORT; double range[2] = { -DBL_MAX, DBL_MAX }; double foreground = 1.0; double background = 0.0; kern_types kernel_id = K_NULL; char *kernel_fn = NULL; char *succ_txt = "B"; char successive_help[] = "Successive operations (Maximum: 100) \ \n\tB[floor:ceil:fg:bg] - binarise in the range, using foreground and background \ \n\tK[floor:ceil:bg] - clamp betwen the specified range. Set other voxels to 'bg' (default: 0) \ \n\tP[bg] - pad volume with respect to the current kernel using 'bg' (default: 0)\ \n\tE - erosion \ \n\tD - dilation \ \n\tM - median dilation \ \n\tO - open \ \n\tC - close \ \n\tL - lowpass filter \ \n\tH - highpass filter \ \n\tX - convolve \ \n\tF - distance transform (binary input only - not checked) \ \n\tG - Label the groups in the volume in ascending order \ \n\tR[TYPE|file.kern] - (2D04|2D08|3D06|3D26) or read in a kernel file \ \n\tW[file.mnc] - write out current results \ \n\tI[cmp.mnc] - local xcorr between current file and cmp.mnc \ \n\tDefault: "; /* Argument table */ ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "General options:"}, {"-verbose", ARGV_CONSTANT, (char *)TRUE, (char *)&verbose, "be verbose"}, {"-clobber", ARGV_CONSTANT, (char *)TRUE, (char *)&clobber, "clobber existing files"}, {NULL, ARGV_HELP, NULL, NULL, "\nOutfile Options"}, {"-filetype", ARGV_CONSTANT, (char *)NC_UNSPECIFIED, (char *)&dtype, "Use data type of the input file."}, {"-byte", ARGV_CONSTANT, (char *)NC_BYTE, (char *)&dtype, "Write out byte data."}, {"-short", ARGV_CONSTANT, (char *)NC_SHORT, (char *)&dtype, "Write out short integer data. (Default)"}, {"-int", ARGV_CONSTANT, (char *)NC_INT, (char *)&dtype, "Write out long integer data."}, {"-float", ARGV_CONSTANT, (char *)NC_FLOAT, (char *)&dtype, "Write out single-precision data."}, {"-double", ARGV_CONSTANT, (char *)NC_DOUBLE, (char *)&dtype, "Write out double-precision data."}, {"-signed", ARGV_CONSTANT, (char *)TRUE, (char *)&is_signed, "Write signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *)FALSE, (char *)&is_signed, "Write unsigned integer data."}, {NULL, ARGV_HELP, NULL, NULL, "\nKernel Options"}, {"-2D04", ARGV_CONSTANT, (char *)K_2D04, (char *)&kernel_id, "Use a 2D 4-connectivity kernel."}, {"-2D08", ARGV_CONSTANT, (char *)K_2D08, (char *)&kernel_id, "Use a 2D 8-connectivity kernel."}, {"-3D06", ARGV_CONSTANT, (char *)K_3D06, (char *)&kernel_id, "Use a 3D 6-connectivity kernel. (default)"}, {"-3D26", ARGV_CONSTANT, (char *)K_3D26, (char *)&kernel_id, "Use a 3D 26-connectivity kernel."}, {"-kernel", ARGV_STRING, (char *)1, (char *)&kernel_fn, " read in a custom kernel file"}, {NULL, ARGV_HELP, NULL, NULL, "\nMorphology Options"}, {"-floor", ARGV_FLOAT, (char *)1, (char *)&range[0], "lowwer value for binarising or clamping"}, {"-ceil", ARGV_FLOAT, (char *)1, (char *)&range[1], "upper value for binarising or clamping (incl)"}, {"-range", ARGV_FLOAT, (char *)2, (char *)range, "range for binarising or clamping (incl)"}, {"-foreground", ARGV_FLOAT, (char *)1, (char *)&foreground, "foreground value"}, {"-background", ARGV_FLOAT, (char *)1, (char *)&background, "background value"}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nSingle morphological operations:"}, {"-binarise", ARGV_CONSTANT, (char *)"B", (char *)&succ_txt, "binarise volume using the input range"}, {"-clamp", ARGV_CONSTANT, (char *)"K", (char *)&succ_txt, "clamp volume using the input range"}, {"-pad", ARGV_CONSTANT, (char *)"P", (char *)&succ_txt, "pad volume with respect to the current kernel (-background to specify value)"}, {"-erosion", ARGV_CONSTANT, (char *)"E", (char *)&succ_txt, "do a single erosion"}, {"-dilation", ARGV_CONSTANT, (char *)"D", (char *)&succ_txt, "do a single dilation"}, {"-median_dilation", ARGV_CONSTANT, (char *)"M", (char *)&succ_txt, "do a single median dilation (note: this is not a median filter!)"}, {"-open", ARGV_CONSTANT, (char *)"O", (char *)&succ_txt, "open: dilation(erosion(X))"}, {"-close", ARGV_CONSTANT, (char *)"C", (char *)&succ_txt, "close: erosion(dilation(X))"}, {"-lowpass", ARGV_CONSTANT, (char *)"L", (char *)&succ_txt, "lowpass filter: close(open(X))"}, {"-highpass", ARGV_CONSTANT, (char *)"H", (char *)&succ_txt, "highpass filter: X - lowpass(X)"}, {"-convolve", ARGV_CONSTANT, (char *)"X", (char *)&succ_txt, "convolve file with kernel"}, {"-distance", ARGV_CONSTANT, (char *)"F", (char *)&succ_txt, "distance transform"}, {"-group", ARGV_CONSTANT, (char *)"G", (char *)&succ_txt, "label groups in ascending order"}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nSuccessive morphological operations:"}, {"-successive", ARGV_STRING, (char *)1, (char *)&succ_txt, successive_help}, {NULL, ARGV_HELP, NULL, NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char *argv[]) { int c; char *arg_string; char *infile; char *outfile; VIO_Volume *volume; VIO_Volume *cmpvol; Kernel *kernel; int num_ops; Operation operation[100]; Operation *op; char *tmp_str; char ext_txt[256]; char tmp_filename[MAXPATHLEN]; double tmp_double[4]; double min, max; char *ptr; char *axis_order[3] = { MIzspace, MIyspace, MIxspace }; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ if(ParseArgv(&argc, argv, argTable, 0) || (argc < 2)){ fprintf(stderr, "\nUsage: %s [options] \n", argv[0]); fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* check for the infile */ if(access(infile, F_OK) != 0){ fprintf(stderr, "%s: Couldn't find %s\n\n", argv[0], infile); exit(EXIT_FAILURE); } /* check for the outfile */ if(access(outfile, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists! (use -clobber to overwrite)\n\n", argv[0], outfile); exit(EXIT_FAILURE); } /* check kernel args */ if(kernel_fn != NULL && kernel_id != K_NULL){ fprintf(stderr, "%s: specify either a kernel file or a set kernel (not both)\n\n", argv[0], outfile); exit(EXIT_FAILURE); } /* set the default kernel */ if(kernel_fn == NULL && kernel_id == K_NULL){ kernel_id = K_3D06; } /* add the implicit read kernel operation */ num_ops = 0; op = &operation[num_ops++]; op->type = READ_KERNEL; op->kernel_fn = kernel_fn; op->kernel_id = kernel_id; /* setup operations and check them... */ if(verbose){ fprintf(stdout, "---Checking Operation(s): %s---\n", succ_txt); } ptr = succ_txt; while(ptr[0] != '\0'){ /* set up counters and extra text */ strcpy(ext_txt, ""); op = &operation[num_ops++]; /* get the operation type */ op->op_c = ptr[0]; ptr++; switch (op->op_c){ case 'B': op->type = BINARISE; /* get 4 possible values */ ptr = get_real_from_string(ptr, &tmp_double[0]); ptr = get_real_from_string(ptr, &tmp_double[1]); ptr = get_real_from_string(ptr, &tmp_double[2]); ptr = get_real_from_string(ptr, &tmp_double[3]); op->range[0] = (tmp_double[0] == DEF_DOUBLE) ? range[0] : tmp_double[0]; op->range[1] = (tmp_double[1] == DEF_DOUBLE) ? range[1] : tmp_double[1]; op->foreground = (tmp_double[2] == DEF_DOUBLE) ? foreground : tmp_double[2]; op->background = (tmp_double[3] == DEF_DOUBLE) ? background : tmp_double[3]; sprintf(ext_txt, "range: [%g:%g] fg/bg: [%g:%g]", op->range[0], op->range[1], op->foreground, op->background); break; case 'K': op->type = CLAMP; /* get 3 possible values */ ptr = get_real_from_string(ptr, &tmp_double[0]); ptr = get_real_from_string(ptr, &tmp_double[1]); ptr = get_real_from_string(ptr, &tmp_double[2]); op->range[0] = (tmp_double[0] == DEF_DOUBLE) ? range[0] : tmp_double[0]; op->range[1] = (tmp_double[1] == DEF_DOUBLE) ? range[1] : tmp_double[1]; op->background = (tmp_double[2] == DEF_DOUBLE) ? background : tmp_double[2]; sprintf(ext_txt, "range: [%g:%g] fg/bg: [%g:%g]", op->range[0], op->range[1], op->foreground, op->background); break; case 'P': op->type = PAD; /* get 1 possible value */ ptr = get_real_from_string(ptr, &tmp_double[0]); op->background = (tmp_double[0] == DEF_DOUBLE) ? background : tmp_double[0]; sprintf(ext_txt, "fill value: %g", op->background); break; case 'E': op->type = ERODE; break; case 'D': op->type = DILATE; break; case 'M': op->type = MDILATE; break; case 'O': op->type = OPEN; break; case 'C': op->type = CLOSE; break; case 'L': op->type = LPASS; break; case 'H': op->type = HPASS; break; case 'X': op->type = CONVOLVE; break; case 'F': op->type = DISTANCE; break; case 'G': op->type = GROUP; break; case 'R': op->type = READ_KERNEL; /* get the filename */ ptr = get_string_from_string(ptr, &tmp_str); if(tmp_str == NULL){ fprintf(stderr, "%s: R[TYPE|file.kern] requires a file or kernel name\n\n", argv[0]); exit(EXIT_FAILURE); } /* check if the input kernel is an inbuilt one */ op->kernel_id = K_NULL; for(c = 1; c <= n_inbuilt_kern; c++){ if(strcmp(tmp_str, KERN_names[c]) == 0){ op->kernel_id = (kern_types) c; } } /* if no inbuilt found, assume it's a file */ if(op->kernel_id == K_NULL){ /* set up and check for the real filename */ if(!realpath(tmp_str, tmp_filename) || access(tmp_filename, F_OK) != 0){ fprintf(stderr, "%s: Couldn't find kernel file: %s\n\n", argv[0], tmp_filename); exit(EXIT_FAILURE); } op->kernel_fn = strdup(tmp_filename); sprintf(ext_txt, "kernel_fn: %s", op->kernel_fn); } else { sprintf(ext_txt, "inbuilt_kernel[%d]: %s", op->kernel_id, KERN_names[op->kernel_id]); } break; case 'W': op->type = WRITE; /* get the filename */ ptr = get_string_from_string(ptr, &op->outfile); if(op->outfile == NULL){ fprintf(stderr, "%s: W[file.mnc] _requires_ a filename\n\n", argv[0]); exit(EXIT_FAILURE); } /* check for the outfile */ if(access(op->outfile, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists! (use -clobber to overwrite)\n\n", argv[0], op->outfile); exit(EXIT_FAILURE); } sprintf(ext_txt, "filename: %s", op->outfile); break; case 'I': op->type = LCORR; /* get the filenames */ ptr = get_string_from_string(ptr, &op->cmpfile); if(op->cmpfile == NULL){ fprintf(stderr, "%s: I[cmp.mnc] requires a filename\n\n", argv[0]); exit(EXIT_FAILURE); } /* check for cmpfile */ if(access(op->cmpfile, F_OK) != 0){ fprintf(stderr, "%s: Couldn't find compare file: %s\n\n", argv[0], op->cmpfile); exit(EXIT_FAILURE); } sprintf(ext_txt, "compare filename: %s", op->cmpfile); break; default: fprintf(stderr, "\nUnknown op: %c\n\n %s -help for operations\n\n", op->op_c, argv[0]); exit(EXIT_FAILURE); } if(verbose){ fprintf(stdout, " Op[%02d] %c = %d\t\t%s\n", num_ops, op->op_c, op->type, ext_txt); } } /* add an implicit write statment to the end if needed */ if(operation[num_ops - 1].type != WRITE){ operation[num_ops].type = WRITE; operation[num_ops].outfile = outfile; num_ops++; } /* malloc space for volume structure and read in infile */ volume = (VIO_Volume *) malloc(sizeof(VIO_Volume)); input_volume(infile, MAX_VAR_DIMS, axis_order, INTERNAL_PREC, TRUE, 0.0, 0.0, TRUE, volume, NULL); get_type_range(get_volume_data_type(*volume), &min, &max); set_volume_real_range(*volume, min, max); /* init and then do some operations */ kernel = new_kernel(0); if(verbose){ fprintf(stdout, "\n---Doing %d Operation(s)---\n", num_ops); } for(c = 0; c < num_ops; c++){ op = &operation[c]; switch (op->type){ case BINARISE: volume = binarise(volume, op->range[0], op->range[1], op->foreground, op->background); break; case CLAMP: volume = clamp(volume, op->range[0], op->range[1], op->background); break; case PAD: volume = pad(kernel, volume, op->background); break; case ERODE: volume = erosion_kernel(kernel, volume); break; case DILATE: volume = dilation_kernel(kernel, volume); break; case MDILATE: volume = median_dilation_kernel(kernel, volume); break; case OPEN: volume = erosion_kernel(kernel, volume); volume = dilation_kernel(kernel, volume); break; case CLOSE: volume = dilation_kernel(kernel, volume); volume = erosion_kernel(kernel, volume); break; case LPASS: volume = erosion_kernel(kernel, volume); volume = dilation_kernel(kernel, volume); volume = dilation_kernel(kernel, volume); volume = erosion_kernel(kernel, volume); break; case HPASS: fprintf(stderr, "%s: GNFARK! Highpass Not implemented yet..\n\n", argv[0]); break; case CONVOLVE: volume = convolve_kernel(kernel, volume); break; case DISTANCE: volume = distance_kernel(kernel, volume, background); break; case GROUP: volume = group_kernel(kernel, volume, background); break; case READ_KERNEL: /* free the existing kernel then set the pointer to the new one */ free(kernel); /* read in the kernel or set the kernel to an inbuilt one */ if(op->kernel_id == K_NULL){ kernel = new_kernel(0); if(input_kernel(op->kernel_fn, kernel) != OK){ fprintf(stderr, "%s: Died reading in kernel file: %s\n\n", argv[0], op->kernel_fn); exit(EXIT_FAILURE); } } else { switch (op->kernel_id){ case K_2D04: kernel = get_2D04_kernel(); break; case K_2D08: kernel = get_2D08_kernel(); break; case K_3D06: kernel = get_3D06_kernel(); break; case K_3D26: kernel = get_3D26_kernel(); break; default: fprintf(stderr, "%s: This shouldn't happen -- much bad\n\n", argv[0]); exit(EXIT_FAILURE); } } setup_pad_values(kernel); if(verbose){ fprintf(stdout, "Input kernel:\n"); print_kernel(kernel); } break; case WRITE: if(op->outfile == NULL){ fprintf(stdout, "%s: WRITE passed a NULL pointer! - this is bad\n\n", argv[0]); exit(EXIT_FAILURE); } if(verbose){ fprintf(stdout, "Outputting to %s\n", op->outfile); } /* get the resulting range */ calc_volume_range(volume, &min, &max); /* set the range to something sensible (if possible) */ if(dtype == NC_BYTE && is_signed == FALSE){ if(min >= 0 && max < 255){ fprintf(stdout, "BYTE data, setting 1:1 mapping (0-256)\n"); min = 0; max = 255; } } set_volume_real_range(*volume, min, max); output_modified_volume(op->outfile, dtype, is_signed, 0.0, 0.0, *volume, infile, arg_string, NULL); break; case LCORR: if(op->cmpfile == NULL){ fprintf(stdout, "%s: LCORR passed a NULL pointer! - this is bad\n\n", argv[0]); exit(EXIT_FAILURE); } if(verbose){ fprintf(stdout, "Comparing to %s\n", op->cmpfile); } /* malloc space for volume structure and read cmpfile */ cmpvol = (VIO_Volume *) malloc(sizeof(VIO_Volume)); input_volume(op->cmpfile, MAX_VAR_DIMS, axis_order, INTERNAL_PREC, TRUE, 0.0, 0.0, TRUE, cmpvol, NULL); /* run the local correlation */ volume = lcorr_kernel(kernel, volume, cmpvol); /* clean up */ delete_volume(*cmpvol); free(cmpvol); break; default: fprintf(stderr, "\n%s: Unknown operation (This is very bad, call Houston)\n\n", argv[0]); exit(EXIT_FAILURE); } } /* jump through operations freeing stuff */ // free(op.kernel); delete_volume(*volume); return (EXIT_SUCCESS); } /* get a real from a char* stream */ /* with possible trailing or leading square bracket */ /* and possible leading ':' */ /* return the string advanced to the next token or */ /* as it was input if nothing found */ char *get_real_from_string(char *string, double *value) { char *ptr; /* skip a [ or : else we probably don't belong here */ if(string[0] == '[' || string[0] == ':'){ string++; } /* get a double */ *value = strtod(&string[0], &ptr); /* if nothing found return a default value */ if(&string[0] == ptr){ *value = DEF_DOUBLE; } /* skip over a possible ']' */ if(ptr[0] == ']'){ ptr++; } return ptr; } /* get a copy of the string between [ and ] from a char* */ /* return the string advanced to the next token or */ /* as it was input if nothing found */ char *get_string_from_string(char *string, char **value) { int offset; char *malloc_string; /* initialise the return values first */ *value = NULL; /* get the string if there is one */ if(string[0] == '['){ string++; /* get the length of the string in question */ offset = strcspn(string, "]"); /* alloc some space for the string */ malloc_string = (char *)malloc((offset + 1) * sizeof(char)); /* get a copy of it and append the null charater */ strncpy(malloc_string, string, offset); malloc_string[offset] = '\0'; /* store the result */ *value = malloc_string; /* increment the pointer and skip over a possible '[' */ string += offset; if(string[0] == ']'){ string++; } } return string; } void calc_volume_range(VIO_Volume * vol, double *min, double *max) { int x, y, z; int sizes[MAX_VAR_DIMS]; double value; VIO_progress_struct progress; *min = DBL_MAX; *max = -DBL_MIN; get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Finding Range"); for(z = sizes[0]; z--;){ for(y = sizes[1]; y--;){ for(x = sizes[2]; x--;){ value = get_volume_voxel_value(*vol, z, y, x, 0, 0); if(value < *min){ *min = value; } else if(value > *max){ *max = value; } } } update_progress_report(&progress, z + 1); } terminate_progress_report(&progress); if (*min == *max) { *max = *min + 1.0; } if(verbose){ fprintf(stdout, "Found range of [%g:%g]\n", *min, *max); } } minc-2.2.00/progs/mincmorph/kernel_io.c0000644000265600003100000002505012030075003014670 00000000000000/* kernel_io.c - reads kernel files */ #include #include "kernel_io.h" #define MAX_KERNEL_ELEMS 1000 extern int verbose; static const STRING KERNEL_FILE_HEADER = "MNI Morphology Kernel File"; static const STRING KERNEL_TYPE = "Kernel_Type"; static const STRING NORMAL_KERNEL = "Normal_Kernel"; static const STRING KERNEL = "Kernel"; /* inbuilt kernels */ int n_inbuilt_kern = 4; /* returns a new Kernel struct (pointer) */ Kernel *new_kernel(int nelems) { int i, j; Kernel *tmp; ALLOC_VAR_SIZED_STRUCT(tmp, Real, 10); /* allocate and initialise the Kernel Array */ SET_ARRAY_SIZE(tmp->K, 0, nelems, 10); for(i = 0; i < nelems; i++){ ALLOC(tmp->K[i], KERNEL_DIMS + 1); for(j = 0; j < KERNEL_DIMS; j++){ tmp->K[i][j] = 0.0; } tmp->K[i][KERNEL_DIMS] = 1.0; } tmp->nelems = nelems; return tmp; } /* reads in a Kernel from a file */ Status input_kernel(const char *kernel_file, Kernel * kernel) { int i, j; STRING line; STRING type_name; STRING str; Real tmp_real; FILE *file; /* parameter checking */ if(kernel_file == NULL){ print_error("input_kernel(): passed NULL FILE.\n"); return (ERROR); } file = fopen(kernel_file, "r"); if(file == NULL){ print_error("input_kernel(): error opening Kernel file.\n"); return (ERROR); } /* okay read the header */ if(mni_input_string(file, &line, (char)0, (char)0) != OK){ delete_string(line); print_error("input_kernel(): could not read header in file.\n"); return (ERROR); } if(!equal_strings(line, KERNEL_FILE_HEADER)){ delete_string(line); print_error("input_kernel(): invalid header in file.\n"); return (ERROR); } /* --- read the type of Kernel */ if(mni_input_keyword_and_equal_sign(file, KERNEL_TYPE, FALSE) != OK){ return (ERROR); } if(mni_input_string(file, &type_name, (char)';', (char)0) != OK){ print_error("input_kernel(): missing kernel type.\n"); return (ERROR); } if(mni_skip_expected_character(file, (char)';') != OK){ return (ERROR); } if(!equal_strings(type_name, NORMAL_KERNEL)){ print_error("input_kernel(): invalid kernel type.\n"); delete_string(type_name); return (ERROR); } delete_string(type_name); /* --- read the next string */ if(mni_input_string(file, &str, (char)'=', (char)0) != OK) return (ERROR); if(!equal_strings(str, KERNEL)){ print_error("Expected %s =\n", KERNEL); delete_string(str); return (ERROR); } delete_string(str); if(mni_skip_expected_character(file, (char)'=') != OK){ return (ERROR); } /* now read the elements (lines) of the kernel */ if(verbose){ fprintf(stderr, "Reading [%s]", kernel_file); } for(i = 0; i < MAX_KERNEL_ELEMS; i++){ /* allocate a bit of memory */ SET_ARRAY_SIZE(kernel->K, kernel->nelems, kernel->nelems + 1, 10); ALLOC(kernel->K[i], KERNEL_DIMS + 1); /* get the 5 dimension vectors and the coefficient */ for(j = 0; j < 6; j++){ if(mni_input_real(file, &tmp_real) == OK){ kernel->K[i][j] = tmp_real; } else { /* check for end */ if(mni_skip_expected_character(file, (char)';') == OK){ kernel->nelems = i; if(verbose){ fprintf(stderr, " %dx%d Kernel elements read\n", i, kernel->nelems); } return (OK); } else { print_error("input_kernel(): error reading kernel [%d,%d]\n", i + 1, j + 1); return (ERROR); } } } kernel->nelems++; if(verbose){ fprintf(stderr, "."); fflush(stderr); } } /* SHOLDN'T BE REACHED */ print_error("input_kernel(): Glark! Something is amiss in the State of Kansas\n"); return (ERROR); } /* pretty print a kernel */ int print_kernel(Kernel * kernel) { int i, j; fprintf(stderr, " x y z t v coeff\n"); fprintf(stderr, " -----------------------------------------------\n"); for(i = 0; i < kernel->nelems; i++){ fprintf(stderr, "[%02d]", i); for(j = 0; j < KERNEL_DIMS + 1; j++){ fprintf(stderr, "%8.02f", kernel->K[i][j]); } fprintf(stderr, "\n"); } return (TRUE); } int setup_pad_values(Kernel * kernel) { int c, n; /* init padding values */ for(n = 0; n < KERNEL_DIMS; n++){ kernel->pre_pad[n] = 0; kernel->post_pad[n] = 0; } /* find the padding sizes */ for(c = 0; c < kernel->nelems; c++){ for(n = 0; n < KERNEL_DIMS; n++){ if(kernel->K[c][n] < kernel->pre_pad[n]){ kernel->pre_pad[n] = kernel->K[c][n]; } if(kernel->K[c][n] > kernel->post_pad[n]){ kernel->post_pad[n] = kernel->K[c][n]; } } } return (TRUE); } /* 2D 4 connectivity kernel */ /* x y z t v coeff */ /* ----------------------------------------------- */ /* [00] 1.00 0.00 0.00 0.00 0.00 1.00 */ /* [01] -1.00 0.00 0.00 0.00 0.00 1.00 */ /* [02] 0.00 1.00 0.00 0.00 0.00 1.00 */ /* [03] 0.00 -1.00 0.00 0.00 0.00 1.00 */ Kernel *get_2D04_kernel(void) { Kernel *K = new_kernel(4); K->K[0][0] = 1.0; K->K[1][0] = -1.0; K->K[2][1] = 1.0; K->K[3][1] = -1.0; return K; } /* 2D 8 connectivity kernel */ /* x y z t v coeff */ /* ----------------------------------------------- */ /* [00] 1.00 1.00 0.00 0.00 0.00 1.00 */ /* [01] 1.00 0.00 0.00 0.00 0.00 1.00 */ /* [02] 1.00 -1.00 0.00 0.00 0.00 1.00 */ /* */ /* [03] 0.00 1.00 0.00 0.00 0.00 1.00 */ /* [04] 0.00 -1.00 0.00 0.00 0.00 1.00 */ /* */ /* [05] -1.00 1.00 0.00 0.00 0.00 1.00 */ /* [06] -1.00 0.00 0.00 0.00 0.00 1.00 */ /* [07] -1.00 -1.00 0.00 0.00 0.00 1.00 */ Kernel *get_2D08_kernel(void) { Kernel *K = new_kernel(8); K->K[0][0] = 1.0; K->K[0][1] = 1.0; K->K[1][0] = 1.0; K->K[2][0] = 1.0; K->K[2][1] = -1.0; K->K[3][1] = 1.0; K->K[4][1] = -1.0; K->K[5][0] = -1.0; K->K[5][1] = 1.0; K->K[6][0] = -1.0; K->K[7][0] = -1.0; K->K[7][1] = -1.0; return K; } /* 3D 6 connectivity kernel */ /* x y z t v coeff */ /* ----------------------------------------------- */ /* [00] 1.00 0.00 0.00 0.00 0.00 1.00 */ /* [01] -1.00 0.00 0.00 0.00 0.00 1.00 */ /* [02] 0.00 1.00 0.00 0.00 0.00 1.00 */ /* [03] 0.00 -1.00 0.00 0.00 0.00 1.00 */ /* [04] 0.00 0.00 1.00 0.00 0.00 1.00 */ /* [05] 0.00 0.00 -1.00 0.00 0.00 1.00 */ Kernel *get_3D06_kernel(void) { Kernel *K = new_kernel(6); K->K[0][0] = 1.0; K->K[1][0] = -1.0; K->K[2][1] = 1.0; K->K[3][1] = -1.0; K->K[4][2] = 1.0; K->K[5][2] = -1.0; return K; } /* 3D 26 connectivity kernel */ /* x y z t v coeff */ /* ----------------------------------------------- */ /* [00] 1.00 1.00 1.00 0.00 0.00 1.00 */ /* [01] 1.00 1.00 0.00 0.00 0.00 1.00 */ /* [02] 1.00 1.00 -1.00 0.00 0.00 1.00 */ /* [03] 1.00 0.00 1.00 0.00 0.00 1.00 */ /* [04] 1.00 0.00 0.00 0.00 0.00 1.00 */ /* [05] 1.00 0.00 -1.00 0.00 0.00 1.00 */ /* [06] 1.00 -1.00 1.00 0.00 0.00 1.00 */ /* [07] 1.00 -1.00 0.00 0.00 0.00 1.00 */ /* [08] 1.00 -1.00 -1.00 0.00 0.00 1.00 */ /* [09] 0.00 1.00 1.00 0.00 0.00 1.00 */ /* [10] 0.00 1.00 0.00 0.00 0.00 1.00 */ /* [11] 0.00 1.00 -1.00 0.00 0.00 1.00 */ /* [12] 0.00 0.00 1.00 0.00 0.00 1.00 */ /* ---- 0.00 0.00 0.00 0.00 0.00 ---- */ /* [13] 0.00 0.00 -1.00 0.00 0.00 1.00 */ /* [14] 0.00 -1.00 1.00 0.00 0.00 1.00 */ /* [15] 0.00 -1.00 0.00 0.00 0.00 1.00 */ /* [16] 0.00 -1.00 -1.00 0.00 0.00 1.00 */ /* [17] -1.00 1.00 1.00 0.00 0.00 1.00 */ /* [18] -1.00 1.00 0.00 0.00 0.00 1.00 */ /* [19] -1.00 1.00 -1.00 0.00 0.00 1.00 */ /* [20] -1.00 0.00 1.00 0.00 0.00 1.00 */ /* [21] -1.00 0.00 0.00 0.00 0.00 1.00 */ /* [22] -1.00 0.00 -1.00 0.00 0.00 1.00 */ /* [23] -1.00 -1.00 1.00 0.00 0.00 1.00 */ /* [24] -1.00 -1.00 0.00 0.00 0.00 1.00 */ /* [25] -1.00 -1.00 -1.00 0.00 0.00 1.00 */ Kernel *get_3D26_kernel(void) { Kernel *K = new_kernel(26); K->K[0][0] = 1.0; K->K[0][1] = 1.0; K->K[0][2] = 1.0; K->K[1][0] = 1.0; K->K[1][1] = 1.0; K->K[2][0] = 1.0; K->K[2][1] = 1.0; K->K[2][2] = -1.0; K->K[3][0] = 1.0; K->K[3][2] = 1.0; K->K[4][0] = 1.0; K->K[5][0] = 1.0; K->K[5][2] = -1.0; K->K[6][0] = 1.0; K->K[6][1] = -1.0; K->K[6][2] = 1.0; K->K[7][0] = 1.0; K->K[7][1] = -1.0; K->K[8][0] = 1.0; K->K[8][1] = -1.0; K->K[8][2] = -1.0; K->K[9][1] = 1.0; K->K[9][2] = 1.0; K->K[10][1] = 1.0; K->K[11][1] = 1.0; K->K[11][2] = -1.0; K->K[12][2] = 1.0; K->K[13][2] = -1.0; K->K[14][1] = -1.0; K->K[14][2] = 1.0; K->K[15][1] = -1.0; K->K[16][1] = -1.0; K->K[16][2] = -1.0; K->K[17][0] = -1.0; K->K[17][1] = 1.0; K->K[17][2] = 1.0; K->K[18][0] = -1.0; K->K[18][1] = 1.0; K->K[19][0] = -1.0; K->K[19][1] = 1.0; K->K[19][2] = -1.0; K->K[20][0] = -1.0; K->K[20][2] = 1.0; K->K[21][0] = -1.0; K->K[22][0] = -1.0; K->K[22][2] = -1.0; K->K[23][0] = -1.0; K->K[23][1] = -1.0; K->K[23][2] = 1.0; K->K[24][0] = -1.0; K->K[24][1] = -1.0; K->K[25][0] = -1.0; K->K[25][1] = -1.0; K->K[25][2] = -1.0; return K; } minc-2.2.00/progs/mincmorph/kernel_ops.c0000644000265600003100000006136512030075003015073 00000000000000/* kernel_ops.c */ #include #include #include "kernel_ops.h" extern int verbose; /* function prototypes */ void split_kernel(Kernel * K, Kernel * k1, Kernel * k2); int compare_ints(const void *a, const void *b); int compare_groups(const void *a, const void *b); /* structure for group information */ typedef struct { unsigned int orig_label; unsigned int count; } group_info_struct; typedef group_info_struct *Group_info; int compare_ints(const void *a, const void *b) { return (*(int *)a - *(int *)b); } int compare_groups(const void *a, const void *b) { return (*(Group_info *) b)->count - (*(Group_info *) a)->count; } void split_kernel(Kernel * K, Kernel * k1, Kernel * k2) { int c, k1c, k2c; /* fill the two sub kernels */ k1c = k2c = 0; for(c = 0; c < K->nelems; c++){ if((K->K[c][2] < 0) || (K->K[c][1] < 0 && K->K[c][2] <= 0) || (K->K[c][0] < 0 && K->K[c][1] <= 0 && K->K[c][2] <= 0)){ k1->K[k1c] = K->K[c]; k1c++; } else { k2->K[k2c] = K->K[c]; k2c++; } } k1->nelems = k1c; k2->nelems = k2c; } /* binarise a volume between a range */ Volume *binarise(Volume * vol, double floor, double ceil, double fg, double bg) { int x, y, z; int sizes[MAX_VAR_DIMS]; double value; progress_struct progress; if(verbose){ fprintf(stdout, "Binarising, range: [%g:%g] fg/bg: [%g:%g]\n", floor, ceil, fg, bg); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Binarise"); for(z = sizes[0]; z--;){ for(y = sizes[1]; y--;){ for(x = sizes[2]; x--;){ value = get_volume_voxel_value(*vol, z, y, x, 0, 0); if((value >= floor) && (value <= ceil)){ set_volume_voxel_value(*vol, z, y, x, 0, 0, fg); } else { set_volume_voxel_value(*vol, z, y, x, 0, 0, bg); } } } update_progress_report(&progress, z + 1); } terminate_progress_report(&progress); return (vol); } /* clamp a volume between a range */ Volume *clamp(Volume * vol, double floor, double ceil, double bg) { int x, y, z; int sizes[MAX_VAR_DIMS]; double value; progress_struct progress; if(verbose){ fprintf(stdout, "Clamping, range: [%g:%g] bg: %g\n", floor, ceil, bg); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Clamping"); for(z = sizes[0]; z--;){ for(y = sizes[1]; y--;){ for(x = sizes[2]; x--;){ value = get_volume_voxel_value(*vol, z, y, x, 0, 0); if((value < floor) || (value > ceil)){ set_volume_voxel_value(*vol, z, y, x, 0, 0, bg); } } } update_progress_report(&progress, z + 1); } terminate_progress_report(&progress); return (vol); } /* pad a volume using the background value */ Volume *pad(Kernel * K, Volume * vol, double bg) { int x, y, z; int sizes[MAX_VAR_DIMS]; get_volume_sizes(*vol, sizes); /* z */ for(y = 0; y < sizes[1]; y++){ for(x = 0; x < sizes[2]; x++){ for(z = 0; z < -K->pre_pad[2]; z++){ set_volume_real_value(*vol, z, y, x, 0, 0, bg); } for(z = sizes[0] - K->post_pad[2]; z < sizes[0]; z++){ set_volume_real_value(*vol, z, y, x, 0, 0, bg); } } } /* y */ for(z = 0; z < sizes[0]; z++){ for(x = 0; x < sizes[2]; x++){ for(y = 0; y < -K->pre_pad[1]; y++){ set_volume_real_value(*vol, z, y, x, 0, 0, bg); } for(y = sizes[1] - K->post_pad[1]; y < sizes[1]; y++){ set_volume_real_value(*vol, z, y, x, 0, 0, bg); } } } /* x */ for(z = 0; z < sizes[0]; z++){ for(y = 0; y < sizes[1]; y++){ for(x = 0; x < -K->pre_pad[0]; x++){ set_volume_real_value(*vol, z, y, x, 0, 0, bg); } for(x = sizes[2] - K->post_pad[0]; x < sizes[2]; x++){ set_volume_real_value(*vol, z, y, x, 0, 0, bg); } } } return (vol); } /* perform a dilation on a volume */ Volume *dilation_kernel(Kernel * K, Volume * vol) { int x, y, z, c; double value; int sizes[MAX_VAR_DIMS]; progress_struct progress; Volume tmp_vol; if(verbose){ fprintf(stdout, "Dilation kernel\n"); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Dilation"); /* copy the volume */ tmp_vol = copy_volume(*vol); for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){ for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){ for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){ value = get_volume_real_value(tmp_vol, z, y, x, 0, 0); for(c = 0; c < K->nelems; c++){ if(get_volume_real_value(*vol, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4]) < value){ set_volume_real_value(*vol, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4], value * K->K[c][5]); } } } } update_progress_report(&progress, z + 1); } delete_volume(tmp_vol); terminate_progress_report(&progress); return (vol); } /* perform a median kernel operation on a volume */ Volume *median_dilation_kernel(Kernel * K, Volume * vol) { int x, y, z, c, i; int sizes[MAX_VAR_DIMS]; progress_struct progress; Volume tmp_vol; double value; unsigned int kvalue; unsigned int neighbours[K->nelems]; if(verbose){ fprintf(stdout, "Median Dilation kernel\n"); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Median Dilation"); /* copy the volume */ tmp_vol = copy_volume(*vol); for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){ for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){ for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){ /* only modify background voxels */ value = get_volume_voxel_value(tmp_vol, z, y, x, 0, 0); if(value == 0.0){ i = 0; for(c = 0; c < K->nelems; c++){ kvalue = (unsigned int)get_volume_voxel_value(tmp_vol, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4]); if(kvalue != 0){ neighbours[i] = kvalue; i++; } } /* only run this for adjacent voxels */ if(i > 0){ /* find the median of our little array */ qsort(&neighbours[0], (size_t) i, sizeof(unsigned int), &compare_ints); /* store the median value */ set_volume_voxel_value(*vol, z, y, x, 0, 0, (double)neighbours[(int)floor((i - 1) / 2)]); } } /* else just copy the original value over */ else { set_volume_voxel_value(*vol, z, y, x, 0, 0, value); } } } update_progress_report(&progress, z + 1); } delete_volume(tmp_vol); terminate_progress_report(&progress); return (vol); } /* perform an erosion on a volume */ Volume *erosion_kernel(Kernel * K, Volume * vol) { int x, y, z, c; double value; int sizes[MAX_VAR_DIMS]; progress_struct progress; Volume tmp_vol; if(verbose){ fprintf(stdout, "Erosion kernel\n"); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Erosion"); /* copy the volume */ tmp_vol = copy_volume(*vol); for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){ for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){ for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){ value = get_volume_real_value(tmp_vol, z, y, x, 0, 0); for(c = 0; c < K->nelems; c++){ if(get_volume_real_value(*vol, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4]) > value){ set_volume_real_value(*vol, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4], value * K->K[c][5]); } } value = get_volume_real_value(tmp_vol, z, y, x, 0, 0); } } update_progress_report(&progress, z + 1); } delete_volume(tmp_vol); terminate_progress_report(&progress); return (vol); } /* convolve a volume with a input kernel */ Volume *convolve_kernel(Kernel * K, Volume * vol) { int x, y, z, c; double value; int sizes[MAX_VAR_DIMS]; progress_struct progress; Volume tmp_vol; if(verbose){ fprintf(stdout, "Convolve kernel\n"); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Convolve"); /* copy the volume */ tmp_vol = copy_volume(*vol); for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){ for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){ for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){ value = 0; for(c = 0; c < K->nelems; c++){ value += get_volume_real_value(tmp_vol, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4]) * K->K[c][5]; } set_volume_real_value(*vol, z, y, x, 0, 0, value); } } update_progress_report(&progress, z + 1); } delete_volume(tmp_vol); terminate_progress_report(&progress); return (vol); } /* should really only work on binary images */ /* from the original 2 pass Borgefors alg */ Volume *distance_kernel(Kernel * K, Volume * vol, double bg) { int x, y, z, c; double value, min; int sizes[MAX_VAR_DIMS]; progress_struct progress; Kernel *k1, *k2; /* split the Kernel */ k1 = new_kernel(K->nelems); k2 = new_kernel(K->nelems); split_kernel(K, k1, k2); setup_pad_values(k1); setup_pad_values(k2); if(verbose){ fprintf(stdout, "Distance kernel - background %g\n", bg); fprintf(stdout, "forward direction kernel:\n"); print_kernel(k1); fprintf(stdout, "\nreverse direction kernel:\n"); print_kernel(k2); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2] * 2, "Distance"); /* forward raster direction */ for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){ for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){ for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){ if(get_volume_real_value(*vol, z, y, x, 0, 0) != bg){ /* find the minimum */ min = DBL_MAX; for(c = 0; c < k1->nelems; c++){ value = get_volume_real_value(*vol, z + k1->K[c][2], y + k1->K[c][1], x + k1->K[c][0], 0 + k1->K[c][3], 0 + k1->K[c][4]) + 1; if(value < min){ min = value; } } set_volume_real_value(*vol, z, y, x, 0, 0, min); } } } update_progress_report(&progress, z + 1); } /* reverse raster direction */ for(z = sizes[0] - k2->post_pad[2] - 1; z >= -k2->pre_pad[2]; z--){ for(y = sizes[1] - k2->post_pad[1] - 1; y >= -k2->pre_pad[1]; y--){ for(x = sizes[2] - k2->post_pad[0] - 1; x >= -k2->pre_pad[0]; x--){ min = get_volume_real_value(*vol, z, y, x, 0, 0); if(min != bg){ /* find the minimum distance to bg in the neighbouring vectors */ for(c = 0; c < k2->nelems; c++){ value = get_volume_real_value(*vol, z + k2->K[c][2], y + k2->K[c][1], x + k2->K[c][0], 0 + k2->K[c][3], 0 + k2->K[c][4]) + 1; if(value < min){ min = value; } } set_volume_real_value(*vol, z, y, x, 0, 0, min); } } } update_progress_report(&progress, sizes[2] + z + 1); } free(k1); free(k2); terminate_progress_report(&progress); return (vol); } /* do connected components labelling on a volume */ /* resulting groups are sorted WRT size */ Volume *group_kernel(Kernel * K, Volume * vol, double bg) { int x, y, z; int sizes[MAX_VAR_DIMS]; progress_struct progress; Volume tmp_vol; Kernel *k1, *k2; unsigned int *equiv; unsigned int *counts; unsigned int *trans; unsigned int neighbours[K->nelems]; /* counters */ unsigned int c; unsigned int value; unsigned int group_idx; /* label for the next group */ unsigned int num_groups; unsigned int min_label; unsigned int curr_label; unsigned int prev_label; unsigned int num_matches; /* structure for group data */ Group_info *group_data; /* split the Kernel into forward and backwards kernels */ k1 = new_kernel(K->nelems); k2 = new_kernel(K->nelems); split_kernel(K, k1, k2); setup_pad_values(k1); setup_pad_values(k2); if(verbose){ fprintf(stdout, "Group kernel - background %g\n", bg); fprintf(stdout, "forward direction kernel:\n"); print_kernel(k1); fprintf(stdout, "\nreverse direction kernel:\n"); print_kernel(k2); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Groups"); /* copy and then zero out the original volume */ tmp_vol = copy_volume(*vol); for(z = sizes[0]; z--;){ for(y = sizes[1]; y--;){ for(x = sizes[2]; x--;){ set_volume_voxel_value(*vol, z, y, x, 0, 0, 0); } } } /* pass 1 - forward direction (we assume a symmetric kernel) */ /* our first group is given the label 1 */ group_idx = 1; /* initialise the equiv and counts arrays */ SET_ARRAY_SIZE(equiv, 0, group_idx, 500); equiv[0] = 0; SET_ARRAY_SIZE(counts, 0, group_idx, 500); counts[0] = 0; for(z = -k1->pre_pad[2]; z < sizes[0] - k1->post_pad[2]; z++){ for(y = -k1->pre_pad[1]; y < sizes[1] - k1->post_pad[1]; y++){ for(x = -k1->pre_pad[0]; x < sizes[2] - k1->post_pad[0]; x++){ if(get_volume_voxel_value(tmp_vol, z, y, x, 0, 0) != bg){ /* search this voxels neighbours */ num_matches = 0; min_label = INT_MAX; for(c = 0; c < k1->nelems; c++){ value = (unsigned int)get_volume_voxel_value(*vol, z + k1->K[c][2], y + k1->K[c][1], x + k1->K[c][0], 0 + k1->K[c][3], 0 + k1->K[c][4]); if(value != 0){ if(value < min_label){ min_label = value; } neighbours[num_matches] = value; num_matches++; } } switch (num_matches){ case 0: /* no neighbours, make a new label and increment */ set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) group_idx); SET_ARRAY_SIZE(equiv, group_idx, group_idx + 1, 500); equiv[group_idx] = group_idx; SET_ARRAY_SIZE(counts, group_idx, group_idx + 1, 500); counts[group_idx] = 1; group_idx++; break; case 1: /* only one neighbour, no equivalences needed */ set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) min_label); counts[min_label]++; break; default: /* more than one neighbour */ /* first sort the neighbours array */ qsort(&neighbours[0], (size_t) num_matches, sizeof(unsigned int), &compare_ints); /* find the minimum possible label for this voxel, */ /* this is done by descending through each neighbours */ /* equivalences until an equivalence equal to itself */ /* is found */ prev_label = -1; for(c = 0; c < num_matches; c++){ curr_label = neighbours[c]; /* recurse this label if we haven't yet */ if(curr_label != prev_label){ while(equiv[curr_label] != equiv[equiv[curr_label]]){ curr_label = equiv[curr_label]; } /* check against the current minimum value */ if(equiv[curr_label] < min_label){ min_label = equiv[curr_label]; } } prev_label = neighbours[c]; } /* repeat, setting equivalences to the min_label */ prev_label = -1; for(c = 0; c < num_matches; c++){ curr_label = neighbours[c]; if(curr_label != prev_label){ while(equiv[curr_label] != equiv[equiv[curr_label]]){ curr_label = equiv[curr_label]; equiv[curr_label] = min_label; } /* set the label itself */ if(equiv[neighbours[c]] != min_label){ equiv[neighbours[c]] = min_label; } } prev_label = neighbours[c]; } /* finally set the voxel in question to the minimum value */ set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) min_label); counts[min_label]++; break; } /* end case */ } } } update_progress_report(&progress, z + 1); } terminate_progress_report(&progress); /* reduce the equiv and counts array */ num_groups = 0; for(c = 0; c < group_idx; c++){ /* if this equivalence is not resolved yet */ if(c != equiv[c]){ /* find the min label value */ min_label = equiv[c]; while(min_label != equiv[min_label]){ min_label = equiv[min_label]; } /* update the label and its counters */ equiv[c] = min_label; counts[min_label] += counts[c]; counts[c] = 0; } else { num_groups++; } } /* Allocate space for the array of groups */ group_data = (Group_info *) malloc(num_groups * sizeof(Group_info)); num_groups = 0; for(c = 0; c < group_idx; c++){ if(counts[c] > 0){ /* allocate space for this element */ group_data[num_groups] = malloc(sizeof(group_info_struct)); group_data[num_groups]->orig_label = equiv[c]; group_data[num_groups]->count = counts[c]; num_groups++; } } /* sort the groups by the count size */ if(verbose){ fprintf(stdout, "Found %d unique groups from %d, sorting...\n", num_groups, group_idx); } qsort(group_data, num_groups, sizeof(Group_info), &compare_groups); /* set up the transpose array */ trans = (unsigned int *)malloc(sizeof(unsigned int) * group_idx); for(c = 0; c < num_groups; c++){ trans[group_data[c]->orig_label] = c + 1; /* +1 to bump past 0 */ } /* pass 2 - resolve equivalences in the output data */ if(verbose){ fprintf(stdout, "Resolving equivalences...\n"); } for(z = sizes[0]; z--;){ for(y = sizes[1]; y--;){ for(x = sizes[2]; x--;){ value = (unsigned int)get_volume_voxel_value(*vol, z, y, x, 0, 0); if(value != 0){ value = trans[equiv[value]]; set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) value); } } } } /* tidy up */ delete_volume(tmp_vol); for(c = 0; c < num_groups; c++){ free(group_data[c]); } free(group_data); free(trans); free(k1); free(k2); return (vol); } /* do local correlation to another volume */ /* xcorr = sum((a*b)^2) / (sqrt(sum(a^2)) * sqrt(sum(b^2)) */ VIO_Volume *lcorr_kernel(Kernel * K, VIO_Volume * vol, VIO_Volume *cmp) { int x, y, z, c; double value, v1, v2; double ssum_v1, ssum_v2, sum_prd, denom; int sizes[MAX_VAR_DIMS]; progress_struct progress; Volume tmp_vol; if(verbose){ fprintf(stdout, "Local Correlation kernel\n"); } get_volume_sizes(*vol, sizes); initialize_progress_report(&progress, FALSE, sizes[2], "Local Correlation"); /* copy the volume */ tmp_vol = copy_volume(*vol); /* zero the output volume */ for(z = sizes[0]; z--;){ for(y = sizes[1]; y--;){ for(x = sizes[2]; x--;){ set_volume_voxel_value(*vol, z, y, x, 0, 0, 0); } } } /* set output range */ set_volume_real_range(*vol, 0.0, 1.0); for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){ for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){ for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){ /* init counters */ ssum_v1 = ssum_v2 = sum_prd = 0; for(c = 0; c < K->nelems; c++){ v1 = get_volume_real_value(tmp_vol, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4]) * K->K[c][5]; v2 = get_volume_real_value(*cmp, z + K->K[c][2], y + K->K[c][1], x + K->K[c][0], 0 + K->K[c][3], 0 + K->K[c][4]) * K->K[c][5]; /* increment counters */ ssum_v1 += v1*v1; ssum_v2 += v2*v2; sum_prd += v1*v2; } denom = sqrt(ssum_v1 * ssum_v2); value = (denom == 0.0) ? 0.0 : sum_prd / denom; set_volume_real_value(*vol, z, y, x, 0, 0, value); } } update_progress_report(&progress, z + 1); } terminate_progress_report(&progress); /* tidy up */ delete_volume(tmp_vol); return (vol); } minc-2.2.00/progs/mincpik/0000755000265600003100000000000012030114721012272 500000000000000minc-2.2.00/progs/mincpik/mincpik.man10000644000265600003100000002200312030102322014411 00000000000000.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MINCPIK 1" .TH MINCPIK 1 "2012-09-24" "perl v5.10.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" \&\fBmincpik\fR \- generate images from minc files .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBmincpik\fR [options] .mnc [] .PP mincpik generates image files from \s-1MINC\s0 volumes using the Imagemagick convert utility. Use \-help or \-man for more information and examples .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBmincpik\fR generates image files from \s-1MINC\s0 volumes using the Imagemagick \&\fBconvert\fR utility. For a complete list of output file types see the \&\fBconvert\fR man pages. .PP \&\s-1EXAMPLES:\s0 To display a default view, axial (z) slicing, middle slice using display. (display is part of the Imagemagick package) .PP .Vb 1 \& mincpik infile.mnc PNG:\- | display \- .Ve .PP To generate a \s-1PNG\s0 file of the 15th coronal slice .PP .Vb 1 \& mincpik \-slice 15 \-coronal infile.mnc outfile.png .Ve .PP To generate a \s-1JPG\s0 file using the hotmetal lookup table with the image range 0 to 100 .PP .Vb 1 \& mincpik \-lookup \*(Aq\-hotmetal\*(Aq \-image_range 0 100 infile.mnc outfile.jpg .Ve .PP ImageMagick: http://www.wizards.dupont.com/cristy/ImageMagick.html \s-1NB:\s0 ImageMagick should be compiled without 16\-bit quanta. .PP Currently if there is a time dimension in the file the image will only produced from the first time point .PP Problems or comments should be sent to: a.janke\e@gmail.com .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-v\fR, \fB\-\-verbose\fR" 4 .IX Item "-v, --verbose" Be noisy when doing things .IP "\fB\-\-version\fR" 4 .IX Item "--version" Print version number and exit .IP "\fB\-?\fR, \fB\-\-help\fR" 4 .IX Item "-?, --help" Dump some quick help output .IP "\fB\-\-man\fR" 4 .IX Item "--man" Dump a man page .IP "\fB\-c\fR \fB\-\-clobber\fR" 4 .IX Item "-c --clobber" overwrite the output file if it exists already .IP "\fB\-f\fR \fB\-\-fake\fR" 4 .IX Item "-f --fake" do a dry run, (echo cmds only). This is usually used in combination with \-verbose to echo commands only .IP "\fB\-\-scale\fR" 4 .IX Item "--scale" scaling factor for resulting image, by default images are output at twice their original resolution .IP "\fB\-\-width\fR" 4 .IX Item "--width" autoscale the resulting image to have a fixed image width (in pixels) .IP "\fB\-\-depth\fR" 4 .IX Item "--depth" bitdepth for resulting image 8 or 16 (\s-1MSB\s0 machines only!) .IP "\fB\-\-title\fR" 4 .IX Item "--title" add a title to the resulting image, if just this option is specified the text used for the title is the name of the input image file. .IP "\fB\-\-title_text\fR" 4 .IX Item "--title_text" use the input string for the title [default: input\-filename]. This option must be used in conjunction with \-title .IP "\fB\-\-title_size\fR" 4 .IX Item "--title_size" font point size for the title .IP "\fB\-\-anot_bar\fR" 4 .IX Item "--anot_bar" create an annotated bar to match the image (use height of the output image) .PP \fIImage range and lookup table options\fR .IX Subsection "Image range and lookup table options" .IP "\fB\-\-range\fR" 4 .IX Item "--range" valid range of values for \s-1MINC\s0 file .IP "\fB\-\-image_range\fR" 4 .IX Item "--image_range" range of image values to use for pixel intensity .IP "\fB\-\-auto_range\fR" 4 .IX Item "--auto_range" automatically determine image range using a 5 and 95% PcT. (histogram) .IP "\fB\-\-lookup\fR" 4 .IX Item "--lookup" arguments to pass to minclookup .PP \fISlicing options\fR .IX Subsection "Slicing options" .IP "\fB\-s\fR \fB\-\-slice\fR" 4 .IX Item "-s --slice" slice number to get. (note this is in voxel co-ordinates) .IP "\fB\-z\fR \fB\-\-axial\fR \fB\-\-transverse\fR" 4 .IX Item "-z --axial --transverse" get an axial/transverse (z) slice .IP "\fB\-y\fR \fB\-\-coronal\fR" 4 .IX Item "-y --coronal" get a coronal (y) slice .IP "\fB\-x\fR \fB\-\-sagittal\fR" 4 .IX Item "-x --sagittal" get a sagital (x) slice .PP \fITriplanar options\fR .IX Subsection "Triplanar options" .IP "\fB\-t\fR \fB\-\-triplanar\fR" 4 .IX Item "-t --triplanar" create a triplanar view of the input file .IP "\fB\-\-tilesize\fR" 4 .IX Item "--tilesize" pixel size for each image in a triplanar .IP "\fB\-\-sagittal_offset\fR" 4 .IX Item "--sagittal_offset" offset the sagittal slice from the centre .IP "\fB\-\-sagittal_offset_perc\fR" 4 .IX Item "--sagittal_offset_perc" offset the sagittal slice by a percentage from the centre .IP "\fB\-\-vertical\fR" 4 .IX Item "--vertical" create a vertical triplanar view (Default) .IP "\fB\-\-horizontal\fR" 4 .IX Item "--horizontal" create a horizontal triplanar view .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIconvert\fR\|(1) \fImincextract\fR\|(1) \fIdisplay\fR\|(1) .SH "AUTHOR" .IX Header "AUTHOR" Andrew Janke \- a.janke@gmail.com .SH "COPYRIGHTS" .IX Header "COPYRIGHTS" Copyright 2012 by Andrew L Janke .SH "POD ERRORS" .IX Header "POD ERRORS" Hey! \fBThe above document had some coding errors, which are explained below:\fR .IP "Around line 580:" 4 .IX Item "Around line 580:" You forgot a '=back' before '=head3' .IP "Around line 582:" 4 .IX Item "Around line 582:" \&'=item' outside of any '=over' .IP "Around line 599:" 4 .IX Item "Around line 599:" You forgot a '=back' before '=head3' .IP "Around line 601:" 4 .IX Item "Around line 601:" \&'=item' outside of any '=over' .IP "Around line 618:" 4 .IX Item "Around line 618:" You forgot a '=back' before '=head3' .IP "Around line 620:" 4 .IX Item "Around line 620:" \&'=item' outside of any '=over' minc-2.2.00/progs/mincpik/mincpik.in0000755000265600003100000004366212027132663014225 00000000000000#! /usr/bin/env perl # # Copyright 2009 # Andrew Janke - a.janke@gmail.com # The University of Queensland # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies. The # author and the University make no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. use strict; use warnings "all"; use Getopt::Long; use Pod::Usage; use File::Basename; use File::Temp qw/ tempdir /; my($Help, $Usage, $me, @opt_table, $tmpdir, %opt); my(@args, $args, $infile, $outfile, %ordering, $CODE); # permutation 'matrix' for differing views %ordering = ( 'zspace' => ['yspace', 'xspace'], 'yspace' => ['zspace', 'xspace'], 'xspace' => ['zspace', 'yspace'], ); $me = &basename($0); %opt = ( 'help' => 0, 'man' => 0, 'verbose' => 0, 'clobber' => 0, 'fake' => 0, 'scale' => 2, 'width' => undef, 'bitdepth' => 8, 'range' => undef, 'image_range' => undef, 'auto_range' => 0, 'lookup' => undef, 'slice' => undef, 'dirs' => ['zspace'], 'triplanar' => 0, 'tilesize' => 250, 'title' => 0, 'title_text' => undef, 'title_size' => 16, 'sagittal_offset' => undef, 'sagittal_offset_perc' => undef, 'orientation' => 'vertical', 'anot_bar' => undef, ); # Check arguments &GetOptions( 'help|?' => \$opt{'help'}, 'man' => \$opt{'man'}, 'version' => sub { &print_version_info }, 'v|verbose' => \$opt{'verbose'}, 'c|clobber' => \$opt{'clobber'}, 'f|fake' => \$opt{'fake'}, 'scale=i' => \$opt{'scale'}, 'width=i' => \$opt{'width'}, 'depth=i' => \$opt{'bitdepth'}, 'title' => \$opt{'title'}, 'title_text=s' => \$opt{'title_text'}, 'title_size=i' => \$opt{'title_size'}, 'anot_bar=s' => \$opt{'anot_bar'}, # Image range and lookup table options 'range=f{2}' => \@{$opt{'range'}}, 'image_range=f{2}' => \@{$opt{'image_range'}}, 'auto_range' => \$opt{'auto_range'}, 'lookup=s' => \$opt{'lookup'}, # Slicing options 's|slice=i' => \$opt{'slice'}, 'z|axial|transverse' => sub { $opt{'dirs'} = ['zspace']; }, 'y|coronal' => sub { $opt{'dirs'} = ['yspace']; }, 'x|sagittal' => sub { $opt{'dirs'} = ['xspace']; }, # triplanar options 't|triplanar' => \$opt{'triplanar'}, 'tilesize=i' => \$opt{'tilesize'}, 'sagittal_offset=i' => \$opt{'sagittal_offset'}, 'sagittal_offset_perc=i' => \$opt{'sagittal_offset_perc'}, 'vertical' => \$opt{'orientation'}, 'horizontal' => \$opt{'orientation'}, ) or pod2usage(-verbose => 1) && exit; # handle -man, -help or missing args pod2usage(-verbose => 1) if $opt{'help'}; pod2usage(-exitstatus => 0, -verbose => 2) if $opt{'man'}; pod2usage(-verbose => 0) && exit if ($#ARGV != 1); # Check arguments #&Getopt::Tabular::SetHelp ($Help, $Usage); #&GetOptions (\@opt_table, \@ARGV) || exit 1; #die $Usage if ($#ARGV < 0); # create temporary directory $tmpdir = &tempdir( "$me-XXXXXXXX", TMPDIR => 1, CLEANUP => 1 ); # set up file names and do a few checks $infile = $ARGV[0]; $outfile = (defined($ARGV[1])) ? $ARGV[1] : 'PNG:-'; die "$me: Couldn't find $infile\n\n" if (!-e $infile); if($outfile ne 'PNG:-' && -e $outfile && !$opt{'clobber'}){ die "\n$me: $outfile exists, use -clobber to overwrite\n\n"; } if($opt{'bitdepth'} != 16 && $opt{bitdepth} != 8) { die "\n$me: Invalid bitdepth specified - $opt{bitdepth} instead of 8 or 16\n\n"; } # sanity check if($opt{'auto_range'} && @{$opt{'image_range'}}){ die "\n$me: only specify one of -auto_range and -image_range (not both)\n\n"; } # warn about -slice and -triplanar if(defined($opt{'slice'}) && $opt{'triplanar'}){ warn "\n$me: you probably don't want to use both -triplanar and -slice\n\n"; } # warn about -sagittal_offset and -sagittal_offset_perc if(defined($opt{'sagittal_offset'}) && $opt{'sagittal_offset_perc'}){ warn "\n$me: only use one of -sagittal_offset -sagittal_offset_perc\n\n"; } # set up directions for triplanar if($opt{'triplanar'}){ $opt{'dirs'} = ['zspace', 'xspace', 'yspace']; } my ($space, $n_slices, $convert_infile, $imgfile, @extract_args, @convert_args, $img_x, $img_y, $img_step_x, $img_step_y, $img_length_x, $img_length_y, $dim_names, $pipe_args, $dimorder, @mont_files); # find the 5% to 95% PcT image range if -auto_range if($opt{'auto_range'}){ my $buf; print STDERR "Getting range of $infile\n" if $opt{'verbose'}; chomp($buf = `mincstats -quiet -pctT 5 $infile`); $buf *= 1.0; @{$opt{'image_range'}}[0] = $buf; chomp($buf = `mincstats -quiet -pctT 95 $infile`); $buf *= 1.0; @{$opt{'image_range'}}[1] = $buf; # a bit of output if($opt{'verbose'}){ print STDERR "Using image range of [@{$opt{image_range}}[0]:@{$opt{image_range}}[1]]\n"; } } # foreach slicing direction foreach $space (@{$opt{'dirs'}}){ print STDERR "Doing direction $space\n" if $opt{'verbose'}; my($slice); $CODE = "GRAY"; # set up the imgfile depending on triplanar and -title if($opt{'triplanar'}){ $imgfile = "$tmpdir/trip-$space.png"; push(@mont_files, $imgfile); } elsif($opt{'title'}){ $imgfile = "$tmpdir/image.png"; } else{ $imgfile = $outfile; } # Get the info we need $args = "mincinfo ". "-dimlength $space ". "-dimlength $ordering{$space}[0] ". "-dimlength $ordering{$space}[1] ". "-attvalue $ordering{$space}[0]:step ". "-attvalue $ordering{$space}[1]:step ". "-dimnames ". $infile; ($n_slices, $img_x, $img_y, $img_step_x, $img_step_y, $dim_names) = split("\n", `$args`); if(defined($opt{'width'})){ $opt{'scale'} = $opt{'width'}/abs($img_step_y * $img_y); print STDERR "Auto-scaling width factor: $opt{'scale'}\n" if $opt{'verbose'}; } $img_length_x = abs(int($img_step_x * $img_x * $opt{'scale'})); $img_length_y = abs(int($img_step_y * $img_y * $opt{'scale'})); # figure out the slice to get $slice = (!defined($opt{'slice'})) ? int($n_slices/2) : $opt{'slice'}; # do the sagittal offset (only one of these should be done) if($space eq 'xspace'){ # slice offset if(defined($opt{'sagittal_offset'})){ $slice += $opt{'sagittal_offset'}; } # perc offset if(defined($opt{'sagittal_offset_perc'})){ $slice += int($n_slices * $opt{'sagittal_offset_perc'} / 100); } } # check we didn't step of the edge if($slice >= $n_slices || $slice < 0){ die "Slice $slice out of range (0-" . ($n_slices-1) . ")\n\n"; } # check if we have a vector_dimension already if($dim_names =~ m/vector_dimension/){ $CODE = 'RGB'; } # take only the first timepoint if we have a time dimension my @time_res_args = (); if($dim_names =~ m/time/){ @time_res_args = ('-dimrange', "time=0,0"); } # do the reshaping $dimorder = join(',', $space, @{$ordering{$space}}); if($CODE eq 'RGB'){ $dimorder .= ',vector_dimension'; } @args = ('mincreshape', '-clobber', '-quiet', '-normalize', '+direction', '-dimsize', "$space=-1", '-dimsize', "$ordering{$space}[0]=-1", '-dimsize', "$ordering{$space}[1]=-1", '-dimorder', $dimorder, '-dimrange', "$space=$slice,1", @time_res_args, $infile, "$tmpdir/reshaped.mnc"); if(scalar(@{$opt{'range'}}) != 0){ push(@args, '-valid_range', @{$opt{'range'}}[0], @{$opt{'range'}}[1]); } if(scalar(@{$opt{'image_range'}}) != 0){ push(@args, '-image_range', @{$opt{'image_range'}}[0], @{$opt{'image_range'}}[1]); } &do_cmd(@args); # do the lookup if required $convert_infile = "$tmpdir/reshaped.mnc"; if($opt{'lookup'}){ if($CODE eq 'RGB'){ warn "$me: Input is vector-valued already. No colour lookup done.\n"; } else{ $convert_infile = "$tmpdir/lookup.mnc"; $CODE = 'RGB'; &do_cmd('minclookup', '-clobber', '-quiet', split(' ', $opt{'lookup'}), "$tmpdir/reshaped.mnc", $convert_infile); } } # set up mincextract command @extract_args = ('mincextract', $convert_infile, '-normalize', ($opt{'bitdepth'} == 16) ? ('-short', '-unsigned') : '-byte'); # set up convert arguments # a flip is 'normal' due to the difference between mnc and most image co-ordinates @convert_args = ('convert', '-depth', $opt{'bitdepth'}, '-flip', '-size', $img_y . 'x' . $img_x, '-geometry', $img_length_y . 'x' . $img_length_x . '!', "$CODE:-", $imgfile); # check if we are big or little endian for convert's MSB wierdity $pipe_args = '|'; if($opt{'bitdepth'} == 16){ if(unpack("c",substr(pack("s",1),0,1))){ warn "$me: LSB machine, swapping bytes with dd and crossing fingers\n"; $pipe_args .= ' dd conv=swab | '; } } &do_cmd(join(' ', @extract_args, $pipe_args, @convert_args)); } # do the triplanar if requested if($opt{'triplanar'}){ my @orient_args; if($opt{'title'}){ $imgfile = "$tmpdir/mont.png"; } else{ $imgfile = $outfile; } if($opt{'orientation'} eq 'vertical'){ @orient_args = ('-tile', ('1x' . ($#mont_files + 1))); } else{ # $opt{orientation} eq 'horizontal' @orient_args = ('-tile', (($#mont_files + 1) . 'x1')); } # do the montage &do_cmd('montage', @orient_args, '-background', 'grey10', '-geometry', "$opt{tilesize}x$opt{tilesize}+1+1", @mont_files, $imgfile); } # Add the title if($opt{'title'}){ # set up the title text if(!defined($opt{'title_text'})){ $opt{'title_text'} = &basename($infile); $opt{'title_text'} =~ s/\.mnc$//; } # This really does not work all that well (but should), go figure # &do_cmd('convert', '-box', 'black', # '-font', '7x13', # '-fill', 'white', # '-draw', "text 4,12 \"$opt{'title_text'}\"", # $imgfile, $outfile); # # use montage instead &do_cmd('montage', '-geometry', '100x100%', '-background', 'black', '-fill', 'white', '-label', $opt{'title_text'}, '-pointsize', $opt{'title_size'}, $imgfile, $outfile); } # create the annotated bar if required if(defined($opt{'anot_bar'})){ my($min, $max, $pcode, $q0, $q1, $q2, $q3, $q4, $bh, $bw, $bb, $ob, $textbump, $i, @buf); # set up a few constants $textbump = 3; $pcode = '%6g'; # text border, other border, height, width $bb = 50; $ob = 25; $bh = $img_length_y - ($ob*2); $bw = int($bh/10); # get range if not defined if(!defined($opt{'image_range'}[0])){ print STDERR "Getting image range\n" if $opt{'verbose'}; @buf = split(/\n/, `mincstats -min -max -quiet $infile`); @{$opt{'image_range'}}[0] = $buf[0] * 1.0; @{$opt{'image_range'}}[1] = $buf[1] * 1.0; } $min = @{$opt{'image_range'}}[0]; $max = @{$opt{'image_range'}}[1]; # set up the datafile my(@data) = undef; my($packstring) = ''; for($i=0; $i<$bh; $i++){ $data[$i] = $i; $packstring .= 'f'; } open(FH, ">$tmpdir/tmp-float.raw"); for($i=0; $i<$bw; $i++){ syswrite(FH, pack($packstring, @data)); } close(FH); # make minc file &do_cmd('rawtominc', '-clobber', '-float', '-input', "$tmpdir/tmp-float.raw", '-xstep', 1, '-ystep', 1, '-zstep', 1, '-xstart', 0, '-ystart', 0, '-zstart', 0, '-dimorder', 'xspace,yspace,zspace', "$tmpdir/bar.mnc", $bw, $bh, 1); # make .miff bar image (whoa... recursion!) &do_cmd('mincpik', '-clobber', '-scale', 1, (defined($opt{'lookup'})) ? ('-lookup', $opt{'lookup'}) : (), "$tmpdir/bar.mnc", "$tmpdir/bar.png"); # set up the text $q0 = sprintf($pcode, $min); $q1 = sprintf($pcode, (($max-$min) * 0.25) + $min); $q2 = sprintf($pcode, (($max-$min) * 0.5) + $min); $q3 = sprintf($pcode, (($max-$min) * 0.75) + $min); $q4 = sprintf($pcode, $max); # create the bar itself via convert &do_cmd('convert', '-bordercolor', 'white', '-border', $bb, # color for all the decorations '-fill', 'black', # bar border '-draw', "line " . join(',', $bb, $bb, ($bb+$bw), $bb ), '-draw', "line " . join(',', $bb, ($bb+$bh), ($bb+$bw), ($bb+$bh)), '-draw', "line " . join(',', $bb, $bb, $bb, ($bb+$bh)), '-draw', "line " . join(',', ($bb+$bw), $bb, ($bb+$bw), ($bb+$bh)), # 3 ticks at 1/4, 1/2 and 3/4 '-draw', "line " . join(',', ($bb+($bw*3/4)), ($bb+($bh*1/4)), ($bb+$bw), ($bb+($bh*1/4))), '-draw', "line " . join(',', ($bb+($bw*3/4)), ($bb+($bh*2/4)), ($bb+$bw), ($bb+($bh*2/4))), '-draw', "line " . join(',', ($bb+($bw*3/4)), ($bb+($bh*3/4)), ($bb+$bw), ($bb+($bh*3/4))), # text '-draw', 'text ' . ($bb+$bw) . ',' . ($bb+($bh*0/4)+$textbump) . " '$q4'", '-draw', 'text ' . ($bb+$bw) . ',' . ($bb+($bh*1/4)+$textbump) . " '$q3'", '-draw', 'text ' . ($bb+$bw) . ',' . ($bb+($bh*2/4)+$textbump) . " '$q2'", '-draw', 'text ' . ($bb+$bw) . ',' . ($bb+($bh*3/4)+$textbump) . " '$q1'", '-draw', 'text ' . ($bb+$bw) . ',' . ($bb+($bh*4/4)+$textbump) . " '$q0'", # finally crop of the extra border '-crop', (($bb*2)+$bw-($bb-$ob)) . "x" . (($bb*2)+$bh-$bb) . "+" . ($bb-$ob) . "+" . ($bb-$ob), "$tmpdir/bar.png", $opt{'anot_bar'}); } sub do_cmd { print STDERR "@_\n" if $opt{'verbose'}; if(!$opt{'fake'}){ system(@_) == 0 or die "\n$me: Failed executing @_\n\n"; } } # print version information sub print_version_info { my $PACKAGE = '@PACKAGE_NAME@'; my $VERSION = '@PACKAGE_VERSION@'; my $PACKAGE_BUGREPORT = '@PACKAGE_BUGREPORT@'; print STDOUT "\n$PACKAGE version $VERSION\n". "Comments to $PACKAGE_BUGREPORT\n\n"; exit 0; } __END__ =head1 NAME B - generate images from minc files =head1 SYNOPSIS B [options] .mnc [] mincpik generates image files from MINC volumes using the Imagemagick convert utility. Use -help or -man for more information and examples =head1 DESCRIPTION B generates image files from MINC volumes using the Imagemagick B utility. For a complete list of output file types see the B man pages. EXAMPLES: To display a default view, axial (z) slicing, middle slice using display. (display is part of the Imagemagick package) mincpik infile.mnc PNG:- | display - To generate a PNG file of the 15th coronal slice mincpik -slice 15 -coronal infile.mnc outfile.png To generate a JPG file using the hotmetal lookup table with the image range 0 to 100 mincpik -lookup '-hotmetal' -image_range 0 100 infile.mnc outfile.jpg ImageMagick: http://www.wizards.dupont.com/cristy/ImageMagick.html NB: ImageMagick should be compiled without 16-bit quanta. Currently if there is a time dimension in the file the image will only produced from the first time point Problems or comments should be sent to: a.janke\@gmail.com =head1 OPTIONS =over 4 =item B<-v>, B<--verbose> Be noisy when doing things =item B<--version> Print version number and exit =item B<-?>, B<--help> Dump some quick help output =item B<--man> Dump a man page =item B<-c> B<--clobber> overwrite the output file if it exists already =item B<-f> B<--fake> do a dry run, (echo cmds only). This is usually used in combination with -verbose to echo commands only =item B<--scale> scaling factor for resulting image, by default images are output at twice their original resolution =item B<--width> autoscale the resulting image to have a fixed image width (in pixels) =item B<--depth> bitdepth for resulting image 8 or 16 (MSB machines only!) =item B<--title> add a title to the resulting image, if just this option is specified the text used for the title is the name of the input image file. =item B<--title_text> use the input string for the title [default: input-filename]. This option must be used in conjunction with -title =item B<--title_size> font point size for the title =item B<--anot_bar> create an annotated bar to match the image (use height of the output image) =head3 Image range and lookup table options =item B<--range> valid range of values for MINC file =item B<--image_range> range of image values to use for pixel intensity =item B<--auto_range> automatically determine image range using a 5 and 95% PcT. (histogram) =item B<--lookup> arguments to pass to minclookup =head3 Slicing options =item B<-s> B<--slice> slice number to get. (note this is in voxel co-ordinates) =item B<-z> B<--axial> B<--transverse> get an axial/transverse (z) slice =item B<-y> B<--coronal> get a coronal (y) slice =item B<-x> B<--sagittal> get a sagital (x) slice =head3 Triplanar options =item B<-t> B<--triplanar> create a triplanar view of the input file =item B<--tilesize> pixel size for each image in a triplanar =item B<--sagittal_offset> offset the sagittal slice from the centre =item B<--sagittal_offset_perc> offset the sagittal slice by a percentage from the centre =item B<--vertical> create a vertical triplanar view (Default) =item B<--horizontal> create a horizontal triplanar view =back =head1 SEE ALSO convert(1) mincextract(1) display(1) =head1 AUTHOR Andrew Janke - a.janke@gmail.com =head1 COPYRIGHTS Copyright 2012 by Andrew L Janke =cuts minc-2.2.00/progs/mincresample/0000755000265600003100000000000012030114723013321 500000000000000minc-2.2.00/progs/mincresample/mincresample.h0000644000265600003100000003273512027132663016114 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincresample.h @DESCRIPTION: Header file for mincresample.c @METHOD : @GLOBALS : @CALLS : @CREATED : February 8, 1993 (Peter Neelin) @MODIFIED : * $Log: mincresample.h,v $ * Revision 6.8 2008-01-13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.7 2005/07/13 21:34:25 bert * Add sinc interpolant (ported from 1.X branch) * * Revision 6.6 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.5 2004/04/27 15:31:20 bert * Added -2 option * * Revision 6.4 2002/11/06 13:32:23 jason * Fixes to mincresample: setting the interpolation type is now done * through an enum rather than function pointers. * * Revision 6.3 2001/04/17 18:40:23 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.2 2001/04/02 14:58:09 neelin * Added -keep_real_range option to prevent rescaling of slices on output * * Revision 6.1 1999/10/19 14:45:27 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:21 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:22 neelin * Release of minc version 0.5 * * Revision 4.1 1997/08/13 15:41:12 neelin * Fixed initialization problem that caused crashing under Linux. * * Revision 4.0 1997/05/07 19:59:42 neelin * Release of minc version 0.4 * * Revision 3.4 1996/01/31 15:22:02 neelin * Fixed bug in transformation of input sampling. * * Revision 3.3 1995/12/12 19:15:35 neelin * Added -spacetype, -talairach and -units options. * * Revision 3.2 1995/11/21 14:13:20 neelin * Transform input sampling with transformation and use this as default. * Added -tfm_input_sampling to specify above option. * Added -use_input_sampling to get old behaviour (no longer the default). * Added -origin option (to specify coordinate instead of start values). * Added -standard_sampling option (to set standard values of start, step * and direction cosines). * Added -invert_transformation option. * * Revision 3.1 1995/11/07 15:04:02 neelin * Modified argument parsing so that only one pass is done. * * Revision 3.0 1995/05/15 19:30:57 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:32:48 neelin * Release of minc version 0.2 * * Revision 1.11 94/09/28 10:32:40 neelin * Pre-release * * Revision 1.10 93/11/04 15:13:40 neelin * Added support for irregularly spaced dimensions. * * Revision 1.9 93/11/02 11:23:56 neelin * Handle imagemax/min potentially varying over slices (for vector data, etc.) * * Revision 1.8 93/10/20 14:05:42 neelin * Added VOXEL_COORD_EPS - an epsilon for doing voxel coordinate comparisons. * * Revision 1.7 93/08/11 14:31:50 neelin * Changed prototype for check_imageminmax. * * Revision 1.6 93/08/11 13:34:20 neelin * Converted to use Dave MacDonald's General_transform code. * Fixed bug in get_slice - for non-linear transformations coord was * transformed, then used again as a starting coordinate. * Handle files that have image-max/min that doesn't vary over slices. * Handle files that have image-max/min varying over row/cols. * Allow volume to extend to voxel edge for -nearest_neighbour interpolation. * Handle out-of-range values (-fill values from a previous mincresample, for * example). * Save transformation file as a string attribute to processing variable. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Constants used in program */ /* Number of dimensions for various things */ #define VOL_NDIMS 3 /* Number of volume dimensions */ #define WORLD_NDIMS 3 /* Number of world spatial dimensions */ #define SLICE_NDIMS 2 /* Number of slice dimensions */ #define MAT_NDIMS WORLD_NDIMS+1 /* Number of dims for homogenous matrix */ /* For referring to world axes in arrays subscripted by WORLD_NDIMS */ #define NO_AXIS -1 #define XAXIS 0 #define YAXIS 1 #define ZAXIS 2 /* For referring to volume axes in arrays subscripted by VOL_NDIMS */ #define SLC_AXIS 0 #define ROW_AXIS 1 #define COL_AXIS 2 /* For referring to slice axes in arrays subscripted by SLICE_NDIMS */ #define SLICE_ROW 0 #define SLICE_COL 1 /* For referring to world coordinates in Coord_Vector */ #define XCOORD 0 #define YCOORD 1 #define ZCOORD 2 /* For referring to volume coordinates in Coord_Vector */ #define SLICE 0 #define ROW 1 #define COLUMN 2 /* Various constants */ #define NO_VALUE DBL_MAX /* Constant to flag fact that value not set */ #define DEFAULT_MAX 1.0 #define DEFAULT_MIN 0.0 #define FILL_DEFAULT DBL_MAX /* Fillvalue indicating -nofill */ #define SMALL_VALUE (100.0*FLT_MIN) /* A small floating-point value */ #define VOXEL_COORD_EPS (100.0*FLT_EPSILON) /* Epsilon for voxel coords */ #define TRANSFORM_BUFFER_INCREMENT 256 #define PROCESSING_VAR "processing" #define TEMP_IMAGE_VAR "mincresample-temporary-image" #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Types used in program */ enum Interpolant_type { TRILINEAR, TRICUBIC, N_NEIGHBOUR, WINDOWED_SINC }; typedef double Coord_Vector[WORLD_NDIMS]; typedef struct { char *name; int mincid; int imgid; int maxid; int minid; int ndims; nc_type datatype; int is_signed; double vrange[2]; /* [0]=min, [1]=max */ long nelements[MAX_VAR_DIMS]; /* Size of each dimension */ int world_axes[MAX_VAR_DIMS]; /* Relates variable index to X, Y, Z or NO_AXIS */ int indices[VOL_NDIMS]; /* Indices of volume dimenions (subscripted from slowest to fastest) */ int axes[WORLD_NDIMS]; /* Relates world X,Y,Z (index) to dimension order (value=0,1,2; 0=slowest varying) */ int using_icv; /* True if we are using an icv to read data */ int icvid; /* Id of icv (if used) */ long slices_per_image; /* Number of volume slices (row, column) per minc file image */ long images_per_file; /* Number of minc file images in the file */ int do_slice_renormalization; /* Flag indicating that we need to loop through the data a second time, recomputing the slices to normalize images properly */ int keep_real_range; /* Flag indicating whether we should keep the real range of the input data or not */ } File_Info; typedef struct { long size[SLICE_NDIMS]; /* Size of each dimension */ double *data; /* Pointer to slice data */ } Slice_Data; typedef struct Volume_Data_Struct Volume_Data; typedef int (*Interpolating_Function) (Volume_Data *volume, Coord_Vector coord, double *result); struct Volume_Data_Struct { nc_type datatype; /* Type of data in volume */ int is_signed; /* Sign of data (TRUE if signed) */ int use_fill; /* TRUE if fill values should be used in calculation of output image max/min */ double fillvalue; /* Value to return when out of bounds */ double vrange[2]; /* [0]=min, [1]=max */ double real_range[2]; /* Real min and max for current volume */ int size[VOL_NDIMS]; /* Size of each dimension */ void *data; /* Pointer to volume data */ double *scale; /* Pointer to array of scales for slices */ double *offset; /* Pointer to array of offsets for slices */ Interpolating_Function interpolant; /* Function Pointer */ }; typedef struct { File_Info *file; /* Information about associated file */ Volume_Data *volume; /* Volume data for (input volume) */ Slice_Data *slice; /* Slice data for (output volume) */ General_transform *voxel_to_world; General_transform *world_to_voxel; } VVolume; typedef struct { int axes[WORLD_NDIMS]; /* Relates world X,Y,Z (index) to dimension order (value=0,1,2; 0=slowest varying) */ long nelements[WORLD_NDIMS]; /* These are subscripted by X, Y and Z */ double step[WORLD_NDIMS]; double start[WORLD_NDIMS]; double dircos[WORLD_NDIMS][WORLD_NDIMS]; double *coords[WORLD_NDIMS]; char units[WORLD_NDIMS][MI_MAX_ATTSTR_LEN]; char spacetype[WORLD_NDIMS][MI_MAX_ATTSTR_LEN]; } Volume_Definition; typedef struct { int verbose; } Program_Flags; typedef struct { int invert_transform; char *file_name; char *file_contents; long buffer_length; General_transform *transformation; } Transform_Info; typedef struct { int clobber; int keep_real_range; nc_type datatype; int is_signed; double vrange[2]; double fillvalue; double origin[3]; Program_Flags flags; enum Interpolant_type interpolant_type; /* Type of interpolation */ Transform_Info transform_info; Volume_Definition volume_def; int v2format; /* If non-zero, create a MINC 2.0 output */ } Arg_Data; typedef struct { long last_index[VOL_NDIMS]; long nelements[VOL_NDIMS]; double *coords[VOL_NDIMS]; } Irregular_Transform_Data; /* Macros used in program */ #define DO_TRANSFORM(result, transformation, coord) \ general_transform_point(transformation, \ coord[XCOORD], coord[YCOORD], coord[ZCOORD], \ &result[XCOORD], &result[YCOORD], &result[ZCOORD]) #define DO_INVERSE_TRANSFORM(result, transformation, coord) \ general_inverse_transform_point(transformation, \ coord[XCOORD], coord[YCOORD], coord[ZCOORD], \ &result[XCOORD], &result[YCOORD], &result[ZCOORD]) #define IS_LINEAR(transformation) \ (get_transform_type(transformation)==LINEAR) #define VECTOR_COPY(result, first) { \ result[XCOORD] = first[XCOORD]; \ result[YCOORD] = first[YCOORD]; \ result[ZCOORD] = first[ZCOORD]; \ } #define VECTOR_DIFF(result, first, second) { \ result[XCOORD] = first[XCOORD] - second[XCOORD]; \ result[YCOORD] = first[YCOORD] - second[YCOORD]; \ result[ZCOORD] = first[ZCOORD] - second[ZCOORD]; \ } #define VECTOR_ADD(result, first, second) { \ result[XCOORD] = first[XCOORD] + second[XCOORD]; \ result[YCOORD] = first[YCOORD] + second[YCOORD]; \ result[ZCOORD] = first[ZCOORD] + second[ZCOORD]; \ } #define VECTOR_SCALAR_MULT(result, vector, scalar) { \ result[XCOORD] = vector[XCOORD] * (scalar); \ result[YCOORD] = vector[YCOORD] * (scalar); \ result[ZCOORD] = vector[ZCOORD] * (scalar); \ } #ifdef INTERPOLATE # undef INTERPOLATE #endif #define INTERPOLATE(volume, coord, result) \ (*volume->interpolant) (volume, coord, result) #define VOLUME_VALUE(volume, slcind, rowind, colind, value) \ { \ long offset; \ \ offset = ((slcind)*volume->size[ROW_AXIS] + \ (rowind))*volume->size[COL_AXIS] + (colind); \ switch (volume->datatype) { \ case NC_BYTE: \ if (volume->is_signed) \ value = *((signed char *) volume->data + offset); \ else \ value = *((unsigned char *) volume->data + offset); \ break; \ case NC_SHORT: \ if (volume->is_signed) \ value = *((signed short *) volume->data + offset); \ else \ value = *((unsigned short *) volume->data + offset); \ break; \ case NC_INT: \ if (volume->is_signed) \ value = *((signed int *) volume->data + offset); \ else \ value = *((unsigned int *) volume->data + offset); \ break; \ case NC_FLOAT: \ value = *((float *) volume->data + offset); \ break; \ case NC_DOUBLE: \ value = *((double *) volume->data + offset); \ break; \ } \ } /* Function prototypes */ extern void resample_volumes(Program_Flags *program_flags, VVolume *in_vol, VVolume *out_vol, General_transform *transformation); extern int trilinear_interpolant(Volume_Data *volume, Coord_Vector coord, double *result); extern int tricubic_interpolant(Volume_Data *volume, Coord_Vector coord, double *result); extern int nearest_neighbour_interpolant(Volume_Data *volume, Coord_Vector coord, double *result); extern int windowed_sinc_interpolant(Volume_Data *volume, Coord_Vector coord, double *result); #define SINC_HALF_WIDTH_MAX 10 #define SINC_HALF_WIDTH_MIN 1 enum sinc_interpolant_window_t { SINC_WINDOW_NONE, SINC_WINDOW_HANNING, SINC_WINDOW_HAMMING }; extern enum sinc_interpolant_window_t sinc_window_type; extern int sinc_half_width; minc-2.2.00/progs/mincresample/mincresample.man10000644000265600003100000003205512027132663016514 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincresample/mincresample.man1,v 6.4 2005-07-13 21:34:25 bert Exp $ .\" .TH MINCRESAMPLE 1 "$Date: 2005-07-13 21:34:25 $" "" "MINC User's Guide" .SH NAME mincresample - resamples a minc file along new spatial dimensions .SH SYNOPSIS .B mincresample [] .SH DESCRIPTION \fIMincresample\fR will resample a minc file along new spatial dimensions with new voxel positions. Each volume in the input file (given by the spatial dimensions xspace, yspace and zspace) is resampled according to the command-line options. Non-spatial dimensions are preserved in their original order, but spatial dimensions can be re-ordered to give transverse, sagittal or coronal images. The new voxel values are calculated using tri-linear, tri-cubic or nearest-neighbour interpolation. .SH WORLD COORDINATES World coordinates refer to millimetric coordinates relative to some physical origin (either the scanner or some anatomical structure). Voxel coordinates are simply the indices into the image volume of a given voxel. In order to specify appropriate resampling options, it is necessary to understand how MINC coordinate conversions work. Each dimension of a MINC image volume is specified by name - the spatial dimensions are xspace, yspace and zspace. The convention is that positive xspace coordinates run from the patient's left side to right side, positive yspace coordinates run from patient posterior to anterior and positive zspace coordinates run from inferior to superior. For each of these spatial dimensions, the world coordinate conversion is specified by a pair of attributes: step and start. The xspace world coordinate, for example is calculated using x = v*step + start, where x is the x world coordinate and v is the voxel count (starting at zero). Thus the magnitude of the step attribute specifies the distance between voxels and the sign of the step attribute specifies the orientation of the axis. There is a further twist: MINC files are allowed to have non-orthogonal axes with the dimensions not perfectly aligned with the named axis. There can be a direction_cosine attribute that gives the true orientation of the axis. For example, normally the xspace dimension should line up with the world x axis, ie. direction cosine = (1,0,0); however, it is possible to have a direction cosine of (0.9, 0.43589, 0). These attributes (step, start and direction_cosines) provide a conversion from voxel coordinates to world coordinates. Combined with a number of elements or samples along an axis, they provide a complete description of where the output sampling should be. However, when we are resampling data, we are frequently interested in a change of world coordinates: from an MRI scanner's coordinate system to a PET scanner's coordinate system, for example, or from a volume in its acquisition space to coordinates in a standardized space. This change of world coordinates can be specified through the use of a transformation (.xfm) file. Thus, in general, the resampling involves three transformations: from the input file's voxel coordinates to its world coordinates (specified by the input file), from the input world coordinates to the output world coordinates (specified by the transformation file), and from the output file's world coordinates to its voxel coordinates (specified by command-line options). In general, direction cosines are rarely used - axis re-orientation is specified by a change of world coordinates (the transformation file). As well, resampling positions (output world to voxel conversion) are often specified relative to a model file (ie. resample this file so that it looks like that file). Although there are many options for a complete specification of the transformation, one does not usually need to specify more than a few of them. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create MINC 2.0 format output files. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB-verbose\fR Print out progress information for each slice computed (default). .TP \fB\-quiet\fR Do not print out progress information. .SH Resampling specification Options that give the output sampling (all of the following except \fB\-transformation\fR) are parsed in the order that they appear on the command line. Thus a command with \fB\-like file.mnc \-znelements 34 \-zstep 2\fR will give a sampling like that in file in \fIfile.mnc\fR but with 34 samples at 2 mm along the \fIzspace\fR axis. The default sampling is taken from the input file, transformed according to any transformation. .TP \fB\-transformation\fR\ \fIfile.xfm\fR Specify a file giving the world coordinate transformation (default is the identity transformation). .TP \fB\-invert_transformation\fR Invert the transformation before using it. .TP \fB\-noinvert_transformation\fR Do no invert the transformation (default). .TP \fB\-tfm_input_sampling\fR Transform the input sampling (using the transform specified by \fB\-transformation\fR) along with the data and use this as the default sampling (default). .TP \fB\-use_input_sampling\fR Use the input sampling as the default sampling, as is, without transformation, even though the data is being transformed (old behaviour). .TP \fB\-like\fR\ \fIfile.mnc\fR Specify a model file that gives the output world to voxel transformation and number of elements (ie. transform this file so that it looks like that one). .TP \fB\-standard_sampling\fR Set the sampling to standard values (start = 0, step = 1, direction cosines point along appropriate axes). .TP \fB\-spacetype\fR\ \fIstring\fR Set the name of the output space (usually \fBnative____\fR or \fBtalairach_\fR). .TP \fB\-talairach\fR Set the name of the output space to talairach_. .TP \fB\-units\fR\ \fIstring\fR Set the units of the output space. .TP \fB\-origin\fR\ \fIox\ oy\ oz\fR Specify the coordinate of the first voxel. This is not the same as the start value if the direction cosines are non-standard. As well, the start is not just a perpendicular projection of the origin onto the axis, it is a parallel projection (as in a multi-dimensional parallelogram projection). The conversion is handled properly by this option. .TP \fB\-nelements\fR\ \fInx\ ny\ nz\fR Number of elements along each of the world dimensions. .TP \fB\-xnelements\fR\ \fInx\fR Number of elements along the xspace dimension. .TP \fB\-ynelements\fR\ \fIny\fR Number of elements along the yspace dimension. .TP \fB\-znelements\fR\ \fInz\fR Number of elements along the zspace dimension. .TP \fB\-step\fR\ \fIxstep\ ystep\ zstep\fR Step between voxels along each of the world dimensions. .TP \fB\-xstep\fR\ \fIxstep\fR Step between voxels along the xspace dimension. .TP \fB\-ystep\fR\ \fIystep\fR Step between voxels along the yspace dimension. .TP \fB\-zstep\fR\ \fIzstep\fR Step between voxels along the zspace dimension. .TP \fB\-start\fR\ \fIxstart\ ystart\ zstart\fR Position of centre of first voxel along each of the world dimensions. .TP \fB\-xstart\fR\ \fIxstart\fR Position of centre of first voxel along the xspace dimension. .TP \fB\-ystart\fR\ \fIystart\fR Position of centre of first voxel along the yspace dimension. .TP \fB\-zstart\fR\ \fIzstart\fR Position of centre of first voxel along the zspace dimension. .TP \fB\-dircos\fR\ \fIx1\ x2\ x3\ y1\ y2\ y3\ z1\ z2\ z3\fR Direction cosines for each of the world axes. .TP \fB\-xdircos\fR\ \fIx1\ x2\ x3\fR Direction cosines for the xspace dimension. .TP \fB\-ydircos\fR\ \fIy1\ y2\ y3\fR Direction cosines for the yspace dimension. .TP \fB\-zdircos\fR\ \fIz1\ z2\ z3\fR Direction cosines for the zspace dimension. .SH Dimension ordering The default is to preserve the original dimension order. .TP \fB\-transverse\fR Write out transverse slices. .TP \fB\-sagittal\fR Write out sagittal slices. .TP \fB\-coronal\fR Write out coronal slices. .SH Output data type and range The default for type, sign and valid range is to use those of the input file. If type is specified, then both sign and valid range are set to the default for that type. If sign is specified, then valid range is set to the default for the type and sign. .TP \fB\-byte\fR Store output voxels in 8-bit integer format. .TP \fB\-short\fR Store output voxels in 16-bit integer format. .TP \fB\-int\fR Store output voxels in 32-bit integer format. .TP \fB\-long\fR Superseded by \fB\-int\fR. .TP \fB-float\fR Store output voxels in 32-bit floating point format. .TP \fB-double\fR Store output voxels in 64-bit floating point format. .TP \fB\-signed\fR Write out values as signed integers (default for short and long). Ignored for floating point types. .TP \fB\-unsigned\fR Write out values as unsigned integers (default for byte). Ignored for floating point types. .TP \fB\-range\fR \fImin max\fR specifies the valid range of output voxel values. Default is the full range for the type and sign. This option is ignored for floating point values. .TP \fB\-keep_real_range\fR Preserve the real minimum and maximum from the input volume, so that values are scaled in the same way on output. This is particularly useful for resampling label volumes where interpolating intensity values does not make sense. .TP \fB\-nokeep_real_range\fR Recompute the real minimum and maximum for each output slice. This is the default. .SH Handling of undefined (invalid) voxel values .TP \fB\-fill\fR Output voxels that fall outside of the input volume have undefined values. When the \fB-fill\fR option is used, these voxels are given a value that is outside of the valid range (less than the valid minimum, if the type, sign and valid range permit) so that they can be detected by other software. The values of these voxels are not included in the \fIimage-max\fR and \fIimage-min\fR variables. .TP \fB\-nofill\fR Use a real/physical value (not voxel value) of zero for points outside of the input volume. These points are included in the calculation of the \fIimage-max\fR and \fIimage-min\fR variables. This is the default. .TP \fB\-fillvalue\fR\ \fIfillvalue\fR Specifies a real/physical value (not voxel value) for points outside of the input volume. The points are not included in the calculation of the \fIimage-max\fR and \fIimage-min\fR variables. .SH Interpolation options .TP \fB\-trilinear\fR Do a tri-linear interpolation between voxels. The edges of the volume are at the centre of the first and last voxels of a dimension. This is the default. .TP \fB\-tricubic\fR Do a tri-cubic interpolation between voxels. The edges of the volume are at the centre of the first and last voxels of a dimension. .TP \fB\-nearest_neighbour\fR Do nearest neighbour interpolation between voxels (ie. find the voxel closest to the point and use its value). The edges of the volume are at the edge of the first and last voxels of a dimension (centre +/- half voxel separation). .TP \fB\-sinc\fR Do renormalized windowed-sinc interpolation between voxels, as described by Thacker et al. JMRI 10:582-588 (1999). .TP \fB\-width\fR \fIn\fR Specifies the half-width of the sinc interpolation kernel, in the range from 1 to 10. The full sinc kernel width is \fIn\fR * 2 + 1, and therefore varies from 3 to 21. The default value is 5 giving a full-width of 11. .TP \fB\-hanning\fR Use a Hanning window with the sinc interpolant. This is the default. .TP \fB\-hamming\fR Use a Hamming window with the sinc interpolant. .SH Generic options .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES Resample an individual's brain in a standardized space on a standard sampling grid: mincresample individual.mnc in_std_space.mnc \\ -transform transform_to_standard_space.xfm \\ -like standard_sampling.mnc Resample an MRI volume to be matched with a PET volume, but with finer resolution: mincresample mri.mnc mri_resampled.mnc \\ -transform mri_to_pet.xfm -like pet.mnc \\ -step 1 1 2 -xstart -0.5 -ystart -0.5 \\ -nelements 256 256 64 Turn a transverse volume into a sagittal volume: mincresample transverse.mnc sagittal.mnc \\ -sagittal -nearest Turn a 256x256x64 (1x1x2mm) transverse volume into 256x128x256 (1x1x1mm) sagittal volume: mincresample transverse.mnc sagittal.mnc -sagittal \\ -zstep 1 -znelem 128 Get a finer axial sampling on a PET volume: mincresample pet_15_slices.mnc pet_46_slices.mnc \\ -zstep 2 -znelements 46 .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 by Peter Neelin .SH "SEE ALSO" .LP .BR mincreshape (1) minc-2.2.00/progs/mincresample/mincresample.c0000644000265600003100000024600212030075003016065 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincresample @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : error status @DESCRIPTION: Program to resample a minc file along different spatial coordinate axes. @METHOD : @GLOBALS : @CALLS : @CREATED : February 8, 1993 (Peter Neelin) @MODIFIED : * $Log: mincresample.c,v $ * Revision 6.23 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.22 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.21 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.20 2006/07/28 18:19:46 baghdadi * *** empty log message *** * * Revision 6.19 2006/07/28 17:54:57 baghdadi * added vector dimension to list of excluded files (minc2. * * Revision 6.18 2005/08/26 21:07:17 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.17 2005/07/13 21:34:24 bert * Add sinc interpolant (ported from 1.X branch) * * Revision 6.16 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.15 2004/04/30 19:53:40 bert * Remove unused variable * * Revision 6.14 2004/04/30 18:52:49 bert * Remove some unused variables * * Revision 6.13 2004/04/27 15:31:20 bert * Added -2 option * * Revision 6.12 2003/09/18 15:01:33 bert * Removed unnecessary brackets from initializer * * Revision 6.11 2002/11/06 13:32:23 jason * Fixes to mincresample: setting the interpolation type is now done * through an enum rather than function pointers. * * Revision 6.10 2002/10/30 13:53:02 jason * Added a ARGV_LONG argument type to ParseArgv. Used that type for the nelements variable in mincresample * * Revision 6.9 2001/08/24 19:12:50 neelin * Re-ordered variables so that image variable is last. This fixes a problem * with an uninitialized processing variable that shows up when mincresample * is linked with netcdf 3.5.0 and an older program linked with 2.3.2 dies * when reading the mincresample output file. * It also allows use of large volumes with 64-bit minc: all variables * must have 32-bit offset, but one (the image) can extend beyond the * 32-bit limit. * * Revision 6.8 2001/08/16 13:32:39 neelin * Partial fix for valid_range of different type from image (problems * arising from double to float conversion/rounding). NOT COMPLETE. * * Revision 6.7 2001/04/24 13:38:45 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.6 2001/04/17 18:40:22 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.5 2001/04/10 12:44:34 neelin * Re-introduced fix for fillvalues that was lost with last version * * Revision 6.4 2001/04/02 14:58:09 neelin * Added -keep_real_range option to prevent rescaling of slices on output * * Revision 6.2 1999/10/19 14:45:27 neelin * Fixed Log subsitutions for CVS * * Revision 6.1 1998/02/19 15:04:24 neelin * Minor bug fixes. * * Revision 6.0 1997/09/12 13:23:21 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:22 neelin * Release of minc version 0.5 * * Revision 4.1 1997/08/13 15:41:12 neelin * Fixed initialization problem that caused crashing under Linux. * * Revision 4.0 1997/05/07 19:59:42 neelin * Release of minc version 0.4 * * Revision 3.5 1996/01/31 15:22:02 neelin * Fixed bug in transformation of input sampling. * * Revision 3.4 1996/01/30 14:10:24 neelin * Added check for -transformation without -like, -tfm_input_sampling or * -use_input_sampling because of change in behaviour. * * Revision 3.3 1995/12/12 19:15:35 neelin * Added -spacetype, -talairach and -units options. * * Revision 3.2 1995/11/21 14:13:20 neelin * Transform input sampling with transformation and use this as default. * Added -tfm_input_sampling to specify above option. * Added -use_input_sampling to get old behaviour (no longer the default). * Added -origin option (to specify coordinate instead of start values). * Added -standard_sampling option (to set standard values of start, step * and direction cosines). * Added -invert_transformation option. * * Revision 3.1 1995/11/07 15:04:02 neelin * Modified argument parsing so that only one pass is done. * * Revision 3.0 1995/05/15 19:30:57 neelin * Release of minc version 0.3 * * Revision 2.3 1995/05/05 19:11:05 neelin * Modified call to input_transform. * * Revision 2.2 1995/02/09 14:05:51 neelin * Mods to make irix 5 lint happy. * * Revision 2.1 1995/02/08 19:31:47 neelin * Moved ARGSUSED statements for irix 5 lint. * * Revision 2.0 1994/09/28 10:32:46 neelin * Release of minc version 0.2 * * Revision 1.16 94/09/28 10:32:33 neelin * Pre-release * * Revision 1.15 94/03/17 14:12:09 neelin * Exit with failure if no argument given for -transformation or -like. * ., * * Revision 1.14 94/03/15 16:44:21 neelin * Changed default from -clobber to -noclobber. * * Revision 1.13 93/11/04 15:13:13 neelin * Added support for irregularly spaced dimensions. * * Revision 1.12 93/11/03 14:32:44 neelin * Turn off fill for output file. * * Revision 1.11 93/11/03 12:32:17 neelin * Change ncopen, nccreate and ncclose to miopen, micreate and miclose. * * Revision 1.10 93/11/02 11:23:06 neelin * Handle imagemax/min potentially varying over slices (for vector data, etc.) * * Revision 1.9 93/10/12 12:47:50 neelin * Use volume_io.h instead of def_mni.h * * Revision 1.8 93/09/16 09:56:36 neelin * Added use of open_file_with_default_suffix in get_transformation to * append appropriate suffix for xfm files. * * Revision 1.7 93/08/11 14:28:19 neelin * Modified get_arginfo and check_imageminmax to modify type of volume (not * file) so that output volume gets the input volume type by default when * an icv is used on input. * * Revision 1.6 93/08/11 13:27:59 neelin * Converted to use Dave MacDonald's General_transform code. * Fixed bug in get_slice - for non-linear transformations coord was * transformed, then used again as a starting coordinate. * Handle files that have image-max/min that doesn't vary over slices. * Handle files that have image-max/min varying over row/cols. * Allow volume to extend to voxel edge for -nearest_neighbour interpolation. * Handle out-of-range values (-fill values from a previous mincresample, for * example). * Save transformation file as a string attribute to processing variable. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include "mincresample.h" /* Kludge to catch use of -transformation without -like and without -tfm_input_sampling or -use_input_sampling */ #define TRANSFORM_CHANGE_KLUDGE #ifdef TRANSFORM_CHANGE_KLUDGE int Specified_like = FALSE; int Specified_transform = FALSE; #define SAMPLING_ACTION_NOT_SET (-1) #endif static void get_arginfo(int argc, char *argv[], Program_Flags *program_flags, VVolume *in_vol, VVolume *out_vol, General_transform *transformation); static void check_imageminmax(File_Info *fp, Volume_Data *volume); static void get_file_info(char *filename, int initialized_volume_def, Volume_Definition *volume_def, File_Info *file_info); static void get_args_volume_def(Volume_Definition *input_volume_def, Volume_Definition *args_volume_def); static void transform_volume_def(Transform_Info *transform_info, Volume_Definition *input_volume_def, Volume_Definition *transformed_volume_def); static int is_zero_vector(double vector[]); static void normalize_vector(double vector[]); static void create_output_file(char *filename, int clobber, Volume_Definition *volume_def, File_Info *in_file, File_Info *out_file, char *tm_stamp, Transform_Info *transform_info); static void get_voxel_to_world_transf(Volume_Definition *volume_def, General_transform *voxel_to_world); static void irregular_transform_function(void *user_data, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans); static void irregular_inverse_transform_function(void *user_data, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans); static double get_default_range(char *what, nc_type datatype, int is_signed); static void finish_up(VVolume *in_vol, VVolume *out_vol); static int get_transformation(char *dst, char *key, char *nextArg); static int get_model_file(char *dst, char *key, char *nextArg); static int set_standard_sampling(char *dst, char *key, char *nextArg); static int set_spacetype(char *dst, char *key, char *nextArg); static int set_units(char *dst, char *key, char *nextArg); static int get_axis_order(char *dst, char *key, char *nextArg); static int get_fillvalue(char *dst, char *key, char *nextArg); /* Main program */ int main(int argc, char *argv[]) { VVolume in_vol_struct, out_vol_struct; VVolume *in_vol = &in_vol_struct, *out_vol = &out_vol_struct; General_transform transformation; Program_Flags program_flags; /* Get argument information */ get_arginfo(argc, argv, &program_flags, in_vol, out_vol, &transformation); /* Do the resampling */ resample_volumes(&program_flags, in_vol, out_vol, &transformation); /* Finish up */ finish_up(in_vol, out_vol); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_arginfo @INPUT : argc - number of command-line arguments argv - command-line arguments @OUTPUT : program_flags - data for program execution in_vol - description of input volume. out_vol - description of output volume. transformation - description of world transformation @RETURNS : (nothing) @DESCRIPTION: Routine to get information from arguments about input and output files and transfomation. Sets up all structures completely (including allocating space for data). @METHOD : @GLOBALS : @CALLS : @CREATED : February 8, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_arginfo(int argc, char *argv[], Program_Flags *program_flags, VVolume *in_vol, VVolume *out_vol, General_transform *transformation) { /* Argument parsing information */ #ifdef TRANSFORM_CHANGE_KLUDGE static int transform_input_sampling = SAMPLING_ACTION_NOT_SET; #else static int transform_input_sampling = TRUE; #endif static Arg_Data args={ FALSE, /* Clobber */ FALSE, /* Keep scale */ MI_ORIGINAL_TYPE, /* Flag that type not set */ INT_MIN, /* Flag that is_signed has not been set */ {-DBL_MAX, -DBL_MAX}, /* Flag that range not set */ FILL_DEFAULT, /* Flag indicating that fillvalue not set */ {NO_VALUE, NO_VALUE, NO_VALUE}, /* Flag indicating that origin not set */ {TRUE}, /* Verbose */ TRILINEAR, /* use trilinear interpolation by default */ {FALSE, NULL, NULL, 0, NULL}, /* Transformation info is empty at start. Transformation must be set before invoking argument parsing */ { /* Use flags to indicate that values not set */ {NO_AXIS, NO_AXIS, NO_AXIS}, /* Axis order */ {0, 0, 0}, /* nelements */ {0.0, 0.0, 0.0}, /* step */ {NO_VALUE, NO_VALUE, NO_VALUE}, /* start */ {{NO_VALUE, NO_VALUE, NO_VALUE}, /* Default direction cosines */ {NO_VALUE, NO_VALUE, NO_VALUE}, {NO_VALUE, NO_VALUE, NO_VALUE}}, {NULL, NULL, NULL}, /* Pointers to coordinate arrays */ {"", "", ""}, /* units */ {"", "", ""} /* spacetype */ }, FALSE /* MINC 2.0 format? */ }; static ArgvInfo argTable[] = { #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &args.v2format, "Produce a MINC 2.0 format output file."}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &args.clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &args.clobber, "Do not overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &args.flags.verbose, "Print out log messages as processing is being done (default).\n"}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &args.flags.verbose, "Do not print out any log messages.\n"}, {"-transformation", ARGV_FUNC, (char *) get_transformation, (char *) &args.transform_info, "File giving world transformation. (Default = identity)."}, {"-invert_transformation", ARGV_CONSTANT, (char *) TRUE, (char *) &args.transform_info.invert_transform, "Invert the transformation before using it.\n"}, {"-noinvert_transformation", ARGV_CONSTANT, (char *) FALSE, (char *) &args.transform_info.invert_transform, "Do not invert the transformation (default).\n"}, {"-tfm_input_sampling", ARGV_CONSTANT, (char *) TRUE, (char *) &transform_input_sampling, "Transform the input sampling with the transform (default).\n"}, {"-use_input_sampling", ARGV_CONSTANT, (char *) FALSE, (char *) &transform_input_sampling, "Use the input sampling without transforming (old behaviour).\n"}, {"-like", ARGV_FUNC, (char *) get_model_file, (char *) &args.volume_def, "Specifies a model file for the resampling."}, {"-standard_sampling", ARGV_FUNC, (char *) set_standard_sampling, (char *) &args.volume_def, "Set the sampling to standard values (step, start and dircos)."}, {"-spacetype", ARGV_FUNC, (char *) set_spacetype, (char *) &args.volume_def, "Set the spacetype attribute to a specified string."}, {"-talairach", ARGV_FUNC, (char *) set_spacetype, (char *) &args.volume_def, "Output is in Talairach space."}, {"-units", ARGV_FUNC, (char *) set_units, (char *) &args.volume_def, "Specify the units of the output sampling."}, {"-nelements", ARGV_LONG, (char *) 3, (char *) args.volume_def.nelements, "Number of elements along each dimension (X, Y, Z)"}, {"-xnelements", ARGV_LONG, (char *) 0, (char *) &args.volume_def.nelements[X], "Number of elements along the X dimension"}, {"-ynelements", ARGV_LONG, (char *) 0, (char *) &args.volume_def.nelements[Y], "Number of elements along the Y dimension"}, {"-znelements", ARGV_LONG, (char *) 0, (char *) &args.volume_def.nelements[Z], "Number of elements along the Z dimension"}, {"-size", ARGV_LONG, (char *) 3, (char *) args.volume_def.nelements, "synonym for -nelements)"}, {"-xsize", ARGV_LONG, (char *) 0, (char *) &args.volume_def.nelements[X], "synonym for -xnelements"}, {"-ysize", ARGV_LONG, (char *) 0, (char *) &args.volume_def.nelements[Y], "synonym for -ynelements"}, {"-zsize", ARGV_LONG, (char *) 0, (char *) &args.volume_def.nelements[Z], "synonym for -ynelements"}, {"-step", ARGV_FLOAT, (char *) 3, (char *) args.volume_def.step, "Step size along each dimension (X, Y, Z)"}, {"-xstep", ARGV_FLOAT, (char *) 0, (char *) &args.volume_def.step[X], "Step size along the X dimension"}, {"-ystep", ARGV_FLOAT, (char *) 0, (char *) &args.volume_def.step[Y], "Step size along the Y dimension"}, {"-zstep", ARGV_FLOAT, (char *) 0, (char *) &args.volume_def.step[Z], "Step size along the Z dimension"}, {"-start", ARGV_FLOAT, (char *) 3, (char *) args.volume_def.start, "Start point along each dimension (X, Y, Z)"}, {"-xstart", ARGV_FLOAT, (char *) 0, (char *) &args.volume_def.start[X], "Start point along the X dimension"}, {"-ystart", ARGV_FLOAT, (char *) 0, (char *) &args.volume_def.start[Y], "Start point along the Y dimension"}, {"-zstart", ARGV_FLOAT, (char *) 0, (char *) &args.volume_def.start[Z], "Start point along the Z dimension"}, {"-dircos", ARGV_FLOAT, (char *) 9, (char *) args.volume_def.dircos, "Direction cosines along each dimension (X, Y, Z)"}, {"-xdircos", ARGV_FLOAT, (char *) 3, (char *) args.volume_def.dircos[X], "Direction cosines along the X dimension"}, {"-ydircos", ARGV_FLOAT, (char *) 3, (char *) args.volume_def.dircos[Y], "Direction cosines along the Y dimension"}, {"-zdircos", ARGV_FLOAT, (char *) 3, (char *) args.volume_def.dircos[Z], "Direction cosines along the Z dimension"}, {"-origin", ARGV_FLOAT, (char *) 3, (char *) args.origin, "Origin of first pixel in 3D space"}, {"-transverse", ARGV_FUNC, (char *) get_axis_order, (char *) &args.volume_def, "Write out transverse slices"}, {"-sagittal", ARGV_FUNC, (char *) get_axis_order, (char *) &args.volume_def, "Write out sagittal slices"}, {"-coronal", ARGV_FUNC, (char *) get_axis_order, (char *) &args.volume_def, "Write out coronal slices"}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &args.datatype, "Write out byte data"}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &args.datatype, "Write out short integer data"}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &args.datatype, "Write out 32-bit integer data"}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &args.datatype, "Superseded by -int"}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &args.datatype, "Write out single-precision floating-point data"}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &args.datatype, "Write out double-precision floating-point data"}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &args.is_signed, "Write signed integer data"}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &args.is_signed, "Write unsigned integer data"}, {"-range", ARGV_FLOAT, (char *) 2, (char *) args.vrange, "Valid range for output data"}, {"-keep_real_range", ARGV_CONSTANT, (char *) TRUE, (char *) &args.keep_real_range, "Keep the real scale of the input volume"}, {"-nokeep_real_range", ARGV_CONSTANT, (char *) FALSE, (char *) &args.keep_real_range, "Do not keep the real scale of the data (default)"}, {"-nofill", ARGV_FUNC, (char *) get_fillvalue, (char *) &args.fillvalue, "Use value zero for points outside of input volume"}, {"-fill", ARGV_FUNC, (char *) get_fillvalue, (char *) &args.fillvalue, "Use a fill value for points outside of input volume"}, {"-fillvalue", ARGV_FLOAT, (char *) 0, (char *) &args.fillvalue, "Specify a fill value for points outside of input volume"}, {"-trilinear", ARGV_CONSTANT, (char *) TRILINEAR, (char *) &args.interpolant_type, "Do trilinear interpolation"}, {"-tricubic", ARGV_CONSTANT, (char *) TRICUBIC, (char *) &args.interpolant_type, "Do tricubic interpolation"}, {"-nearest_neighbour", ARGV_CONSTANT, (char *) N_NEIGHBOUR, (char *) &args.interpolant_type, "Do nearest neighbour interpolation"}, {"-sinc", ARGV_CONSTANT, (char *) WINDOWED_SINC, (char *) &args.interpolant_type, "Do windowed sinc interpolation"}, {"-width", ARGV_INT, (char *) 1, (char *) &sinc_half_width, "Set half-width of sinc window (1-10)" }, {"-hanning", ARGV_CONSTANT, (char *) SINC_WINDOW_HANNING, (char *) &sinc_window_type, "Set sinc window type to Hanning"}, {"-hamming", ARGV_CONSTANT, (char *) SINC_WINDOW_HAMMING, (char *) &sinc_window_type, "Set sinc window type to Hamming"}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Other variables */ int idim, index; int out_vindex; /* Volume indices (0, 1 or 2) */ int out_findex; /* File indices (0 to ndims-1) */ long size, total_size; char *infile, *outfile; File_Info *fp; char *tm_stamp, *pname; Volume_Definition input_volume_def, transformed_volume_def; General_transform input_transformation; int cflags; /* Initialize the transformation to identity */ create_linear_transform(&input_transformation, NULL); args.transform_info.transformation = &input_transformation; /* Get the time stamp */ tm_stamp = time_stamp(argc, argv); /* Save the program name */ pname=argv[0]; /* Call ParseArgv */ if (ParseArgv(&argc, argv, argTable, 0) || (argc!=3)) { (void) fprintf(stderr, "\nUsage: %s [] \n", pname); (void) fprintf(stderr, " %s [-help]\n\n", pname); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; #ifdef TRANSFORM_CHANGE_KLUDGE if (Specified_transform && !Specified_like && (transform_input_sampling == SAMPLING_ACTION_NOT_SET)) { (void) fprintf(stderr, "Use -like, -tfm_input_sampling or " "-use_input_sampling with -transformation\n"); exit(EXIT_FAILURE); } if (transform_input_sampling == SAMPLING_ACTION_NOT_SET) { transform_input_sampling = TRUE; } #endif /* Check for an inverted transform. This looks backwards because we normally invert the transform. */ if (args.transform_info.invert_transform) { copy_general_transform(args.transform_info.transformation, transformation); } else { create_inverse_general_transform(args.transform_info.transformation, transformation); } args.transform_info.transformation = transformation; /* Get rid of the input transformation */ delete_general_transform(&input_transformation); /* Check input file for default argument information */ in_vol->file = malloc(sizeof(File_Info)); get_file_info(infile, FALSE, &input_volume_def, in_vol->file); transform_volume_def((transform_input_sampling ? &args.transform_info : NULL), &input_volume_def, &transformed_volume_def); get_args_volume_def(&transformed_volume_def, &args.volume_def); /* Check that direction cosines are normalized and look for origin option */ for (idim=0; idim < WORLD_NDIMS; idim++) { normalize_vector(args.volume_def.dircos[idim]); if (is_zero_vector(args.volume_def.dircos[idim])) { (void) fprintf(stderr, "Bad direction cosines.\n"); exit(EXIT_FAILURE); } } if (args.origin[0] != NO_VALUE) { if (convert_origin_to_start(args.origin, args.volume_def.dircos[XCOORD], args.volume_def.dircos[YCOORD], args.volume_def.dircos[ZCOORD], args.volume_def.start) != 0) { (void) fprintf(stderr, "Error converting origin to start value: "); (void) fprintf(stderr, "Bad direction cosines.\n"); exit(EXIT_FAILURE); } } /* Save the voxel_to_world transformation information */ in_vol->voxel_to_world = malloc(sizeof(General_transform)); in_vol->world_to_voxel = malloc(sizeof(General_transform)); get_voxel_to_world_transf(&input_volume_def, in_vol->voxel_to_world); create_inverse_general_transform(in_vol->voxel_to_world, in_vol->world_to_voxel); /* Get input volume data information */ in_vol->slice = NULL; in_vol->volume = malloc(sizeof(Volume_Data)); in_vol->volume->datatype = in_vol->file->datatype; in_vol->volume->is_signed = in_vol->file->is_signed; in_vol->volume->vrange[0] = in_vol->file->vrange[0]; in_vol->volume->vrange[1] = in_vol->file->vrange[1]; if (args.fillvalue == FILL_DEFAULT) { in_vol->volume->fillvalue = 0.0; in_vol->volume->use_fill = TRUE; } else { in_vol->volume->fillvalue = args.fillvalue; in_vol->volume->use_fill = (args.fillvalue != -DBL_MAX); } /* set the function pointer defining the type of interpolation */ switch (args.interpolant_type ) { case TRICUBIC: in_vol->volume->interpolant = tricubic_interpolant; break; case TRILINEAR: in_vol->volume->interpolant = trilinear_interpolant; break; case N_NEIGHBOUR: in_vol->volume->interpolant = nearest_neighbour_interpolant; break; case WINDOWED_SINC: in_vol->volume->interpolant = windowed_sinc_interpolant; if (sinc_half_width < SINC_HALF_WIDTH_MIN || sinc_half_width > SINC_HALF_WIDTH_MAX) { fprintf(stderr, "Invalid sinc half-window size %d\n", sinc_half_width); exit(EXIT_FAILURE); } break; default: (void) fprintf(stderr, "Error determining interpolation type\n"); exit(EXIT_FAILURE); } /* Check min/max variables */ fp = in_vol->file; fp->using_icv=FALSE; if ((fp->maxid != MI_ERROR) && (fp->minid != MI_ERROR) && (fp->datatype!=NC_FLOAT) && (fp->datatype!=NC_DOUBLE)) { check_imageminmax(fp, in_vol->volume); } /* Get space for volume data */ total_size = 1; for (idim=0; idim < WORLD_NDIMS; idim++) { index = input_volume_def.axes[idim]; size = input_volume_def.nelements[idim]; total_size *= size; in_vol->volume->size[index] = size; } in_vol->volume->data = malloc((size_t) total_size * nctypelen(in_vol->volume->datatype)); /* Get space for slice scale and offset */ in_vol->volume->scale = malloc(sizeof(double) * in_vol->volume->size[SLC_AXIS]); in_vol->volume->offset = malloc(sizeof(double) * in_vol->volume->size[SLC_AXIS]); /* Save the program flags */ *program_flags = args.flags; /* Set the default output file datatype */ if (args.datatype == MI_ORIGINAL_TYPE) args.datatype = in_vol->file->datatype; /* Explicitly force output files to have regular spacing */ for (idim=0; idim < WORLD_NDIMS; idim++) { if (args.volume_def.coords[idim] != NULL) { free(args.volume_def.coords[idim]); args.volume_def.coords[idim] = NULL; } } /* Check to see if sign and range have been explicitly set. If not set them now */ if (args.is_signed == INT_MIN) { if (args.datatype == in_vol->file->datatype) args.is_signed = in_vol->file->is_signed; else args.is_signed = (args.datatype != NC_BYTE); } if (args.vrange[0] == -DBL_MAX) { if ((args.datatype == in_vol->file->datatype) && (args.is_signed == in_vol->file->is_signed)) { args.vrange[0] = in_vol->file->vrange[0]; args.vrange[1] = in_vol->file->vrange[1]; } else { args.vrange[0] = get_default_range(MIvalid_min, args.datatype, args.is_signed); args.vrange[1] = get_default_range(MIvalid_max, args.datatype, args.is_signed); } } /* Set up the file description for the output file */ out_vol->file = malloc(sizeof(File_Info)); out_vol->file->ndims = in_vol->file->ndims; out_vol->file->datatype = args.datatype; out_vol->file->is_signed = args.is_signed; out_vol->file->vrange[0] = args.vrange[0]; out_vol->file->vrange[1] = args.vrange[1]; for (idim=0; idim < out_vol->file->ndims; idim++) { out_vol->file->nelements[idim] = in_vol->file->nelements[idim]; out_vol->file->world_axes[idim] = in_vol->file->world_axes[idim]; } out_vol->file->keep_real_range = args.keep_real_range; /* Get space for output slice */ out_vol->volume = NULL; out_vol->slice = malloc(sizeof(Slice_Data)); /* Loop through list of axes, getting size of volume and slice */ total_size = 1; for (idim=0; idim < WORLD_NDIMS; idim++) { /* Get the index for input and output volumes */ out_vindex = args.volume_def.axes[idim]; /* 0, 1 or 2 */ out_findex = in_vol->file->indices[out_vindex]; /* 0 to ndims-1 */ size = args.volume_def.nelements[idim]; /* Update output axes and indices and nelements */ out_vol->file->nelements[out_findex] = size; out_vol->file->world_axes[out_findex] = idim; out_vol->file->axes[idim] = out_vindex; out_vol->file->indices[out_vindex] = out_findex; /* Update slice size */ if (out_vindex != 0) { out_vol->slice->size[out_vindex-1] = size; total_size *= size; } } out_vol->slice->data = malloc((size_t) total_size * sizeof(double)); /* Create the output file */ if (args.clobber) { cflags = NC_CLOBBER; } else { cflags = NC_NOCLOBBER; } #if MINC2 if (args.v2format) { cflags |= MI2_CREATE_V2; } #endif /* MINC2 */ create_output_file(outfile, cflags, &args.volume_def, in_vol->file, out_vol->file, tm_stamp, &args.transform_info); /* Save the voxel_to_world transformation information */ out_vol->voxel_to_world = malloc(sizeof(General_transform)); out_vol->world_to_voxel = malloc(sizeof(General_transform)); get_voxel_to_world_transf(&args.volume_def, out_vol->voxel_to_world); create_inverse_general_transform(out_vol->voxel_to_world, out_vol->world_to_voxel); /* Free the time stamp */ free(tm_stamp); } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_imageminmax @INPUT : fp - pointer to file description volume - pointer to volume description @OUTPUT : @RETURNS : (nothing) @DESCRIPTION: Routine to check that MIimagemax and MIimagemin do not vary over volume rows and columns. If they do, set up an icv to handle it. @METHOD : @GLOBALS : @CALLS : @CREATED : August 5, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void check_imageminmax(File_Info *fp, Volume_Data *volume) { int ndims, idim, dim[MAX_VAR_DIMS], imgdim[MAX_VAR_DIMS]; int ivar, varid; /* Get MIimage dimensions */ (void) ncvarinq(fp->mincid, fp->imgid, NULL, NULL, &ndims, imgdim, NULL); /* Check MIimagemax/min dimensions */ for (ivar=0; ivar<2; ivar++) { varid = (ivar==0 ? fp->maxid : fp->minid); (void) ncvarinq(fp->mincid, varid, NULL, NULL, &ndims, dim, NULL); for (idim=0; idim < ndims; idim++) { if ((dim[idim] == imgdim[fp->indices[ROW_AXIS]]) || (dim[idim] == imgdim[fp->indices[COL_AXIS]])) { fp->using_icv = TRUE; } } /* End loop over MIimagemax/min dimensions */ } /* End loop over variables MIimagemax/min */ /* Set up an icv if needed to handle values varying over slice dims. */ if (fp->using_icv) { /* Change type to floating point so that there is no loss of precision (except possibly for long values). */ if (volume->datatype != NC_DOUBLE) volume->datatype = NC_FLOAT; volume->is_signed = TRUE; /* Create the icv */ fp->icvid = miicv_create(); (void) miicv_setint(fp->icvid, MI_ICV_TYPE, volume->datatype); (void) miicv_setstr(fp->icvid, MI_ICV_SIGN, (volume->is_signed ? MI_SIGNED : MI_UNSIGNED)); (void) miicv_setint(fp->icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(fp->icvid, MI_ICV_DO_FILLVALUE, TRUE); (void) miicv_attach(fp->icvid, fp->mincid, fp->imgid); /* Get max and min for doing valid range checking */ (void) miicv_inqdbl(fp->icvid, MI_ICV_NORM_MIN, &volume->vrange[0]); (void) miicv_inqdbl(fp->icvid, MI_ICV_NORM_MAX, &volume->vrange[1]); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_file_info @INPUT : filename - name of file to read initialized_volume_def - if TRUE, then volume_def is taken as being properly initialized and arrays are freed if non-NULL. Otherwise arrays are not freed. @OUTPUT : volume_def - description of volume file_info - description of file @RETURNS : (nothing) @DESCRIPTION: Routine to get information about the volume definition of a minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : February 9, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_file_info(char *filename, int initialized_volume_def, Volume_Definition *volume_def, File_Info *file_info) { int dim[MAX_VAR_DIMS], dimid; int axis_counter, idim, jdim, cur_axis; int varndims, vardim[MAX_VAR_DIMS]; long varstart, varcount, dimlength; char attstr[MI_MAX_ATTSTR_LEN]; char dimname[MAX_NC_NAME]; enum {UNKNOWN, REGULAR, IRREGULAR} coord_spacing; /* Open the minc file */ file_info->mincid = miopen(filename, NC_NOWRITE); file_info->name = filename; /* Get variable identifiers */ file_info->imgid = ncvarid(file_info->mincid, MIimage); ncopts = 0; file_info->maxid = ncvarid(file_info->mincid, MIimagemax); file_info->minid = ncvarid(file_info->mincid, MIimagemin); ncopts = NC_VERBOSE | NC_FATAL; /* Get information about datatype dimensions of variable */ (void) miget_datatype(file_info->mincid, file_info->imgid, &file_info->datatype, &file_info->is_signed); /* Get valid max and min */ (void) miget_valid_range(file_info->mincid, file_info->imgid, file_info->vrange); /* Get information about dimensions */ (void) ncvarinq(file_info->mincid, file_info->imgid, NULL, NULL, &file_info->ndims, dim, NULL); /* Set variables for keeping track of spatial dimensions */ axis_counter = 0; /* Keeps track of values for axes */ /* Initialize volume definition variables */ for (idim=0; idim < WORLD_NDIMS; idim++) { volume_def->axes[idim] = NO_AXIS; volume_def->step[idim] = 1.0; volume_def->start[idim] = 0.0; for (jdim=0; jdim < WORLD_NDIMS; jdim++) { if (jdim==idim) volume_def->dircos[idim][jdim] = 1.0; else volume_def->dircos[idim][jdim] = 0.0; } if (initialized_volume_def && (volume_def->coords[idim] != NULL)) { free(volume_def->coords[idim]); } volume_def->coords[idim] = NULL; (void) strcpy(volume_def->units[idim], "mm"); (void) strcpy(volume_def->spacetype[idim], MI_NATIVE); } /* Loop through dimensions, getting dimension information */ for (idim=0; idim < file_info->ndims; idim++) { /* Get size of dimension */ (void) ncdiminq(file_info->mincid, dim[idim], dimname, &file_info->nelements[idim]); /* Check variable name */ cur_axis = NO_AXIS; if (strcmp(dimname, MIxspace)==0) cur_axis = XAXIS; else if (strcmp(dimname, MIyspace)==0) cur_axis = YAXIS; else if (strcmp(dimname, MIzspace)==0) cur_axis = ZAXIS; /* Save world axis info */ file_info->world_axes[idim] = cur_axis; /* Check for spatial dimension */ if (cur_axis == NO_AXIS) continue; /* Set axis */ if (volume_def->axes[cur_axis] != NO_AXIS) { (void) fprintf(stderr, "Repeated spatial dimension %s in file %s.\n", dimname, filename); exit(EXIT_FAILURE); } volume_def->axes[cur_axis] = axis_counter++; /* Save spatial axis specific info */ file_info->axes[cur_axis] = volume_def->axes[cur_axis]; file_info->indices[volume_def->axes[cur_axis]] = idim; volume_def->nelements[cur_axis] = file_info->nelements[idim]; /* Check for existence of variable */ ncopts = 0; dimid = ncvarid(file_info->mincid, dimname); ncopts = NC_VERBOSE | NC_FATAL; if (dimid == MI_ERROR) continue; /* Get attributes from variable */ ncopts = 0; (void) miattget1(file_info->mincid, dimid, MIstep, NC_DOUBLE, &volume_def->step[cur_axis]); if (volume_def->step[cur_axis] == 0.0) volume_def->step[cur_axis] = 1.0; (void) miattget1(file_info->mincid, dimid, MIstart, NC_DOUBLE, &volume_def->start[cur_axis]); (void) miattget(file_info->mincid, dimid, MIdirection_cosines, NC_DOUBLE, WORLD_NDIMS, volume_def->dircos[cur_axis], NULL); (void) miattgetstr(file_info->mincid, dimid, MIunits, MI_MAX_ATTSTR_LEN, volume_def->units[cur_axis]); (void) miattgetstr(file_info->mincid, dimid, MIspacetype, MI_MAX_ATTSTR_LEN, volume_def->spacetype[cur_axis]); ncopts = NC_VERBOSE | NC_FATAL; /* Normalize the direction cosine */ normalize_vector(volume_def->dircos[cur_axis]); /* Look for irregular coordinates for dimension variable */ ncopts = 0; coord_spacing = UNKNOWN; dimlength = volume_def->nelements[cur_axis]; if (miattgetstr(file_info->mincid, dimid, MIspacing, MI_MAX_ATTSTR_LEN, attstr) != NULL) { if (strcmp(attstr, MI_IRREGULAR) == 0) coord_spacing = IRREGULAR; else if (strcmp(attstr, MI_REGULAR) == 0) coord_spacing = REGULAR; } if (ncvarinq(file_info->mincid, dimid, NULL, NULL, &varndims, vardim, NULL) == MI_ERROR) { ncopts = NC_VERBOSE | NC_FATAL; continue; } if ((coord_spacing != REGULAR) && (varndims == 1) && (vardim[0] == dim[idim])) { coord_spacing = IRREGULAR; } if ((coord_spacing == UNKNOWN) || (dimlength <= 1)) { coord_spacing = REGULAR; } if (coord_spacing == IRREGULAR) { volume_def->coords[cur_axis] = malloc(sizeof(double) * dimlength); varstart = 0; varcount = dimlength; if (mivarget(file_info->mincid, dimid, &varstart, &varcount, NC_DOUBLE, MI_SIGNED, volume_def->coords[cur_axis]) == MI_ERROR) { ncopts = NC_VERBOSE | NC_FATAL; free(volume_def->coords[cur_axis]); volume_def->coords[cur_axis] = NULL; continue; } volume_def->start[cur_axis] = volume_def->coords[cur_axis][0]; if (dimlength > 1) { volume_def->step[cur_axis] = (volume_def->coords[cur_axis][dimlength-1] - volume_def->coords[cur_axis][0]) / (dimlength - 1); if (volume_def->step[cur_axis] == 0.0) volume_def->step[cur_axis] = 1.0; } } ncopts = NC_VERBOSE | NC_FATAL; } /* End of loop over dimensions */ /* Check that we have the correct number of spatial dimensions */ if (axis_counter != WORLD_NDIMS) { (void) fprintf(stderr, "Incorrect number of spatial dimensions in file %s.\n", filename); exit(EXIT_FAILURE); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_args_volume_def @INPUT : input_volume_def - description of input volume @OUTPUT : args_volume_def - description of new output volume @RETURNS : (nothing) @DESCRIPTION: Routine to copy appropriate information from input volume definition to output volume definition, overriding values not set on the command line. @METHOD : @GLOBALS : @CALLS : @CREATED : November 7, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_args_volume_def(Volume_Definition *input_volume_def, Volume_Definition *args_volume_def) { int idim, jdim; /* Loop over dimensions */ for (idim=0; idim < WORLD_NDIMS; idim++) { /* Copy values, as needed */ if (args_volume_def->axes[idim] == NO_AXIS) args_volume_def->axes[idim] = input_volume_def->axes[idim]; if (args_volume_def->nelements[idim] == 0) args_volume_def->nelements[idim] = input_volume_def->nelements[idim]; if (args_volume_def->step[idim] == 0.0) args_volume_def->step[idim] = input_volume_def->step[idim]; if (args_volume_def->start[idim] == NO_VALUE) args_volume_def->start[idim] = input_volume_def->start[idim]; if (args_volume_def->dircos[idim][0] == NO_VALUE) { for (jdim=0; jdim < WORLD_NDIMS; jdim++) args_volume_def->dircos[idim][jdim] = input_volume_def->dircos[idim][jdim]; } if (strlen(args_volume_def->units[idim]) == 0) (void) strcpy(args_volume_def->units[idim], input_volume_def->units[idim]); if (strlen(args_volume_def->spacetype[idim]) == 0) (void) strcpy(args_volume_def->spacetype[idim], input_volume_def->spacetype[idim]); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : transform_volume_def @INPUT : transform_info - description of output to input transform (if NULL, then don't transform). input_volume_def - description of input volume @OUTPUT : transformed_volume_def - description of new output volume @RETURNS : (nothing) @DESCRIPTION: Routine to copy appropriate information from input volume definition to a new volume definition, after transformation from with the output to input transform. @METHOD : @GLOBALS : @CALLS : @CREATED : November 7, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void transform_volume_def(Transform_Info *transform_info, Volume_Definition *input_volume_def, Volume_Definition *transformed_volume_def) { int idim, jdim; Coord_Vector origin = {0, 0, 0}; Coord_Vector transformed_origin, vector; double length, nelements; /* Copy the volume definition */ *transformed_volume_def = *input_volume_def; /* Modify things if the transform has changed */ if ((transform_info != NULL) && (transform_info->file_name != NULL)) { /* Set up origin vector */ for (idim=0; idim < WORLD_NDIMS; idim++) for (jdim=0; jdim < WORLD_NDIMS; jdim++) origin[idim] += input_volume_def->start[jdim] * input_volume_def->dircos[jdim][idim]; /* Transform origin vector */ DO_INVERSE_TRANSFORM(transformed_origin, transform_info->transformation, origin); /* Loop over dimensions */ for (idim=0; idim < WORLD_NDIMS; idim++) { /* Get number of elements */ nelements = input_volume_def->nelements[idim] - 1; if (nelements < 1) nelements = 1.0; /* Transform whole axis */ VECTOR_SCALAR_MULT(vector, input_volume_def->dircos[idim], nelements * input_volume_def->step[idim]); VECTOR_ADD(vector, vector, origin); DO_INVERSE_TRANSFORM(vector, transform_info->transformation, vector); VECTOR_DIFF(vector, vector, transformed_origin); /* Calculate length of transformed axis - new step value */ length = sqrt(vector[XCOORD]*vector[XCOORD] + vector[YCOORD]*vector[YCOORD] + vector[ZCOORD]*vector[ZCOORD]); transformed_volume_def->step[idim] = length / nelements; /* Calculate new direction cosines */ for (jdim=0; jdim < WORLD_NDIMS; jdim++) { transformed_volume_def->dircos[idim][jdim] = (length > 0.0 ? vector[jdim] / length : (jdim == idim ? 1.0 : 0.0)); } /* Make sure that direction cosines point the right way */ if (transformed_volume_def->dircos[idim][idim] < 0.0) { VECTOR_SCALAR_MULT(transformed_volume_def->dircos[idim], transformed_volume_def->dircos[idim], -1.0); transformed_volume_def->step[idim] *= -1.0; } } /* Calculate the start along each axis - check for bad dircos. */ if (convert_origin_to_start(transformed_origin, transformed_volume_def->dircos[XCOORD], transformed_volume_def->dircos[YCOORD], transformed_volume_def->dircos[ZCOORD], transformed_volume_def->start) != 0) { /* If dircos are bad, set them to default */ for (idim=0; idim < WORLD_NDIMS; idim++) { for (jdim=0; jdim < WORLD_NDIMS; jdim++) { transformed_volume_def->dircos[idim][jdim] = ((idim==jdim) ? 1.0 : 0.0); } } /* Try to convert point again */ if (convert_origin_to_start(transformed_origin, transformed_volume_def->dircos[XCOORD], transformed_volume_def->dircos[YCOORD], transformed_volume_def->dircos[ZCOORD], transformed_volume_def->start) != 0) { (void) fprintf(stderr, "Serious problem converting origin to start!\n"); exit(EXIT_FAILURE); } } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : is_zero_vector @INPUT : vector - 3D vector @OUTPUT : (none) @RETURNS : 1 if vector has zero length, 0 otherwise @DESCRIPTION: Routine to check for a zero length vector. @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int is_zero_vector(double vector[]) { return ((vector[0] == 0.0) && (vector[1] == 0.0) && (vector[2] == 0.0)); } /* ----------------------------- MNI Header ----------------------------------- @NAME : normalize_vector @INPUT : vector - 3D vector @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to normalize a vector @METHOD : @GLOBALS : @CALLS : @CREATED : November 9, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void normalize_vector(double vector[]) { int idim; double magnitude; /* Normalize the direction cosine */ magnitude = 0.0; for (idim=0; idim < WORLD_NDIMS; idim++) { magnitude += (vector[idim] * vector[idim]); } magnitude = sqrt(magnitude); if (magnitude > 0.0) { for (idim=0; idim < WORLD_NDIMS; idim++) { vector[idim] /= magnitude; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_output_file @INPUT : filename - name of file to create cflags - flag creation flags volume_def - description of volume in_file - description of input file out_file - description of output file tm_stamp - string describing program invocation transformation - transformation to be applied to data @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to create an minc output file and set up its parameters properly. @METHOD : @GLOBALS : @CALLS : @CREATED : February 9, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void create_output_file(char *filename, int cflags, Volume_Definition *volume_def, File_Info *in_file, File_Info *out_file, char *tm_stamp, Transform_Info *transform_info) { int ndims, in_dims[MAX_VAR_DIMS], out_dims[MAX_VAR_DIMS]; int out_maxmin_dims[MAX_VAR_DIMS]; char dimname[MAX_NC_NAME]; int nmaxmin_dims, nimage_dims, axis, idim, dimid, varid, itrans; int att_length; nc_type datatype; int nexcluded, excluded_vars[10]; char *string; int dim_exists, is_volume_dimension; int in_index, out_index; /* Save the file name */ out_file->name = filename; /* Create the list of excluded variables */ nexcluded = 0; ncopts = 0; if ((varid=ncvarid(in_file->mincid, MIxspace)) != MI_ERROR) excluded_vars[nexcluded++] = varid; if ((varid=ncvarid(in_file->mincid, MIyspace)) != MI_ERROR) excluded_vars[nexcluded++] = varid; if ((varid=ncvarid(in_file->mincid, MIzspace)) != MI_ERROR) excluded_vars[nexcluded++] = varid; if ((varid=ncvarid(in_file->mincid, MIimage)) != MI_ERROR) excluded_vars[nexcluded++] = varid; if ((varid=ncvarid(in_file->mincid, MIimagemax)) != MI_ERROR) excluded_vars[nexcluded++] = varid; if ((varid=ncvarid(in_file->mincid, MIimagemin)) != MI_ERROR) excluded_vars[nexcluded++] = varid; #if MINC2 if ((varid=ncvarid(in_file->mincid, MIvector_dimension)) != MI_ERROR) excluded_vars[nexcluded++] = varid; #endif /* MINC2 */ ncopts = NC_VERBOSE | NC_FATAL; /* Create the file */ out_file->mincid = micreate(filename, cflags); /* Copy all other variable definitions */ (void) micopy_all_var_defs(in_file->mincid, out_file->mincid, nexcluded, excluded_vars); /* Add the time stamp */ ncopts=0; if ((ncattinq(out_file->mincid, NC_GLOBAL, MIhistory, &datatype, &att_length) == MI_ERROR) || (datatype != NC_CHAR)) att_length = 0; att_length += strlen(tm_stamp) + 1; string = malloc(att_length); string[0] = '\0'; (void) miattgetstr(out_file->mincid, NC_GLOBAL, MIhistory, att_length, string); ncopts=NC_VERBOSE | NC_FATAL; (void) strcat(string, tm_stamp); (void) miattputstr(out_file->mincid, NC_GLOBAL, MIhistory, string); free(string); /* Get the dimension ids from the input file */ (void) ncvarinq(in_file->mincid, in_file->imgid, NULL, NULL, &ndims, in_dims, NULL); /* Check for screw-up on number of dimensions */ if (ndims != out_file->ndims) { (void) fprintf(stderr, "Error in number of dimensions for output file.\n"); exit(EXIT_FAILURE); } /* Create the dimensions for the image variable */ for (out_index=0; out_indexworld_axes[out_index] != NO_AXIS); /* Get the input index */ if (!is_volume_dimension) in_index = out_index; else { axis = out_file->world_axes[out_index]; if ((axis<0) || (axis>=WORLD_NDIMS)) { (void) fprintf(stderr, "Error creating dimensions for output file.\n"); exit(EXIT_FAILURE); } in_index = in_file->indices[in_file->axes[axis]]; } /* Get the dimension name from the input file */ (void) ncdiminq(in_file->mincid, in_dims[in_index], dimname, NULL); /* Check to see if the dimension already exists */ ncopts = 0; out_dims[out_index] = ncdimid(out_file->mincid, dimname); ncopts = NC_VERBOSE | NC_FATAL; dim_exists = (out_dims[out_index] != MI_ERROR); /* If we have a volume dimension and it exists already with the wrong size, then we must rename it */ if (is_volume_dimension && dim_exists && (out_file->nelements[out_index] != in_file->nelements[in_index])) { string = malloc(MAX_NC_NAME); ncopts = 0; idim = 0; do { (void) sprintf(string, "%s%d", dimname, idim); idim++; } while (ncdimid(out_file->mincid, string) != MI_ERROR); ncopts = NC_VERBOSE | NC_FATAL; (void) ncdimrename(out_file->mincid, out_dims[out_index], string); free(string); out_dims[out_index] = ncdimdef(out_file->mincid, dimname, out_file->nelements[out_index]); } else if (!dim_exists) out_dims[out_index] = ncdimdef(out_file->mincid, dimname, out_file->nelements[out_index]); /* If this is a volume dimension, create a variable */ if (is_volume_dimension) { /* Create the variable */ dimid = micreate_group_variable(out_file->mincid, dimname); (void) miattputdbl(out_file->mincid, dimid, MIstep, volume_def->step[axis]); (void) miattputdbl(out_file->mincid, dimid, MIstart, volume_def->start[axis]); (void) ncattput(out_file->mincid, dimid, MIdirection_cosines, NC_DOUBLE, WORLD_NDIMS, volume_def->dircos[axis]); (void) miattputstr(out_file->mincid, dimid, MIunits, volume_def->units[axis]); (void) miattputstr(out_file->mincid, dimid, MIspacetype, volume_def->spacetype[axis]); } /* If volume dimension */ } /* Loop over dimensions */ /* Create the image max and min variables. These do not vary over the volume rows and columns even if they are not image dimensions, so we have to copy down the elements of the array (excluding image dimensions). Compute number of slices (row,columns) in an image (minc file def'n) and number of images in the file. */ nimage_dims = 2; ncdiminq(out_file->mincid, out_dims[ndims-1], dimname, NULL); if (strcmp(dimname, MIvector_dimension)==0) nimage_dims++; nmaxmin_dims = 0; out_file->slices_per_image = 1; out_file->images_per_file = 1; for (idim=0; idimindices[COL_AXIS]) && (idim != out_file->indices[ROW_AXIS])) { if (idim < ndims-nimage_dims) { out_maxmin_dims[nmaxmin_dims] = out_dims[idim]; nmaxmin_dims++; out_file->images_per_file *= out_file->nelements[idim]; } else { out_file->slices_per_image *= out_file->nelements[idim]; } } } out_file->do_slice_renormalization = ((out_file->datatype != NC_FLOAT) && (out_file->datatype != NC_DOUBLE) && (out_file->slices_per_image > 1)); /* Create the variables */ out_file->maxid = micreate_std_variable(out_file->mincid, MIimagemax, NC_DOUBLE, nmaxmin_dims, out_maxmin_dims); if (in_file->maxid != MI_ERROR) (void) micopy_all_atts(in_file->mincid, in_file->maxid, out_file->mincid, out_file->maxid); out_file->minid = micreate_std_variable(out_file->mincid, MIimagemin, NC_DOUBLE, nmaxmin_dims, out_maxmin_dims); if (in_file->minid != MI_ERROR) (void) micopy_all_atts(in_file->mincid, in_file->minid, out_file->mincid, out_file->minid); /* Add transformation information to image processing variable if a transformation is given on the command line */ if (transform_info->file_name != NULL) { ncopts = 0; /* Get id of processing variable (create it if needed) */ varid = ncvarid(out_file->mincid, PROCESSING_VAR); if (varid == MI_ERROR) { varid = ncvardef(out_file->mincid, PROCESSING_VAR, NC_INT, 0, NULL); (void) miadd_child(out_file->mincid, ncvarid(out_file->mincid, MIrootvariable), varid); } /* Look for an unused transformation attribute */ string = malloc(MI_MAX_ATTSTR_LEN); itrans = 0; do { (void) sprintf(string, "transformation%d-filename", itrans); itrans++; } while (ncattinq(out_file->mincid, varid, string, NULL, NULL) != MI_ERROR); itrans--; /* Reset error handling */ ncopts = NC_VERBOSE | NC_FATAL; /* Add the attributes describing the transformation */ (void) miattputstr(out_file->mincid, varid, string, transform_info->file_name); (void) sprintf(string, "transformation%d-filedata", itrans); (void) miattputstr(out_file->mincid, varid, string, transform_info->file_contents); if (transform_info->invert_transform) { (void) sprintf(string, "transformation%d-inverted", itrans); (void) miattputstr(out_file->mincid, varid, string, MI_TRUE); } free(string); } /* If transform specified on command line */ /* Create the image variable */ out_file->imgid = micreate_std_variable(out_file->mincid, MIimage, out_file->datatype, ndims, out_dims); (void) micopy_all_atts(in_file->mincid, in_file->imgid, out_file->mincid, out_file->imgid); (void) miattputstr(out_file->mincid, out_file->imgid, MIcomplete, MI_FALSE); (void) miset_valid_range(out_file->mincid, out_file->imgid, out_file->vrange); if (out_file->is_signed) (void) miattputstr(out_file->mincid, out_file->imgid, MIsigntype, MI_SIGNED); else (void) miattputstr(out_file->mincid, out_file->imgid, MIsigntype, MI_UNSIGNED); /* Get into data mode */ (void) ncsetfill(out_file->mincid, NC_NOFILL); (void) ncendef(out_file->mincid); /* Copy all the other data */ (void) micopy_all_var_values(in_file->mincid, out_file->mincid, nexcluded, excluded_vars); /* Create and attach an icv */ out_file->using_icv = TRUE; out_file->icvid = miicv_create(); (void) miicv_setint(out_file->icvid, MI_ICV_TYPE, NC_DOUBLE); (void) miicv_setint(out_file->icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(out_file->icvid, MI_ICV_USER_NORM, TRUE); (void) miicv_attach(out_file->icvid, out_file->mincid, out_file->imgid); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_voxel_to_world_transf @INPUT : volume_def - description of volume @OUTPUT : voxel_to_world - transformation @RETURNS : (nothing) @DESCRIPTION: Routine to convert a Volume definition specification of sampling to a voxel-to-world transformation @METHOD : @GLOBALS : @CALLS : @CREATED : February 9, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_voxel_to_world_transf(Volume_Definition *volume_def, General_transform *voxel_to_world) { int idim, jdim, cur_dim, vol_axis; int irregular; long ielement, dimlength; Transform matrix; Irregular_Transform_Data *irreg_transf_data; General_transform linear_transf, irreg_transf; /* Make an identity matrix */ make_identity_transform(&matrix); /* Loop over rows of matrix */ for (idim=0; idimaxes[jdim]; /* Get rotation/scale components of matrix */ Transform_elem(matrix, idim, cur_dim) = volume_def->step[jdim] * volume_def->dircos[jdim][idim]; /* Get translation components */ Transform_elem(matrix, idim, VOL_NDIMS) += volume_def->start[jdim] * volume_def->dircos[jdim][idim]; } } /* Save the general transform */ create_linear_transform(voxel_to_world, &matrix); /* Check for an irregularly spaced dimension */ irregular = FALSE; for (idim=0; idim < WORLD_NDIMS; idim++) { if (volume_def->coords[idim] != NULL) irregular = TRUE; } /* If we have an irregularly spaced dimension, then create the appropriate transform */ if (irregular) { irreg_transf_data = malloc(sizeof(*irreg_transf_data)); /* Loop through the axes */ for (idim=0; idim < WORLD_NDIMS; idim++) { vol_axis = volume_def->axes[idim]; irreg_transf_data->last_index[vol_axis] = 0; /* Check whether the axis is irregularly spaced or not */ if (volume_def->coords[idim] == NULL) { irreg_transf_data->nelements[vol_axis] = 0; irreg_transf_data->coords[vol_axis] = NULL; } else { /* If irregular then get the number of elements and allocate space */ dimlength = volume_def->nelements[idim]; irreg_transf_data->nelements[vol_axis] = dimlength; irreg_transf_data->coords[vol_axis] = malloc(sizeof(double) * dimlength); /* Normalize the coordinates to give first coord 0 and last coord n-1 (so that we can concat with the linear transform already created */ for (ielement=0; ielement < dimlength; ielement++) { irreg_transf_data->coords[vol_axis][ielement] = (volume_def->coords[idim][ielement] - volume_def->start[idim]) / volume_def->step[idim]; } } } /* Create an irregular transform and free the data (we only free the Irregular_Transform_Data structure, not the coord pointers, since these arrays are not copied) */ create_user_transform(&irreg_transf, (void *) irreg_transf_data, sizeof(*irreg_transf_data), irregular_transform_function, irregular_inverse_transform_function); free(irreg_transf_data); /* Concatenate the linear transform with the irregular transform */ copy_general_transform(voxel_to_world, &linear_transf); delete_general_transform(voxel_to_world); concat_general_transforms(&irreg_transf, &linear_transf, voxel_to_world); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : irregular_transform_function @INPUT : user_data - pointer to user data x, y, z - coordinate to transform @OUTPUT : x_trans, y_trans, z_trans - resulting coordinate @RETURNS : (nothin) @DESCRIPTION: Routine to transform irregularly spaced coordinate to a regular spacing. @METHOD : @GLOBALS : @CALLS : @CREATED : November 4, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void irregular_transform_function(void *user_data, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans) { Irregular_Transform_Data *irreg_transf_data; int idim; long dimlength, index; double coord[VOL_NDIMS], coord_transf[VOL_NDIMS]; double frac; /* Get the pointer to the data */ irreg_transf_data = (Irregular_Transform_Data *) user_data; /* Get the coordinate */ coord[0] = x; coord[1] = y; coord[2] = z; /* Loop through axes, renormalizing coordinate */ for (idim=0; idim < VOL_NDIMS; idim++) { dimlength = irreg_transf_data->nelements[idim]; if (dimlength <= 1) { coord_transf[idim] = coord[idim]; } else { /* For irregular dimension, do linear interpolation between coords */ index = (long) coord[idim]; if (index < 0) index = 0; if (index > dimlength-2) index = dimlength-2; frac = coord[idim] - index; coord_transf[idim] = (1.0 - frac) * irreg_transf_data->coords[idim][index] + frac * irreg_transf_data->coords[idim][index + 1]; } } /* Save the coordinates */ *x_trans = coord_transf[0]; *y_trans = coord_transf[1]; *z_trans = coord_transf[2]; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : irregular_inverse_transform_function @INPUT : user_data - pointer to user data x, y, z - coordinate to transform @OUTPUT : x_trans, y_trans, z_trans - resulting coordinate @RETURNS : (nothin) @DESCRIPTION: Routine to transform irregularly spaced coordinate to a regular spacing. @METHOD : @GLOBALS : @CALLS : @CREATED : November 4, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void irregular_inverse_transform_function(void *user_data, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans) { Irregular_Transform_Data *irreg_transf_data; int idim, not_found; long dimlength, index; double coord[VOL_NDIMS], coord_transf[VOL_NDIMS]; double first, next, step, frac; /* Get the pointer to the data */ irreg_transf_data = (Irregular_Transform_Data *) user_data; /* Get the coordinate */ coord[0] = x; coord[1] = y; coord[2] = z; /* Loop through axes, renormalizing coordinate */ for (idim=0; idim < VOL_NDIMS; idim++) { dimlength = irreg_transf_data->nelements[idim]; if (dimlength <= 1) { coord_transf[idim] = coord[idim]; } else { /* Search for the closest index (checking for out-of-range values) */ index = irreg_transf_data->last_index[idim]; if (index < 0) index = 0; if (index > dimlength-2) index = dimlength-2; not_found = TRUE; while (not_found) { if (coord[idim] < irreg_transf_data->coords[idim][index]) { if (index > 0) index--; else { index = 0; not_found = FALSE; } } else if (coord[idim] > irreg_transf_data->coords[idim][index+1]) { if (index < dimlength-2) index++; else { index = dimlength-2; not_found = FALSE; } } else { not_found = FALSE; } } irreg_transf_data->last_index[idim] = index; /* Do linear interpolation */ first = irreg_transf_data->coords[idim][index]; next = irreg_transf_data->coords[idim][index + 1]; step = next - first; if (step == 0.0) frac = 0.0; else frac = (coord[idim] - first) / step; coord_transf[idim] = (1.0 - frac) * index + frac * (index + 1); } } /* Save the coordinates */ *x_trans = coord_transf[0]; *y_trans = coord_transf[1]; *z_trans = coord_transf[2]; return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_default_range @INPUT : what - MIvalid_min means get default min, MIvalid_min means get default min datatype - type of variable is_signed - TRUE if variable is signed @OUTPUT : (none) @RETURNS : default maximum or minimum for the datatype @DESCRIPTION: Return the defaults maximum or minimum for a given datatype and sign. @METHOD : @GLOBALS : @CALLS : @CREATED : August 10, 1992 (Peter Neelin) @MODIFIED : February 10, 1993 (Peter Neelin) - ripped off from MINC code ---------------------------------------------------------------------------- */ static double get_default_range(char *what, nc_type datatype, int is_signed) { double limit; if (strcmp(what, MIvalid_max)==0) { switch (datatype) { case NC_INT: limit = (is_signed) ? INT_MAX : UINT_MAX; break; case NC_SHORT: limit = (is_signed) ? SHRT_MAX : USHRT_MAX; break; case NC_BYTE: limit = (is_signed) ? SCHAR_MAX : UCHAR_MAX; break; default: limit = DEFAULT_MAX; break; } } else if (strcmp(what, MIvalid_min)==0) { switch (datatype) { case NC_INT: limit = (is_signed) ? INT_MIN : 0; break; case NC_SHORT: limit = (is_signed) ? SHRT_MIN : 0; break; case NC_BYTE: limit = (is_signed) ? SCHAR_MIN : 0; break; default: limit = DEFAULT_MIN; break; } } else { limit = 0.0; } return limit; } /* ----------------------------- MNI Header ----------------------------------- @NAME : finish_up @INPUT : in_vol - input volume out_vol - output volume @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to finish up at end of program, closing files, etc. @METHOD : @GLOBALS : @CALLS : @CREATED : February 15, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void finish_up(VVolume *in_vol, VVolume *out_vol) { File_Info *in_file, *out_file; /* Get file info pointers */ in_file = in_vol->file; out_file = out_vol->file; /* Close the output file */ (void) miattputstr(out_file->mincid, out_file->imgid, MIcomplete, MI_TRUE); if (out_file->using_icv) { (void) miicv_free(out_file->icvid); } (void) miclose(out_file->mincid); /* Close the input file */ if (in_file->using_icv) { (void) miicv_free(in_file->icvid); } (void) miclose(in_file->mincid); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transformation @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE so that ParseArgv will discard nextArg, unless there is no following argument. @DESCRIPTION: Routine called by ParseArgv to read in a transformation file @METHOD : @GLOBALS : @CALLS : @CREATED : February 15, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_transformation(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Transform_Info *transform_info; General_transform *transformation; FILE *fp; int ch, index; /* Check for following argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get pointer to transform info structure */ transform_info = (Transform_Info *) dst; /* Save file name */ transform_info->file_name = nextArg; transformation = transform_info->transformation; /* Open the file */ if (strcmp(nextArg, "-") == 0) { /* Create a temporary for standard input */ fp=tmpfile(); if (fp==NULL) { (void) fprintf(stderr, "Error opening temporary file.\n"); exit(EXIT_FAILURE); } while ((ch=getc(stdin))!=EOF) (void) putc(ch, fp); rewind(fp); } else { if (open_file_with_default_suffix(nextArg, get_default_transform_file_suffix(), READ_FILE, ASCII_FORMAT, &fp) != OK) { (void) fprintf(stderr, "Error opening transformation file %s.\n", nextArg); exit(EXIT_FAILURE); } } /* Read in the file for later use */ if (transform_info->file_contents == NULL) { transform_info->file_contents = malloc(TRANSFORM_BUFFER_INCREMENT); transform_info->buffer_length = TRANSFORM_BUFFER_INCREMENT; } for (index = 0; (ch=getc(fp)) != EOF; index++) { if (index >= transform_info->buffer_length-1) { transform_info->buffer_length += TRANSFORM_BUFFER_INCREMENT; transform_info->file_contents = realloc(transform_info->file_contents, transform_info->buffer_length); } transform_info->file_contents[index] = (char) ch; } transform_info->file_contents[index] = '\0'; rewind(fp); /* Get rid of the old transformation */ delete_general_transform(transformation); /* Read the file */ if (input_transform(fp, transform_info->file_name, transformation)!=OK) { (void) fprintf(stderr, "Error reading transformation file.\n"); exit(EXIT_FAILURE); } (void) close_file(fp); #ifdef TRANSFORM_CHANGE_KLUDGE Specified_transform = TRUE; #endif return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_model_file @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE so that ParseArgv will discard nextArg unless there is no following argument. @DESCRIPTION: Routine called by ParseArgv to read in a model file (-like) @METHOD : @GLOBALS : @CALLS : @CREATED : February 15, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_model_file(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Volume_Definition *volume_def; File_Info file; /* Check for following argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get pointer to volume definition structure */ volume_def = (Volume_Definition *) dst; /* Get file information */ get_file_info(nextArg, TRUE, volume_def, &file); /* Close the file */ (void) miclose(file.mincid); #ifdef TRANSFORM_CHANGE_KLUDGE Specified_like = TRUE; #endif return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_standard_sampling @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : FALSE so that ParseArgv will not discard nextArg. @DESCRIPTION: Routine called by ParseArgv to set the sampling to standard values (sets only step, start and direction cosines). @METHOD : @GLOBALS : @CALLS : @CREATED : November 14, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int set_standard_sampling(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Volume_Definition *volume_def; int idim, jdim; /* Get pointer to volume definition structure */ volume_def = (Volume_Definition *) dst; /* Set sensible values */ for (idim=0; idim < WORLD_NDIMS; idim++) { volume_def->step[idim] = 1.0; volume_def->start[idim] = 0.0; for (jdim=0; jdim < WORLD_NDIMS; jdim++) { volume_def->dircos[idim][jdim] = (idim == jdim ? 1.0 : 0.0); } } return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_spacetype @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE if nextArg should be discarded, FALSE otherwise @DESCRIPTION: Routine called by ParseArgv to set the space type of the output sampling. @METHOD : @GLOBALS : @CALLS : @CREATED : December 12, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int set_spacetype(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Volume_Definition *volume_def; char *spacetype; int idim; int return_value; /* Get pointer to client data */ volume_def = (Volume_Definition *) dst; /* Check key for spacetype */ return_value = FALSE; if (strcmp(key, "-talairach") == 0) { spacetype = MI_TALAIRACH; } else { /* Check for following argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } spacetype = nextArg; return_value = TRUE; } /* Copy the strings */ for (idim=0; idim < WORLD_NDIMS; idim++) { (void) strncpy(volume_def->spacetype[idim], spacetype, MI_MAX_ATTSTR_LEN); volume_def->spacetype[idim][MI_MAX_ATTSTR_LEN-1] = '\0'; } return return_value; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_units @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE if nextArg should be discarded, FALSE otherwise @DESCRIPTION: Routine called by ParseArgv to set the units of the output sampling. @METHOD : @GLOBALS : @CALLS : @CREATED : December 12, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int set_units(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Volume_Definition *volume_def; char *units; int idim; /* Get pointer to client data */ volume_def = (Volume_Definition *) dst; /* Check for following argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } units = nextArg; /* Copy the strings */ for (idim=0; idim < WORLD_NDIMS; idim++) { (void) strncpy(volume_def->units[idim], units, MI_MAX_ATTSTR_LEN); volume_def->units[idim][MI_MAX_ATTSTR_LEN-1] = '\0'; } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_axis_order @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : FALSE so that ParseArgv will not discard nextArg @DESCRIPTION: Routine called by ParseArgv to get the axis order @METHOD : @GLOBALS : @CALLS : @CREATED : February 15, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_axis_order(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Volume_Definition *volume_def; /* Get pointer to client data */ volume_def = (Volume_Definition *) dst; /* Check key for order */ if (strcmp(key, "-transverse") == 0) { volume_def->axes[Z] = 0; volume_def->axes[Y] = 1; volume_def->axes[X] = 2; } else if (strcmp(key, "-sagittal") == 0) { volume_def->axes[X] = 0; volume_def->axes[Z] = 1; volume_def->axes[Y] = 2; } else if (strcmp(key, "-coronal") == 0) { volume_def->axes[Y] = 0; volume_def->axes[Z] = 1; volume_def->axes[X] = 2; } return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_fillvalue @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : FALSE so that ParseArgv will not discard nextArg @DESCRIPTION: Routine called by ParseArgv to set the fill value @METHOD : @GLOBALS : @CALLS : @CREATED : February 15, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_fillvalue(char *dst, char *key, char *nextArg) /* ARGSUSED */ { double *dptr; /* Get pointer to client data */ dptr = (double *) dst; /* Check key for fill value to set */ if (strcmp(key, "-fill") == 0) { *dptr = -DBL_MAX; } else if (strcmp(key, "-nofill") == 0) { *dptr = FILL_DEFAULT; } return FALSE; } minc-2.2.00/progs/mincresample/resample_volumes.c0000644000265600003100000013772612027132663017020 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : resample_volumes.c @DESCRIPTION: File containing routines to resample minc volumes. @METHOD : @GLOBALS : @CREATED : February 8, 1993 (Peter Neelin) @MODIFIED : * $Log: resample_volumes.c,v $ * Revision 6.12 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.11 2008/01/13 09:49:00 stever * Add do_Ncubic_interpolation declaration, moved here from mincresample.h. * * Revision 6.10 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.9 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.8 2008/01/11 07:17:08 stever * Remove unused variables. * * Revision 6.7 2007/12/12 20:55:26 rotor * * added a bunch of bug fixes from Claude. * * Revision 6.6 2006/05/19 00:13:39 bert * Add config.h * * Revision 6.5 2005/07/13 21:34:25 bert * Add sinc interpolant (ported from 1.X branch) * * Revision 6.4 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.3 2001/08/16 13:32:39 neelin * Partial fix for valid_range of different type from image (problems * arising from double to float conversion/rounding). NOT COMPLETE. * * Revision 6.2 2001/04/02 14:58:10 neelin * Added -keep_real_range option to prevent rescaling of slices on output * * Revision 6.1 1999/10/19 14:45:28 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:21 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:22 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 19:59:42 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:30:57 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:32:50 neelin * Release of minc version 0.2 * * Revision 1.15 94/09/28 10:32:38 neelin * Pre-release * * Revision 1.14 94/03/15 10:58:47 neelin * Fixed tricubic interpolation (wasn't initializing variable for fillvalue * detection). * * Revision 1.13 94/03/01 14:33:48 neelin * Fixed error in calculating valid minimum for float volumes. * * Revision 1.12 93/11/02 11:23:52 neelin * Handle imagemax/min potentially varying over slices (for vector data, etc.) * * Revision 1.11 93/10/20 14:06:36 neelin * Modified tri-linear interpolation to allow volumes to extend epsilon * beyond the first voxel. * Added code to handle volume dimensions of size one (in tri-linear * interpolation). * * Revision 1.10 93/10/15 13:48:22 neelin * Removed include of recipes.h * * Revision 1.9 93/10/12 12:48:08 neelin * Use volume_io.h instead of def_mni.h * * Revision 1.8 93/08/11 14:29:53 neelin * Use volume->datatype in load_volume instead of file->datatype. * Loop for slice max/min is from 0, not 1 in load_volume. * * Revision 1.7 93/08/11 13:34:15 neelin * Converted to use Dave MacDonald's General_transform code. * Fixed bug in get_slice - for non-linear transformations coord was * transformed, then used again as a starting coordinate. * Handle files that have image-max/min that doesn't vary over slices. * Handle files that have image-max/min varying over row/cols. * Allow volume to extend to voxel edge for -nearest_neighbour interpolation. * Handle out-of-range values (-fill values from a previous mincresample, for * example). * Save transformation file as a string attribute to processing variable. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "mincresample.h" static void load_volume(File_Info *file, long start[], long count[], Volume_Data *volume); static void get_slice(long slice_num, VVolume *in_vol, VVolume *out_vol, General_transform *transformation, double *minimum, double *maximum); static void renormalize_slices(Program_Flags *program_flags, VVolume *out_vol, double slice_min[], double slice_max[]); static int do_Ncubic_interpolation(Volume_Data *volume, long index[], int cur_dim, double frac[], double *result); /* ----------------------------- MNI Header ----------------------------------- @NAME : resample_volumes @INPUT : program_flags - data for program execution in_vol - description of input volume out_vol - description of output volume transformation - description of world transformation @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Resamples in_vol into file specified by out_vol using given world transformation. @METHOD : @GLOBALS : @CALLS : @CREATED : February 8, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void resample_volumes(Program_Flags *program_flags, VVolume *in_vol, VVolume *out_vol, General_transform *transformation) { long in_start[MAX_VAR_DIMS], in_count[MAX_VAR_DIMS], in_end[MAX_VAR_DIMS]; long out_start[MAX_VAR_DIMS], out_count[MAX_VAR_DIMS]; long mm_start[MAX_VAR_DIMS]; /* Vector for min/max variables */ long nslice, islice, slice_count; int idim, index, slice_index; double maximum, minimum, valid_range[2]; double *slice_max, *slice_min; File_Info *ifp,*ofp; /* Set pointers to file information */ ifp = in_vol->file; ofp = out_vol->file; /* Allocate slice min/max arrays if needed */ if (ofp->do_slice_renormalization) { slice_min = malloc(ofp->images_per_file * ofp->slices_per_image * sizeof(double)); slice_max = malloc(ofp->images_per_file * ofp->slices_per_image * sizeof(double)); } /* Set input file start, count and end vectors for reading a volume at a time */ (void) miset_coords(ifp->ndims, (long) 0, in_start); (void) miset_coords(ifp->ndims, (long) 1, in_count); for (idim=0; idim < ifp->ndims; idim++) { in_end[idim] = ifp->nelements[idim]; } for (idim=0; idim < VOL_NDIMS; idim++) { index = ifp->indices[idim]; in_count[index] = ifp->nelements[index]; } /* Set output file count for writing a slice and get the number of output slices */ (void) miset_coords(ifp->ndims, (long) 1, out_count); for (idim=0; idim < VOL_NDIMS; idim++) { index = ofp->indices[idim]; if (idim==0) { slice_index = index; nslice = ofp->nelements[index]; } else { out_count[index] = ofp->nelements[index]; } } /* Initialize global max and min */ valid_range[0] = DBL_MAX; valid_range[1] = -DBL_MAX; /* Initialize file max/min slice count */ slice_count = 0; /* Print log message */ if (program_flags->verbose) { (void) fprintf(stderr, "Transforming slices:"); (void) fflush(stderr); } /* Loop over input volumes */ while (in_start[0] < in_end[0]) { /* Copy the start vector */ for (idim=0; idim < ifp->ndims; idim++) out_start[idim] = in_start[idim]; /* Read in the volume */ load_volume(ifp, in_start, in_count, in_vol->volume); /* Loop over slices */ for (islice=0; islice < nslice; islice++) { /* Print log message */ if (program_flags->verbose) { (void) fprintf(stderr, "."); (void) fflush(stderr); } /* Set slice number in out_start */ out_start[slice_index] = islice; /* Get the slice */ get_slice(islice, in_vol, out_vol, transformation, &minimum, &maximum); /* Check whether we are keep the input range */ if (ofp->keep_real_range) { minimum = in_vol->volume->real_range[0]; maximum = in_vol->volume->real_range[1]; } /* Update global max and min */ if (maximum > valid_range[1]) valid_range[1] = maximum; if (minimum < valid_range[0]) valid_range[0] = minimum; /* Write the max, min and slice */ (void) mivarput1(ofp->mincid, ofp->maxid, mitranslate_coords(ofp->mincid, ofp->imgid, out_start, ofp->maxid, mm_start), NC_DOUBLE, NULL, &maximum); (void) mivarput1(ofp->mincid, ofp->minid, mitranslate_coords(ofp->mincid, ofp->imgid, out_start, ofp->minid, mm_start), NC_DOUBLE, NULL, &minimum); (void) miicv_put(ofp->icvid, out_start, out_count, out_vol->slice->data); /* Save the max, min if needed */ if (ofp->do_slice_renormalization) { slice_max[slice_count] = maximum; slice_min[slice_count] = minimum; } /* Increment slice count */ slice_count++; } /* End loop over slices */ /* Increment in_start counter */ idim = ofp->ndims-1; in_start[idim] += in_count[idim]; while ( (idim>0) && (in_start[idim] >= in_end[idim])) { in_start[idim] = 0; idim--; in_start[idim] += in_count[idim]; } } /* End loop over volumes */ /* Print end of log message */ if (program_flags->verbose) { (void) fprintf(stderr, "Done\n"); (void) fflush(stderr); } /* If output volume is floating point, write out global max and min */ if ((ofp->datatype == NC_FLOAT) || (ofp->datatype == NC_DOUBLE)) { (void) miset_valid_range(ofp->mincid, ofp->imgid, valid_range); } /* Recompute slices and free vectors, if needed */ if (ofp->do_slice_renormalization) { renormalize_slices(program_flags, out_vol, slice_min, slice_max); free(slice_min); free(slice_max); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : load_volume @INPUT : file - description of input file start - index of start of volume in minc file count - vector size of volume in minc file volume - description of volume data @OUTPUT : volume - contains new volume data and scales and offsets @RETURNS : (none) @DESCRIPTION: Loads a volume from a minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void load_volume(File_Info *file, long start[], long count[], Volume_Data *volume) { long nread, islice, mm_start[MAX_VAR_DIMS], mm_count[MAX_VAR_DIMS]; int varid, ivar, idim, ndims; double *values, maximum, minimum, denom; /* Load the file */ if (file->using_icv) { (void) miicv_get(file->icvid, start, count, volume->data); } else { (void) ncvarget(file->mincid, file->imgid, start, count, volume->data); } /* Read the max and min from the file into the scale and offset variables (maxima into scale and minima into offset) if datatype is not floating point */ /* Don't do it ourselves if the icv is doing it for us */ if (file->using_icv) { for (islice=0; islice < volume->size[SLC_AXIS]; islice++) { (void) miicv_inqdbl(file->icvid, MI_ICV_NORM_MAX, &volume->scale[islice]); (void) miicv_inqdbl(file->icvid, MI_ICV_NORM_MIN, &volume->offset[islice]); } } /* If either max/min variable doesn't exist, or if type is floating point, then set max to 1 and min to 0 */ else if ((file->maxid == MI_ERROR) || (file->minid == MI_ERROR) || (volume->datatype == NC_FLOAT) || (volume->datatype == NC_DOUBLE)) { for (islice=0; islice < volume->size[SLC_AXIS]; islice++) { volume->scale[islice] = DEFAULT_MAX; volume->offset[islice] = DEFAULT_MIN; } } /* Otherwise the imagemax/min variables exist - use them for integer types */ else { for (ivar=0; ivar<2; ivar++) { /* Set up variables */ varid = (ivar == 0 ? file->maxid : file->minid); values = (ivar == 0 ? volume->scale : volume->offset); /* Read max or min */ (void) mivarget(file->mincid, varid, mitranslate_coords(file->mincid, file->imgid, start, varid, miset_coords(MAX_VAR_DIMS, 0L, mm_start)), mitranslate_coords(file->mincid, file->imgid, count, varid, miset_coords(MAX_VAR_DIMS, 1L, mm_count)), NC_DOUBLE, NULL, values); /* Check for number of values read */ (void) ncvarinq(file->mincid, varid, NULL, NULL, &ndims, NULL, NULL); for (nread=1, idim=0; idimsize[SLC_AXIS]; islice++) { values[islice] = values[0]; } } else if (nread != volume->size[SLC_AXIS]) { (void) fprintf(stderr, "Program bug while reading image max/min\n"); exit(EXIT_FAILURE); } } /* Loop over max/min variables */ } /* If max/min variables both exist */ /* Get the real range of this volume (offset is min, scale is max) */ volume->real_range[0] = volume->offset[0]; volume->real_range[1] = volume->scale[0]; for (islice=1; islice < volume->size[SLC_AXIS]; islice++) { if (volume->offset[islice] < volume->real_range[0]) volume->real_range[0] = volume->offset[islice]; if (volume->scale[islice] > volume->real_range[1]) volume->real_range[1] = volume->scale[islice]; } /* Calculate the scale and offset */ for (islice=0; islice < volume->size[SLC_AXIS]; islice++) { /* If the variables type is floating point, then don't scale */ if ((volume->datatype==NC_FLOAT) || (volume->datatype==NC_DOUBLE)) { volume->scale[islice] = 1.0; volume->offset[islice] = 0.0; } /* Otherwise, calculate scale and offset */ else { maximum = volume->scale[islice]; minimum = volume->offset[islice]; denom = file->vrange[1] - file->vrange[0]; if (denom != 0.0) { volume->scale[islice] = (maximum - minimum) / denom; } else { volume->scale[islice] = 0.0; } volume->offset[islice] = minimum - file->vrange[0] * volume->scale[islice]; } } /* End of loop through slices */ } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_slice @INPUT : in_vol - description of input volume out_vol - description of output volume transformation - description of world transformation @OUTPUT : out_vol - slice field contains new slice minimum - slice minimum (excluding data from outside volume) maximum - slice maximum (excluding data from outside volume) @RETURNS : (none) @DESCRIPTION: Resamples current volume of in_vol into slice in out_vol using given world transformation. @METHOD : @GLOBALS : @CALLS : @CREATED : February 8, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void get_slice(long slice_num, VVolume *in_vol, VVolume *out_vol, General_transform *transformation, double *minimum, double *maximum) { Slice_Data *slice; Volume_Data *volume; double *dptr; long irow, icol; int all_linear; int idim; /* Coordinate vectors for stepping through slice */ Coord_Vector zero = {0, 0, 0}; Coord_Vector column = {0, 0, 1}; Coord_Vector row = {0, 1, 0}; Coord_Vector start = {0, 0, 0}; /* start[SLICE] set later to slice_num */ Coord_Vector coord, transf_coord; /* Transformation stuff */ General_transform total_transf, temp_transf; /* Get slice and volume pointers */ volume = in_vol->volume; slice = out_vol->slice; /* Concatenate transforms */ concat_general_transforms(out_vol->voxel_to_world, transformation, &temp_transf); concat_general_transforms(&temp_transf, in_vol->world_to_voxel, &total_transf); delete_general_transform(&temp_transf); /* Check for complete linear transformation */ all_linear = (get_transform_type(&total_transf) == LINEAR); /* Transform vectors for linear transformation */ start[SLICE] = slice_num; if (all_linear) { DO_TRANSFORM(zero, &total_transf, zero); DO_TRANSFORM(column, &total_transf, column); DO_TRANSFORM(row, &total_transf, row); DO_TRANSFORM(start, &total_transf, start); } /* Make sure that row and column are vectors and not points */ VECTOR_DIFF(row, row, zero); VECTOR_DIFF(column, column, zero); /* Initialize maximum and minimum */ *maximum = -DBL_MAX; *minimum = DBL_MAX; /* Loop over rows of slice */ for (irow=0; irow < slice->size[SLICE_ROW]; irow++) { /* Set starting coordinate of row */ VECTOR_SCALAR_MULT(coord, row, irow); VECTOR_ADD(coord, coord, start); /* Loop over columns */ dptr = slice->data + irow*slice->size[SLICE_COL]; for (icol=0; icol < slice->size[SLICE_COL]; icol++) { /* If transformation is not completely linear, then transform voxel to world, world to world and world to voxel, as needed */ for (idim=0; idimuse_fill) { if (*dptr > *maximum) *maximum = *dptr; if (*dptr < *minimum) *minimum = *dptr; } /* Increment coordinate */ VECTOR_ADD(coord, coord, column); /* Increment slice pointer */ dptr++; } /* Loop over columns */ } /* Loop over rows */ if ((*maximum == -DBL_MAX) && (*minimum == DBL_MAX)) { *minimum = 0.0; *maximum = SMALL_VALUE; } else if (*maximum <= *minimum) { if (*minimum == 0.0) *maximum = SMALL_VALUE; else if (*minimum < 0.0) *maximum = 0.0; else *maximum = 2.0 * (*minimum); } /* Delete the transformation */ delete_general_transform(&total_transf); } /* ----------------------------- MNI Header ----------------------------------- @NAME : trilinear_interpolant @INPUT : volume - pointer to volume data coord - point at which volume should be interpolated in voxel units (with 0 being first point of the volume). @OUTPUT : result - interpolated value. @RETURNS : TRUE if coord is within the volume, FALSE otherwise. @DESCRIPTION: Routine to interpolate a volume at a point with tri-linear interpolation. @METHOD : @GLOBALS : @CALLS : @CREATED : February 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int trilinear_interpolant(Volume_Data *volume, Coord_Vector coord, double *result) { long slcind, rowind, colind, slcmax, rowmax, colmax; long slcnext, rownext, colnext; static double f0, f1, f2, r0, r1, r2, r1r2, r1f2, f1r2, f1f2; static double v000, v001, v010, v011, v100, v101, v110, v111; /* Check that the coordinate is inside the volume */ slcmax = volume->size[SLC_AXIS] - 1; rowmax = volume->size[ROW_AXIS] - 1; colmax = volume->size[COL_AXIS] - 1; if ((coord[SLICE] < -VOXEL_COORD_EPS) || (coord[SLICE] > slcmax+VOXEL_COORD_EPS) || (coord[ROW] < -VOXEL_COORD_EPS) || (coord[ROW] > rowmax+VOXEL_COORD_EPS) || (coord[COLUMN] < -VOXEL_COORD_EPS) || (coord[COLUMN] > colmax+VOXEL_COORD_EPS)) { *result = volume->fillvalue; return FALSE; } /* Get the whole part of the coordinate */ slcind = (long) coord[SLICE]; rowind = (long) coord[ROW]; colind = (long) coord[COLUMN]; if (slcind >= slcmax-1) slcind = slcmax-1; if (rowind >= rowmax-1) rowind = rowmax-1; if (colind >= colmax-1) colind = colmax-1; /* Get the next voxel up */ slcnext = slcind+1; rownext = rowind+1; colnext = colind+1; /* Check for case of dimension of length one */ if (slcmax == 0) { slcind = 0; slcnext = 0; } if (rowmax == 0) { rowind = 0; rownext = 0; } if (colmax == 0) { colind = 0; colnext = 0; } /* Get the relevant voxels */ VOLUME_VALUE(volume, slcind , rowind , colind , v000); VOLUME_VALUE(volume, slcind , rowind , colnext, v001); VOLUME_VALUE(volume, slcind , rownext, colind , v010); VOLUME_VALUE(volume, slcind , rownext, colnext, v011); VOLUME_VALUE(volume, slcnext, rowind , colind , v100); VOLUME_VALUE(volume, slcnext, rowind , colnext, v101); VOLUME_VALUE(volume, slcnext, rownext, colind , v110); VOLUME_VALUE(volume, slcnext, rownext, colnext, v111); /* Check that the values are not fill values */ if ((v000 < volume->vrange[0]) || (v000 > volume->vrange[1]) || (v001 < volume->vrange[0]) || (v001 > volume->vrange[1]) || (v010 < volume->vrange[0]) || (v010 > volume->vrange[1]) || (v011 < volume->vrange[0]) || (v011 > volume->vrange[1]) || (v100 < volume->vrange[0]) || (v100 > volume->vrange[1]) || (v101 < volume->vrange[0]) || (v101 > volume->vrange[1]) || (v110 < volume->vrange[0]) || (v110 > volume->vrange[1]) || (v111 < volume->vrange[0]) || (v111 > volume->vrange[1])) { *result = volume->fillvalue; return FALSE; } /* Get the fraction parts */ f0 = coord[SLICE] - slcind; f1 = coord[ROW] - rowind; f2 = coord[COLUMN] - colind; r0 = 1.0 - f0; r1 = 1.0 - f1; r2 = 1.0 - f2; /* Do the interpolation */ r1r2 = r1 * r2; r1f2 = r1 * f2; f1r2 = f1 * r2; f1f2 = f1 * f2; *result = r0 * (volume->scale[slcind] * (r1r2 * v000 + r1f2 * v001 + f1r2 * v010 + f1f2 * v011) + volume->offset[slcind]); *result += f0 * (volume->scale[slcind+1] * (r1r2 * v100 + r1f2 * v101 + f1r2 * v110 + f1f2 * v111) + volume->offset[slcind+1]); return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : tricubic_interpolant @INPUT : volume - pointer to volume data coord - point at which volume should be interpolated in voxel units (with 0 being first point of the volume). @OUTPUT : result - interpolated value. @RETURNS : TRUE if coord is within the volume, FALSE otherwise. @DESCRIPTION: Routine to interpolate a volume at a point with tri-cubic interpolation. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int tricubic_interpolant(Volume_Data *volume, Coord_Vector coord, double *result) { long slcind, rowind, colind, slcmax, rowmax, colmax, index[VOL_NDIMS]; double frac[VOL_NDIMS]; /* Check that the coordinate is inside the volume */ slcmax = volume->size[SLC_AXIS] - 1; rowmax = volume->size[ROW_AXIS] - 1; colmax = volume->size[COL_AXIS] - 1; /* Identify a slice or a volume. Slice must be in x-y. */ if( slcmax == 0 ) { /* 2-d slice */ if( (coord[ROW] < 0) || (coord[ROW] > rowmax) || (coord[COLUMN] < 0) || (coord[COLUMN] > colmax) ) { *result = volume->fillvalue; return FALSE; } } else { /* 3-d volume */ if( (coord[SLICE] < 0) || (coord[SLICE] > slcmax) || (coord[ROW] < 0) || (coord[ROW] > rowmax) || (coord[COLUMN] < 0) || (coord[COLUMN] > colmax) ) { *result = volume->fillvalue; return FALSE; } } /* Get the whole and fractional part of the coordinate */ slcind = (long)coord[SLICE]; rowind = (long)coord[ROW]; colind = (long)coord[COLUMN]; frac[0] = coord[SLICE] - slcind; frac[1] = coord[ROW] - rowind; frac[2] = coord[COLUMN] - colind; slcind--; rowind--; colind--; /* Check for dimension of image. */ /* Check for edges in the 2-d plane - do linear interpolation at edges */ /* Note: Spline stencil is right-sided, so ok to start at 0. */ if( slcmax == 0 && rowmax > 0 && colmax > 0 ) { if( (rowind > rowmax-3) || (rowind < 0) || (colind > colmax-3) || (colind < 0)) { return trilinear_interpolant(volume, coord, result); } else { slcind = 0; /* there is only slice 0 */ index[0]=slcind; index[1]=rowind; index[2]=colind; if( do_Ncubic_interpolation(volume, index, 1, frac, result) ) { /* scaling not done for a slice in do_Ncubic_interpolation, */ /* only done for a volume */ *result = (*result) * volume->scale[slcind] + volume->offset[slcind]; return TRUE; } else { return FALSE; } } } /* Check for edges in the 3-d volume - do linear interpolation at edges */ /* Note: Spline stencil is right-sided, so ok to start at 0. */ if ((slcind > slcmax-3) || (slcind < 0) || (rowind > rowmax-3) || (rowind < 0) || (colind > colmax-3) || (colind < 0)) { return trilinear_interpolant(volume, coord, result); } else { index[0]=slcind; index[1]=rowind; index[2]=colind; /* Do the interpolation and return its value */ return do_Ncubic_interpolation(volume, index, 0, frac, result); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_Ncubic_interpolation @INPUT : volume - pointer to volume data index - indices to start point in volume (bottom of 4x4x4 cube for interpolation) cur_dim - dimension to be interpolated (0 = volume, 1 = slice, 2 = line) @OUTPUT : result - interpolated value. @RETURNS : TRUE if coord is within the volume, FALSE otherwise. @DESCRIPTION: Routine to interpolate a volume, slice or line (specified by cur_dim). @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int do_Ncubic_interpolation(Volume_Data *volume, long index[], int cur_dim, double frac[], double *result) { long base_index; double v0, v1, v2, v3, u; int found_fillvalue; /* Save index that we will change */ base_index = index[cur_dim]; /* If last dimension, then just get the values */ found_fillvalue = FALSE; if (cur_dim == VOL_NDIMS-1) { VOLUME_VALUE(volume, index[0] ,index[1], index[2], v0); index[cur_dim]++; VOLUME_VALUE(volume, index[0] ,index[1], index[2], v1); index[cur_dim]++; VOLUME_VALUE(volume, index[0] ,index[1], index[2], v2); index[cur_dim]++; VOLUME_VALUE(volume, index[0] ,index[1], index[2], v3); /* Check for fillvalues */ if ((v0 < volume->vrange[0]) || (v0 > volume->vrange[1]) || (v1 < volume->vrange[0]) || (v1 > volume->vrange[1]) || (v2 < volume->vrange[0]) || (v2 > volume->vrange[1]) || (v3 < volume->vrange[0]) || (v3 > volume->vrange[1])) { found_fillvalue = TRUE; } } /* Otherwise, recurse */ else { if (!do_Ncubic_interpolation(volume, index, cur_dim+1, frac, &v0)) { found_fillvalue = TRUE; } index[cur_dim]++; if (!do_Ncubic_interpolation(volume, index, cur_dim+1, frac, &v1)) { found_fillvalue = TRUE; } index[cur_dim]++; if (!do_Ncubic_interpolation(volume, index, cur_dim+1, frac, &v2)) { found_fillvalue = TRUE; } index[cur_dim]++; if (!do_Ncubic_interpolation(volume, index, cur_dim+1, frac, &v3)) { found_fillvalue = TRUE; } } /* Restore index */ index[cur_dim] = base_index; /* Check for fill value found */ if (found_fillvalue) { *result = volume->fillvalue; return FALSE; } /* Scale values for slices */ if (cur_dim==0) { v0 = v0 * volume->scale[base_index ] + volume->offset[base_index ]; v1 = v1 * volume->scale[base_index+1] + volume->offset[base_index+1]; v2 = v2 * volume->scale[base_index+2] + volume->offset[base_index+2]; v3 = v3 * volume->scale[base_index+3] + volume->offset[base_index+3]; } /* Get fraction */ u = frac[cur_dim]; /* Do tricubic interpolation (code from Dave MacDonald). Gives v1 and v2 at u = 0 and 1 and gives continuity of intensity and first derivative. */ *result = ( (v1) + (u) * ( 0.5 * ((v2)-(v0)) + (u) * ( (v0) - 2.5 * (v1) + 2.0 * (v2) - 0.5 * (v3) + (u) * ( -0.5 * (v0) + 1.5 * (v1) - 1.5 * (v2) + 0.5 * (v3) ) ) ) ); return TRUE; } /************************************************************************ * Windowed Sinc Interpolant * * The technique used is borrowed from Neil Thacker et al., "Improved * Quality of Re-sliced MR Images Using Re-normalized Sinc * Interpolation", Journal of Magnetic Resonance Imaging 10:582-588 * (1999). * * Any bugs are of course my own fault! * * -bert */ int sinc_half_width = SINC_HALF_WIDTH_MAX / 2; enum sinc_interpolant_window_t sinc_window_type = SINC_WINDOW_HANNING; /* basic windowed sinc function */ static double windowed_sinc(double delta) { double phase; double sinc; double window; /* Calculate the sinc function. */ phase = delta * M_PI; if (phase == 0.0) { sinc = 1.0; } else { sinc = sin(phase) / phase; } switch (sinc_window_type) { case SINC_WINDOW_HANNING: /* Calculate the Hanning window. */ window = 0.50 + 0.50 * cos(phase / (1.0 + sinc_half_width)); break; case SINC_WINDOW_HAMMING: /* Calculate the Hamming window. */ window = 0.54 + 0.46 * cos(phase / (1.0 + sinc_half_width)); break; default: window = 1.0; /* No window */ break; } return (sinc * window); } /* Floating-point (unscaled) multiply/accumulate operations */ #define SINC_FRND result += *pix_ptr++ * *win_ptr++ /* Unroll those loops!! */ #define SINC_FMAC \ result = 0.0; \ switch (sinc_half_width) { \ case 10: SINC_FRND; SINC_FRND; \ case 9: SINC_FRND; SINC_FRND; \ case 8: SINC_FRND; SINC_FRND; \ case 7: SINC_FRND; SINC_FRND; \ case 6: SINC_FRND; SINC_FRND; \ case 5: SINC_FRND; SINC_FRND; \ case 4: SINC_FRND; SINC_FRND; \ case 3: SINC_FRND; SINC_FRND; \ case 2: SINC_FRND; SINC_FRND; \ case 1: SINC_FRND; SINC_FRND; \ SINC_FRND; /* Do the leftover */ \ } /* Integer (scaled) multiply/accumulate operations */ #define SINC_IRND result += ((slope * *pix_ptr++) + intercept) * *win_ptr++ /* Unroll the loops!! */ #define SINC_IMAC \ result = 0.0; \ switch (sinc_half_width) { \ case 10: SINC_IRND; SINC_IRND; \ case 9: SINC_IRND; SINC_IRND; \ case 8: SINC_IRND; SINC_IRND; \ case 7: SINC_IRND; SINC_IRND; \ case 6: SINC_IRND; SINC_IRND; \ case 5: SINC_IRND; SINC_IRND; \ case 4: SINC_IRND; SINC_IRND; \ case 3: SINC_IRND; SINC_IRND; \ case 2: SINC_IRND; SINC_IRND; \ case 1: SINC_IRND; SINC_IRND; \ SINC_IRND; /* Do the leftover */ \ } static double sinc_mac_d(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; long offset; double *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (double *) volume->data + offset; SINC_FMAC; return (result); } static double sinc_mac_f(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; long offset; float *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (float *) volume->data + offset; SINC_FMAC; return (result); } static double sinc_mac_uc(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; double slope = volume->scale[z]; double intercept = volume->offset[z]; long offset; unsigned char *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (unsigned char *) volume->data + offset; SINC_IMAC; return (result); } static double sinc_mac_sc(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; double slope = volume->scale[z]; double intercept = volume->offset[z]; long offset; char *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (char *) volume->data + offset; SINC_IMAC; return (result); } static double sinc_mac_us(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; double slope = volume->scale[z]; double intercept = volume->offset[z]; long offset; unsigned short *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (unsigned short *) volume->data + offset; SINC_IMAC; return (result); } static double sinc_mac_ss(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; double slope = volume->scale[z]; double intercept = volume->offset[z]; long offset; short *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (short *) volume->data + offset; SINC_IMAC; return (result); } static double sinc_mac_ui(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; double slope = volume->scale[z]; double intercept = volume->offset[z]; long offset; unsigned int *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (unsigned int *) volume->data + offset; SINC_IMAC; return (result); } static double sinc_mac_si(Volume_Data *volume, int z, int y, int x, double *win_ptr) { double result; double slope = volume->scale[z]; double intercept = volume->offset[z]; long offset; int *pix_ptr; offset = (z * volume->size[ROW_AXIS] + y) * volume->size[COL_AXIS] + x; pix_ptr = (int *) volume->data + offset; SINC_IMAC; return (result); } /* ----------------------------- MNI Header ----------------------------------- @NAME : windowed_sinc_interpolant @INPUT : volume - pointer to volume data coord - point at which volume should be interpolated in voxel units (with 0 being first point of the volume). @OUTPUT : result - interpolated value. @RETURNS : TRUE if coord is within the volume, FALSE otherwise. @DESCRIPTION: Routine to interpolate a volume at a point with windowed sinc interpolation. @METHOD : @GLOBALS : @CALLS : @CREATED : July 11 2005 (Robert Vincent) @MODIFIED : ---------------------------------------------------------------------------- */ int windowed_sinc_interpolant(Volume_Data *volume, Coord_Vector coord, double *result) { double zt, yt, xt; double zf, yf, xf; int zi, yi, xi; int i, j; double new; double tmp; long slcmax, rowmax, colmax; double zw[SINC_HALF_WIDTH_MAX * 2 + 1]; double yw[SINC_HALF_WIDTH_MAX * 2 + 1]; double xw[SINC_HALF_WIDTH_MAX * 2 + 1]; slcmax = volume->size[SLC_AXIS] - 1; rowmax = volume->size[ROW_AXIS] - 1; colmax = volume->size[COL_AXIS] - 1; if ((coord[SLICE] < 0) || (coord[SLICE] > slcmax) || (coord[ROW] < 0) || (coord[ROW] > rowmax) || (coord[COLUMN] < 0) || (coord[COLUMN] > colmax)) { *result = volume->fillvalue; return FALSE; } zi = (int) coord[SLICE]; yi = (int) coord[ROW]; xi = (int) coord[COLUMN]; /* Check for edges - do linear interpolation at edges */ if ((zi > slcmax-sinc_half_width) || (zi < sinc_half_width) || (yi > rowmax-sinc_half_width) || (yi < sinc_half_width) || (xi > colmax-sinc_half_width) || (xi < sinc_half_width)) { return trilinear_interpolant(volume, coord, result); } /* Calculate fractional part of the coordinate. */ zf = coord[SLICE] - zi; yf = coord[ROW] - yi; xf = coord[COLUMN] - xi; /* Initialize the totals. */ zt = 0.0; yt = 0.0; xt = 0.0; /* Generate the three windowed sinc functions. */ for (i = -sinc_half_width; i <= sinc_half_width; i++) { tmp = windowed_sinc(zf - i); zw[i + sinc_half_width] = tmp; zt += tmp; tmp = windowed_sinc(yf - i); yw[i + sinc_half_width] = tmp; yt += tmp; tmp = windowed_sinc(xf - i); xw[i + sinc_half_width] = tmp; xt += tmp; } /* Now calculate the new value. */ new = 0.0; for (i = -sinc_half_width; i <= sinc_half_width; i++) { for (j = -sinc_half_width; j <= sinc_half_width; j++) { switch (volume->datatype) { case NC_BYTE: if (volume->is_signed) { tmp = sinc_mac_sc(volume, zi + i, yi + j, xi - sinc_half_width, xw); } else { tmp = sinc_mac_uc(volume, zi + i, yi + j, xi - sinc_half_width, xw); } break; case NC_SHORT: if (volume->is_signed) { tmp = sinc_mac_ss(volume, zi + i, yi + j, xi - sinc_half_width, xw); } else { tmp = sinc_mac_us(volume, zi + i, yi + j, xi - sinc_half_width, xw); } break; case NC_INT: if (volume->is_signed) { tmp = sinc_mac_si(volume, zi + i, yi + j, xi - sinc_half_width, xw); } else { tmp = sinc_mac_ui(volume, zi + i, yi + j, xi - sinc_half_width, xw); } break; case NC_FLOAT: tmp = sinc_mac_f(volume, zi + i, yi + j, xi - sinc_half_width, xw); break; case NC_DOUBLE: tmp = sinc_mac_d(volume, zi + i, yi + j, xi - sinc_half_width, xw); break; default: fprintf(stderr, "UNHANDLED TYPE!!!\n"); break; } new += zw[i + sinc_half_width] * yw[j + sinc_half_width] * tmp; } } *result = (new / (zt * yt * xt)); return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : nearest_neighbour_interpolant @INPUT : volume - pointer to volume data coord - point at which volume should be interpolated in voxel units (with 0 being first point of the volume). @OUTPUT : result - interpolated value. @RETURNS : TRUE if coord is within the volume, FALSE otherwise. @DESCRIPTION: Routine to interpolate a volume at a point with nearest neighbour interpolation. Allows the coord to be outside the volume by up to 1/2 a pixel. @METHOD : @GLOBALS : @CALLS : @CREATED : February 12, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int nearest_neighbour_interpolant(Volume_Data *volume, Coord_Vector coord, double *result) { long slcind, rowind, colind, slcmax, rowmax, colmax; /* Check that the coordinate is inside the volume */ slcmax = volume->size[SLC_AXIS] - 1; rowmax = volume->size[ROW_AXIS] - 1; colmax = volume->size[COL_AXIS] - 1; slcind = ROUND(coord[SLICE]); rowind = ROUND(coord[ROW]); colind = ROUND(coord[COLUMN]); if ((slcind < 0) || (slcind > slcmax) || (rowind < 0) || (rowind > rowmax) || (colind < 0) || (colind > colmax)) { *result = volume->fillvalue; return FALSE; } /* Get the value */ VOLUME_VALUE(volume, slcind , rowind , colind , *result); /* Check for fillvalue on input */ if ((*result < volume->vrange[0]) || (*result > volume->vrange[1])) { *result = volume->fillvalue; return FALSE; } *result = volume->scale[slcind] * (*result) + volume->offset[slcind]; return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : renormalize_slices @INPUT : ofp - output file pointer slice_min - array of slice minima slice_max - array of slice maxima @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to loop through the output file and renormalize the slices. @METHOD : @GLOBALS : @CALLS : @CREATED : October 29, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void renormalize_slices(Program_Flags *program_flags, VVolume *out_vol, double slice_min[], double slice_max[]) { File_Info *ofp; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS], end[MAX_VAR_DIMS]; long mm_start[MAX_VAR_DIMS]; long nslice, image, islice, ivolume, image_slice, slice_count; int idim, slice_index, index; double *image_maximum, *image_minimum; /* Set pointer to file information */ ofp = out_vol->file; /* Set output file start, count and end vectors for stepping a slice at a time */ (void) miset_coords(ofp->ndims, (long) 0, start); (void) miset_coords(ofp->ndims, (long) 1, count); for (idim=0; idim < ofp->ndims; idim++) { end[idim] = ofp->nelements[idim]; } for (idim=0; idim < VOL_NDIMS; idim++) { index = ofp->indices[idim]; if (idim==0) { slice_index = index; nslice = ofp->nelements[index]; count[slice_index] = 1; } else { count[index] = ofp->nelements[index]; } } /* Find the max/min for each image */ image_maximum = malloc( sizeof(double) * ofp->images_per_file); image_minimum = malloc( sizeof(double) * ofp->images_per_file); for (image=0; image < ofp->images_per_file; image++) { image_maximum[image] = -DBL_MAX; image_minimum[image] = DBL_MAX; } slice_count = 0; for (ivolume=0; ivolume < ofp->images_per_file / nslice; ivolume++) { for (image_slice=0; image_sliceslices_per_image; image_slice++) { for (islice=0; islice < nslice; islice++) { image = ivolume * nslice + islice; image_maximum[image] = MAX(image_maximum[image], slice_max[slice_count]); image_minimum[image] = MIN(image_minimum[image], slice_min[slice_count]); slice_count++; } } } /* Initialize file max/min slice count */ slice_count = 0; /* Print log message */ if (program_flags->verbose) { (void) fprintf(stderr, "Renormalizing slices:"); (void) fflush(stderr); } /* Loop over output volumes */ while (start[0] < end[0]) { /* Loop over slices */ for (islice=0; islice < nslice; islice++) { /* Print log message */ if (program_flags->verbose) { (void) fprintf(stderr, "."); (void) fflush(stderr); } /* Set slice number in out_start */ start[slice_index] = islice; /* Figure out which image, slice, volume, etc we are dealing with */ islice = slice_count % nslice; ivolume = slice_count / nslice / ofp->slices_per_image; image = ivolume * nslice + islice; /* Get the slice min/max start coordinate */ (void) mitranslate_coords(ofp->mincid, ofp->imgid, start, ofp->maxid, mm_start), /* Write out the slice max and min */ (void) mivarput1(ofp->mincid, ofp->maxid, mm_start, NC_DOUBLE, NULL, &slice_max[slice_count]); (void) mivarput1(ofp->mincid, ofp->minid, mm_start, NC_DOUBLE, NULL, &slice_min[slice_count]); /* Read in the slice */ (void) miicv_get(ofp->icvid, start, count, out_vol->slice->data); /* Write the image max, min and slice */ (void) mivarput1(ofp->mincid, ofp->maxid, mm_start, NC_DOUBLE, NULL, &image_maximum[image]); (void) mivarput1(ofp->mincid, ofp->minid, mm_start, NC_DOUBLE, NULL, &image_minimum[image]); (void) miicv_put(ofp->icvid, start, count, out_vol->slice->data); /* Increment slice count */ slice_count++; } /* End loop over slices */ /* Set slice counter to ensure that we move to the next volume */ start[slice_index] = end[slice_index] - 1; /* Increment in_start counter */ idim = ofp->ndims-1; start[idim] += count[idim]; while ( (idim>0) && (start[idim] >= end[idim])) { start[idim] = 0; idim--; start[idim] += count[idim]; } } /* End loop over volumes */ /* Print end of log message */ if (program_flags->verbose) { (void) fprintf(stderr, "Done\n"); (void) fflush(stderr); } /* Free the image max/min arrays */ free(image_maximum); free(image_minimum); return; } minc-2.2.00/progs/mincreshape/0000755000265600003100000000000012030114723013140 500000000000000minc-2.2.00/progs/mincreshape/mincreshape.h0000644000265600003100000001113212027132663015536 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincreshape.h @DESCRIPTION: Header file for mincreshape.c @METHOD : @GLOBALS : @CALLS : @CREATED : March 11, 1994 (Peter Neelin) @MODIFIED : * $Log: mincreshape.h,v $ * Revision 6.5 2008-01-13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.4 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.3 2001/12/06 14:12:45 neelin * Trivial change to definition of NCOPTS_DEFAULT. * * Revision 6.2 1999/10/19 14:45:29 neelin * Fixed Log subsitutions for CVS * * Revision 6.1 1998/08/19 13:57:50 neelin * Added ARG_SEPARATOR to replace string literal for comma. * * Revision 6.0 1997/09/12 13:24:12 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:10 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:44 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:32:36 neelin * Release of minc version 0.3 * * Revision 1.3 1994/12/02 09:08:57 neelin * Moved nd_loop to proglib. * * Revision 1.2 94/11/23 11:47:08 neelin * Handle image-min/max properly when using icv for normalization. * * Revision 1.1 94/11/02 16:22:00 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ /* Constants used in program */ #define NOFILL DBL_MAX /* Fillvalue indicating -nofill */ #define FILL -DBL_MAX /* Fillvalue for -fill */ #define NCOPTS_DEFAULT (NC_VERBOSE | NC_FATAL) #define DEFAULT_MAX_CHUNK_SIZE_IN_KB (1024*4) #define DIM_WIDTH_SUFFIX "-width" #define ARG_SEPARATOR ',' #define VECTOR_SEPARATOR ',' #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Types used in program */ typedef struct { int verbose; int icvid, inmincid, outmincid, outimgid; nc_type output_datatype; int output_is_signed; int input_ndims; /* Number of input dimensions */ int output_ndims; /* Number of output dimensions */ long input_size[MAX_VAR_DIMS]; /* Size of input volume */ long input_start[MAX_VAR_DIMS]; /* Start of desired hyperslab */ long input_count[MAX_VAR_DIMS]; /* Size of desired hyperslab (<0 means 1 and remove dimension) */ int map_out_to_in[MAX_VAR_DIMS]; /* Map output dimension index to input */ int map_in_to_out[MAX_VAR_DIMS]; /* Map input dimension index to output (-1 means no mapping) */ int dim_used_in_block[MAX_VAR_DIMS]; /* TRUE if output dim used in block */ int chunk_count[MAX_VAR_DIMS]; /* Specifies count for chunk hyperslab */ int need_fillvalue; /* TRUE if we will need a fill value */ double fillvalue; /* Value to fill with (FILL_DEFAULT means fill with real value zero) */ int do_block_normalization; /* Normalize slices to block max/min */ int do_icv_normalization; /* Use icv for normalization */ /* Note that a block is a hyperslab of the output volume in which all values are normalized the same way. A chunk is a hyperslab that is copied in one piece (smaller than or equal to a block). */ } Reshape_info; typedef struct { int nentries; char *name[MAX_VAR_DIMS]; long size[MAX_VAR_DIMS]; } Dimsize_list; typedef struct { int nentries; char *name[MAX_VAR_DIMS]; long start[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS]; } Axis_ranges; /* Macros used in program */ #define ISSPACE(ch) (isspace((int)ch)) #define ABS(x) (((x) >= 0) ? (x) : (-(x))) #define MAX( x, y ) ( ((x) >= (y)) ? (x) : (y) ) #define MIN( x, y ) ( ((x) <= (y)) ? (x) : (y) ) /* Function prototypes */ extern void copy_data(Reshape_info *reshape_info); minc-2.2.00/progs/mincreshape/mincreshape.man10000644000265600003100000003166112027132663016154 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1994 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincreshape/mincreshape.man1,v 6.2 2004-05-20 21:52:09 bert Exp $ .\" .TH MINCRESHAPE 1 "$Date: 2004-05-20 21:52:09 $" "" "MINC User's Guide" .SH NAME mincreshape - cuts a hyperslab out of a minc file (with dimension re-ordering) .SH SYNOPSIS .B mincreshape [] .mnc .mnc .SH DESCRIPTION \fIMincreshape's\fR main job is to chop a hyperslab out of a minc file and put it into a new minc file. "What is a hyperslab?", you ask. It is simply a multi-dimensional box specified with a starting index (a vector giving a voxel coordinate) and a count vector (a number of voxels along each axis). A single slice out of a volume is a hyperslab (with a count of 1 in the slice direction), a small block pulled out of a large volume is a hyperslab, a single echo volume out of a multi-echo MRI dataset is a hyperslab, one time point out of a dynamic acquisition is a hyperslab - you get the idea. Check out the \fB-start\fR, \fB-count\fR and \fB-dimrange\fR options for more details on how to do this (and look at the examples!). If you are pulling out only one point along a dimension, you have the option of making the dimension disappear, so \fImincreshape\fR gives you the ability to reduce the dimensionality of a minc file. As well, you aren't constrained to specify a hyperslab that is only within the input file, you can extend beyond the bounds of the dimensions in the input file, and furthermore you can give a count that will flip the data along a dimension. As if all that is not enough, \fImincreshape\fR has the ability to re-order dimensions. The most obvious case is converting a transverse image into a coronal image. But you can type a list of dimension names to get an arbitrary order of dimensions. You want more!?! Okay, okay. \fIMincreshape\fR makes all of the minc library ICV operations available on the command line. For those who like things defined, an ICV is an image conversion variable (don't ask me why I called it that) which basically lets you tell the data what it's going to look like. In other words, it does a bunch of conversions for you. These conversions include changing type, range and normalization of the voxel values, expanding or contracting images (by voxel duplication or averaging) to give a specified image size, and converting vector images to scalar. Just so you don't get confused let me tell you clearly here: \fImincreshape\fR does all of the ICV conversions first and then the hyperslab and dimension re-ordering stuff is applied to the result of that. So if you want to mix them together (like \fB-imgsize\fR, \fB-start\fR, \fB-count\fR), get it clear in your head first. Okay, hold on to your seat: here's a list of options. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-2\fR Create MINC 2.0 format output files. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB-verbose\fR Print out progress information for each chunk of data copied (default). A chunk varies in size depending mostly on whether you're re-ordering dimensions or not and how big the internal buffer is allowed to be. .TP \fB\-quiet\fR Do not print out progress information. .TP \fB\-max_chunk_size_in_kb\fR\ \fIsize\fR Specify the maximum size of the copy buffer (in kbytes). Default is 4096 kbytes (4meg). .SH Image conversion options (pixel type and range): The default for type, sign and valid range is to use those of the input file. If type is specified, then both sign and valid range are set to the default for that type. If sign is specified, then valid range is set to the default for the type and sign. .TP \fB\-filetype\fR Don't do any type conversion (default). .TP \fB\-byte\fR Store output voxels in 8-bit integer format. .TP \fB\-short\fR Store output voxels in 16-bit integer format. .TP \fB\-int\fR Store output voxels in 32-bit integer format. .TP \fB\-long\fR Superseded by \fB\-int\fR. .TP \fB-float\fR Store output voxels in 32-bit floating point format. .TP \fB-double\fR Store output voxels in 64-bit floating point format. .TP \fB\-signed\fR Write out values as signed integers (default for short and long). Ignored for floating point types. .TP \fB\-unsigned\fR Write out values as unsigned integers (default for byte). Ignored for floating point types. .TP \fB\-valid_range\fR\ \fImin\ max\fR specifies the valid range of output voxel values in their integer representation. Default is the full range for the type and sign. This option is ignored for floating point values. .TP \fB\-image_range\fR\ \fImin\ max\fR Normalize images to a given minimum and maximum real value (not voxel value). .TP \fB\-normalize\fR Normalize images to real minimum and maximum for the entire input file. .TP \fB\-nonormalize\fR Do not normalize images (default). .TP \fB\-nopixfill\fR Do not convert out-of-range values in input file, just copy them through. .TP \fB\-pixfill\fR Replace out-of-range values in input file by the smallest possible value (default). .TP \fB\-pixfillvalue\fR\ \fIvalue\fR Specify a new pixel value to replace out-of-range values in the input file. .SH Image conversion options (dimension direction and size): .TP \fB\-scalar\fR Convert vector images to scalar images (a vector image is one with \fIvector_dimension\fR as the fastest varying dimension). The vector dimension is removed and values are averaged. .TP \fB\-noscalar\fR Do not convert vector images to scalar images (default). .TP \fB\+direction\fR Flip images to give positive step value for spatial axes. Note that the flipping of spatial axes only applies to "image dimensions". These are the two fastest varying (non-vector) dimensions in the file. If you want to flip a non-image dimension, you can convert it to an image dimension with \fB\-dimsize\fR \fIdimname\fR\fB=\-1\fR (the \-1 means don't really change the size). Check out the examples. .TP \fB\-direction\fR Flip images to give negative step value for spatial axes. .TP \fB-anydirection\fR Don't flip images along spatial axes (default). .TP \fB+xdirection\fR Flip images to give positive xspace:step value (left-to-right). .TP \fB\-xdirection\fR Flip images to give negative xspace:step value (right-to-left). .TP \fB\-xanydirection\fR Don't flip images along x-axis. .TP \fB\+ydirection\fR Flip images to give positive yspace:step value (posterior-to-anterior). .TP \fB\-ydirection\fR Flip images to give negative yspace:step value (anterior-to-posterior). .TP \fB\-yanydirection\fR Don't flip images along y-axis. .TP \fB\+zdirection\fR Flip images to give positive zspace:step value (inferior-to-superior). .TP \fB\-zdirection\fR Flip images to give negative zspace:step value (superior-to-inferior). .TP \fB\-zanydirection\fR Don't flip images along z-axis. .TP \fB\-keepaspect\fR Preserve aspect ratio when resizing images. This means that voxels are replicated (or averaged) the same number of times along each image dimension. .TP \fB\-nokeepaspect\fR Do not force preservation of aspect ratio when resizing images (default). .TP \fB\-imgsize\fR\ \fIsize\fR Specify the desired image size (used if \fB\-rowsize\fR or \fB\-colsize\fR not given). .TP \fB\-rowsize\fR\ \fIsize\fR Specify the desired number of rows in the image. .TP \fB\-colsize\fR\ \fIsize\fR Specify the desired number of columns in the image. .TP \fB\-dimsize\fR\ \fIdimension\fR=\fIsize\fR Specify the size of a named dimension (\fIdimension\fR=\fIsize\fR). Note that the resizing only applies to "image dimensions" - usually the two fastest-varying (non-vector) dimensions. To do dimension resizing, all fastest-varying dimensions up to the named dimension are turned into image dimensions, and these are then affected by the direction options. The dimension name and size must be in one command-line argument, so if you use spaces (which is okay), remember to use quotes to hide them from the shell. .SH Reshaping options: .TP \fB\-transverse\fR Write out transverse slices. .TP \fB\-sagittal\fR Write out sagittal slices. .TP \fB-coronal\fR Write out coronal slices. .TP \fB\-dimorder\fR\ \fIdim1\fR,\fIdim2\fR,\fIdim3\fR,... Specify dimension order, where \fIdim?\fR are the names of the dimensions. You can give fewer dimensions than exist in the file: they are assumed to be the fastest varying dimensions in the output file (so \fB\-transverse\fR is exactly equivalent to \fB-dimorder zspace,yspace,xspace\fR). Again, spaces are allowed between names, but remember to hide them from the shell with quotes. .TP \fB\-dimrange\fR\ \fIdim\fR=\fIstart\fR[,\fIcount\fR] Specify the range of dimension subscripts for dimension \fIdim\fR. If \fIcount\fR is missing or 0, then it is taken to mean 1, but remove the dimension from the output file (a count of 1 will keep a dimension of size 1). A negative \fIcount\fR means flip the data along that dimension - in this case \fIstart\fR specifies the highest voxel coordinate for the dimension (\fB\-dimrange\ xspace=3,\-3\fR gives a flipped version of \fB\-dimrange\ xspace=1,3\fR). The options \fB\-start\fR and \fB\-count\fR provide an alternative way to specify the same information. .TP \fB\-start\fR\ \fIcoord0\fR,\fIcoord1\fR,\fIcoord2\fR,... Specifies the starting corner of the hyperslab (coordinates go from slowest varying dimension to fastest). If fewer coordinates are given than dimensions exist in the file, then they are assumed to apply to the slowest varying dimensions and the remaining coordinates are set to 0. See \fB\-dimrange\fR for more details. Both \fB\-start\fR and \fB\-count\fR give vectors that correspond to input file dimensions after the image conversion (ICV) options have been applied. .TP \fB\-count\fR\ \fIsize0\fR,\fIsize1\fR,\fIsize2\fR,... Specifies edge lengths of hyperslab to read (coordinates go from slowest varying dimension to fastest). If fewer sizes are given than dimensions exist in the file, then they are assumed to apply to the slowest varying dimensions and the remaining sizes are set to the full size of the dimension. See \fB\-dimrange\fR for more details. Both \fB\-start\fR and \fB-count\fR give vectors that correspond to input file dimensions after the image conversion (ICV) options have been applied. .SH Missing data options: .TP \fB\-nofill\fR Use value zero for points outside of the input volume (default). .TP \fB\-fill\fR Use a fill value for points outside of input volume (minimum possible value). .TP \fB\-fillvalue\fR\ \fIvalue\fR Specify a fill value for points outside of the input volume (this is a real value, not a pixel value). .SH Generic options for all commands: .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH EXAMPLES: Assume that we have a volume with dimensions zspace, yspace, xspace (that's transverse) and sizes 128, 256, 256. If we want to get slice 40 out of it (keeping the coordinate information for the zspace dimension), then we can use mincreshape original.mnc new.mnc -dimrange zspace=40,1 Alternatively, we could use mincreshape original.mnc new.mnc -start 40,0,0 -count 1,256,256 Or simply mincreshape original.mnc new.mnc -start 40 -count 1 If we wanted to get rid of the zspace dimension, we could use mincreshape original.mnc new.mnc -dimrange zspace=40,0 Let's get a block out of the middle and flip it along xspace: mincreshape original.mnc new.mnc \\ -start 40,10,240 -count 1,200,-200 But why restrain outselves? Let's go out of bounds: mincreshape original.mnc new.mnc \\ -start 40,-100,340 -count 1,200,-200 If you want a sagittal volume, use this: mincreshape original.mnc new.mnc -sagittal How about some sideways heads - flip x and y. And convert to byte to save space while we're at it: mincreshape original.mnc new.mnc -dimorder xspace,yspace -byte You like to store volumes in x,y,z order (that's z varying fastest! I know some people who do it!)? Okay. mincreshape original.mnc new.mnc -dimorder xspace,yspace,zspace But you're a minimalist (and don't mind taking a chance). Here's the same thing (but it might break for another file): mincreshape original.mnc new.mnc -dimorder zspace Let's make sure that all dimensions have a negative step attribute (see option +direction for some details): mincreshape original.mnc new.mnc -direction -dimsize zspace=-1 .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1994 by Peter Neelin .SH "SEE ALSO" .LP .BR mincresample (1) minc-2.2.00/progs/mincreshape/mincreshape.c0000644000265600003100000020131612027132663015536 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincreshape @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : error status @DESCRIPTION: Program to allow reshaping of minc lattices: selecting a a subrange (or superrange) of dimension indices, eliminating dimensions, or re-ordering axes. As well, all icv conversions are made accessible on the command line. @METHOD : @GLOBALS : @CALLS : @CREATED : March 10, 1994 (Peter Neelin) @MODIFIED : * $Log: mincreshape.c,v $ * Revision 6.14 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.13 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.12 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.11 2005/08/26 21:07:18 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.10 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.9 2004/04/27 15:30:02 bert * Add -2 flag * * Revision 6.8 2001/11/13 14:16:50 neelin * Get correct valid range for conversion from int to float types * * Revision 6.7 2001/09/18 15:32:53 neelin * Create image variable last to allow big images and to fix compatibility * problems with 2.3 and 3.x. * * Revision 6.6 2001/08/16 16:41:36 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.5 2001/04/24 13:38:45 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.4 2001/04/17 18:40:24 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.3 1999/10/19 14:45:29 neelin * Fixed Log subsitutions for CVS * * Revision 6.2 1998/08/19 13:57:23 neelin * Fixed argument parsing to detect errors such as octal numbers * containing illegal digits (08) and extraneous characters on the end of * arguments. * * Revision 6.0 1997/09/12 13:24:12 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:10 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:44 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:32:36 neelin * Release of minc version 0.3 * * Revision 1.6 1995/02/09 14:08:24 neelin * Mods to make irix 5 lint happy. * * Revision 1.5 1995/02/08 19:31:47 neelin * Moved ARGSUSED statements for irix 5 lint. * * Revision 1.4 1994/11/23 11:47:05 neelin * Handle image-min/max properly when using icv for normalization. * * Revision 1.3 94/11/22 08:46:09 neelin * Fixed handling of normalization for number of image dimensions > 2. * Added appropriate default values of image-max and image-min. * * Revision 1.2 94/11/03 08:48:20 neelin * Allow chunk_count to have sizes less than full block size. * * Revision 1.1 94/11/02 16:21:24 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "mincreshape.h" static void get_arginfo(int argc, char *argv[], Reshape_info *reshape_info); static int get_fillvalue(char *dst, char *key, char *nextArg); static int get_dimsize(char *dst, char *key, char *nextArg); static int get_axis_order(char *dst, char *key, char *nextArg); static int get_axis_range(char *dst, char *key, char *nextArg); static int get_arg_vector(char *dst, char *key, char *nextArg); static void get_default_datatype(int mincid, nc_type *datatype, int *is_signed, double valid_range[2]); static void setup_dim_sizes(int icvid, int mincid, Dimsize_list *dimsize_list); static void setup_reshaping_info(int icvid, int mincid, int do_norm, double fillvalue, int do_scalar, char *axis_order[], Axis_ranges *axis_ranges, long hs_start[], long hs_count[], int max_chunk_size_in_kb, Reshape_info *reshape_info); static void setup_output_file(int mincid, char *history, Reshape_info *reshape_info); static void create_dim_var(int outmincid, int outdimid, int inicvid, int cur_image_dim, int inmincid, long input_start, long input_count); static void copy_dimension_values(int outmincid, int outdimid, int inmincid, long input_start, long input_count); static void copy_dim_var_values(int outmincid, char *dimname, char *varname, int inmincid, long input_start, long input_count); /* Main program */ int main(int argc, char *argv[]) { Reshape_info reshape_info; /* Get argument information and create the output file */ get_arginfo(argc, argv, &reshape_info); /* Copy the data */ copy_data(&reshape_info); /* Close the output file */ (void) miattputstr(reshape_info.outmincid, reshape_info.outimgid, MIcomplete, MI_TRUE); (void) miclose(reshape_info.outmincid); (void) miclose(reshape_info.inmincid); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_arginfo @INPUT : argc - number of command-line arguments argv - command-line arguments @OUTPUT : reshape_info - information for reshaping file @RETURNS : (nothing) @DESCRIPTION: Routine to get information from arguments about input and output files and reshaping. @METHOD : @GLOBALS : @CALLS : @CREATED : March 11, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_arginfo(int argc, char *argv[], Reshape_info *reshape_info) { /* Argument variables */ static int clobber = FALSE; static int verbose = TRUE; static nc_type datatype = MI_ORIGINAL_TYPE; static int is_signed = INT_MIN; static double valid_range[2] = {DBL_MAX,DBL_MAX}; static double image_range[2] = {DBL_MAX,DBL_MAX}; static int do_norm = FALSE; static double pixfillvalue = FILL; static int do_scalar= FALSE; static int direction = MI_ICV_ANYDIR; static int xdirection = INT_MIN; static int ydirection = INT_MIN; static int zdirection = INT_MIN; static int keep_aspect = FALSE; static int image_size = MI_ICV_ANYSIZE; static int row_size = MI_ICV_ANYSIZE; static int col_size = MI_ICV_ANYSIZE; static Dimsize_list dimsize_list = {0}; static char *axis_order[MAX_VAR_DIMS+1]; static Axis_ranges axis_ranges = {0}; static long hs_start[MAX_VAR_DIMS] = {LONG_MIN}; static long hs_count[MAX_VAR_DIMS] = {LONG_MIN}; static double fillvalue = NOFILL; static int max_chunk_size_in_kb = DEFAULT_MAX_CHUNK_SIZE_IN_KB; #if MINC2 static int minc2_format = 0; #endif /* MINC2 */ int cflags; /* File creation flags */ /* Argument table */ static ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "General options:"}, {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Do not overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages as processing is being done (default).\n"}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out any log messages."}, {"-max_chunk_size_in_kb", ARGV_INT, (char *) 0, (char *) &max_chunk_size_in_kb, "Specify the maximum size of the copy buffer (in kbytes)."}, #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *)&minc2_format, "Produce a MINC 2.0 format output file."}, #endif /* MINC2 */ {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Image conversion options (pixel type and range):"}, {"-filetype", ARGV_CONSTANT, (char *) MI_ORIGINAL_TYPE, (char *) &datatype, "Don't do any type conversion (default)."}, {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &datatype, "Convert to byte data"}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &datatype, "Convert to short integer data"}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Convert to 32-bit integer data"}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &datatype, "Superseded by -int"}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &datatype, "Convert to single-precision floating-point data"}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &datatype, "Convert to double-precision floating-point data"}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &is_signed, "Convert to signed integer data"}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &is_signed, "Convert to unsigned integer data"}, {"-valid_range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Valid range for output data (pixel values)"}, {"-image_range", ARGV_FLOAT, (char *) 2, (char *) image_range, "Normalize images to a given minimum and maximum"}, {"-normalize", ARGV_CONSTANT, (char *) TRUE, (char *) &do_norm, "Normalize images to file minimum and maximum."}, {"-nonormalize", ARGV_CONSTANT, (char *) FALSE, (char *) &do_norm, "Do not normalize images (default)."}, {"-nopixfill", ARGV_FUNC, (char *) get_fillvalue, (char *) &pixfillvalue, "Do not convert out-of-range values in input file."}, {"-pixfill", ARGV_FUNC, (char *) get_fillvalue, (char *) &pixfillvalue, "Replace out-of-range values in input file by smallest value (default)."}, {"-pixfillvalue", ARGV_FLOAT, (char *) 0, (char *) &pixfillvalue, "Specify new value to replace out-of-range values in input file."}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Image conversion options (dimension direction and size):"}, {"-scalar", ARGV_CONSTANT, (char *) TRUE, (char *) &do_scalar, "Convert vector images to scalar images."}, {"-noscalar", ARGV_CONSTANT, (char *) FALSE, (char *) &do_scalar, "Do not convert vector images to scalar images (default)."}, {"+direction", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &direction, "Flip images to give positive step value for spatial axes."}, {"-direction", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &direction, "Flip images to give negative step value for spatial axes."}, {"-anydirection", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &direction, "Don't flip images along spatial axes (default)."}, {"+xdirection", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &xdirection, "Flip images to give positive xspace:step value (left-to-right)."}, {"-xdirection", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &xdirection, "Flip images to give negative xspace:step value (right-to-left)."}, {"-xanydirection", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &xdirection, "Don't flip images along x-axis."}, {"+ydirection", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &ydirection, "Flip images to give positive yspace:step value (post-to-ant)."}, {"-ydirection", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &ydirection, "Flip images to give negative yspace:step value (ant-to-post)."}, {"-yanydirection", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &ydirection, "Don't flip images along y-axis."}, {"+zdirection", ARGV_CONSTANT, (char *) MI_ICV_POSITIVE, (char *) &zdirection, "Flip images to give positive zspace:step value (inf-to-sup)."}, {"-zdirection", ARGV_CONSTANT, (char *) MI_ICV_NEGATIVE, (char *) &zdirection, "Flip images to give negative zspace:step value (sup-to-inf)."}, {"-zanydirection", ARGV_CONSTANT, (char *) MI_ICV_ANYDIR, (char *) &zdirection, "Don't flip images along z-axis."}, {"-keepaspect", ARGV_CONSTANT, (char *) TRUE, (char *) &keep_aspect, "Preserve aspect ratio when resizing images."}, {"-nokeepaspect", ARGV_CONSTANT, (char *) FALSE, (char *) &keep_aspect, "Do not preserve aspect ratio when resizing images (default)."}, {"-imgsize", ARGV_INT, (char *) 0, (char *) &image_size, "Specify the desired image size."}, {"-rowsize", ARGV_INT, (char *) 0, (char *) &row_size, "Specify the desired number of rows in the image."}, {"-colsize", ARGV_INT, (char *) 0, (char *) &col_size, "Specify the desired number of columns in the image."}, {"-dimsize", ARGV_FUNC, (char *) get_dimsize, (char *) &dimsize_list, "Specify the size of a named dimension (=)."}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Reshaping options:"}, {"-transverse", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Write out transverse slices"}, {"-sagittal", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Write out sagittal slices"}, {"-coronal", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Write out coronal slices"}, {"-dimorder", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Specify dimension order (,,,...)."}, {"-dimrange", ARGV_FUNC, (char *) get_axis_range, (char *) &axis_ranges, "Specify range of dimension subscripts (=[,])."}, {"-start", ARGV_FUNC, (char *) get_arg_vector, (char *) hs_start, "Specifies corner of hyperslab (C conventions for indices)"}, {"-count", ARGV_FUNC, (char *) get_arg_vector, (char *) hs_count, "Specifies edge lengths of hyperslab to read"}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Missing data options:"}, {"-nofill", ARGV_FUNC, (char *) get_fillvalue, (char *) &fillvalue, "Use value zero for points outside of input volume (default)"}, {"-fill", ARGV_FUNC, (char *) get_fillvalue, (char *) &fillvalue, "Use a fill value for points outside of input volume"}, {"-fillvalue", ARGV_FLOAT, (char *) 0, (char *) &fillvalue, "Specify a fill value for points outside of input volume"}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Other variables */ char *infile, *outfile; char *history, *pname; int icvid; /* Get the history information and program name */ history = time_stamp(argc, argv); pname = argv[0]; /* Call ParseArgv */ if (ParseArgv(&argc, argv, argTable, 0) || (argc!=3)) { (void) fprintf(stderr, "\nUsage: %s [] \n", pname); (void) fprintf(stderr, " %s [-help]\n\n", pname); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* Save verbose setting */ reshape_info->verbose = verbose; /* Check max chunk size value */ if (max_chunk_size_in_kb <= 0) { (void) fprintf(stderr, "Illegal value for max_chunk_size (%d)\n", max_chunk_size_in_kb); exit(EXIT_FAILURE); } /* Check the x, y and z directions */ if (xdirection == INT_MIN) xdirection = direction; if (ydirection == INT_MIN) ydirection = direction; if (zdirection == INT_MIN) zdirection = direction; /* Check the row and column size */ if (row_size == MI_ICV_ANYSIZE) row_size = image_size; if (col_size == MI_ICV_ANYSIZE) col_size = image_size; /* Check for normalization to specified range */ if (image_range[0] != DBL_MAX) do_norm = TRUE; /* Open the input file */ reshape_info->inmincid = miopen(infile, NC_NOWRITE); /* Get the default datatype */ get_default_datatype(reshape_info->inmincid, &datatype, &is_signed, valid_range); reshape_info->output_datatype = datatype; reshape_info->output_is_signed = is_signed; /* Create the icv */ reshape_info->icvid = miicv_create(); icvid = reshape_info->icvid; /* Set the icv properties */ /* Set datatype properties (get min and max for type from icv) */ (void) miicv_setint(icvid, MI_ICV_TYPE, datatype); if (is_signed != INT_MIN) { if (is_signed) (void) miicv_setstr(icvid, MI_ICV_SIGN, MI_SIGNED); else (void) miicv_setstr(icvid, MI_ICV_SIGN, MI_UNSIGNED); } if (valid_range[0] != DBL_MAX) { (void) miicv_setdbl(icvid, MI_ICV_VALID_MIN, valid_range[0]); (void) miicv_setdbl(icvid, MI_ICV_VALID_MAX, valid_range[1]); } /* Check for normalization */ (void) miicv_setint(icvid, MI_ICV_DO_NORM, do_norm); (void) miicv_setint(icvid, MI_ICV_USER_NORM, (image_range[0] != DBL_MAX)); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MIN, image_range[0]); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MAX, image_range[1]); /* Check for pixel fill value conversion */ (void) miicv_setint(icvid, MI_ICV_DO_FILLVALUE, (pixfillvalue != NOFILL)); (void) miicv_setdbl(icvid, MI_ICV_FILLVALUE, pixfillvalue); /* Set up for dimension conversion */ (void) miicv_setint(icvid, MI_ICV_DO_DIM_CONV, TRUE); (void) miicv_setint(icvid, MI_ICV_DO_SCALAR, do_scalar); (void) miicv_setint(icvid, MI_ICV_XDIM_DIR, xdirection); (void) miicv_setint(icvid, MI_ICV_YDIM_DIR, ydirection); (void) miicv_setint(icvid, MI_ICV_ZDIM_DIR, zdirection); /* Set up for image resizing */ (void) miicv_setint(icvid, MI_ICV_KEEP_ASPECT, keep_aspect); (void) miicv_setint(icvid, MI_ICV_ADIM_SIZE, col_size); (void) miicv_setint(icvid, MI_ICV_BDIM_SIZE, row_size); setup_dim_sizes(icvid, reshape_info->inmincid, &dimsize_list); /* Save reshaping information */ setup_reshaping_info(icvid, reshape_info->inmincid, do_norm, fillvalue, do_scalar, axis_order, &axis_ranges, hs_start, hs_count, max_chunk_size_in_kb, reshape_info); /* Attach the icv */ (void) miicv_attach(icvid, reshape_info->inmincid, ncvarid(reshape_info->inmincid, MIimage)); /* Create the output file */ if (clobber) { cflags = NC_CLOBBER; } else { cflags = NC_NOCLOBBER; } #if MINC2 if (minc2_format) { cflags |= MI2_CREATE_V2; } #endif /* MINC2 */ reshape_info->outmincid = micreate(outfile, cflags); setup_output_file(reshape_info->outmincid, history, reshape_info); return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_fillvalue @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : FALSE so that ParseArgv will not discard nextArg @DESCRIPTION: Routine called by ParseArgv to set the fill value @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_fillvalue(char *dst, char *key, char *nextArg) /* ARGSUSED */ { double *dptr; /* Get pointer to client data */ dptr = (double *) dst; /* Check key for fill value to set */ if ((strcmp(key, "-fill") == 0) || (strcmp(key, "-pixfill") == 0)) { *dptr = FILL; } else if ((strcmp(key, "-nofill") == 0) || (strcmp(key, "-nopixfill") == 0)) { *dptr = NOFILL; } return FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dimsize @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE so that ParseArgv will discard nextArg @DESCRIPTION: Routine called by ParseArgv to get a dimension size @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_dimsize(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Dimsize_list *dimsize_list; char *size_string; int ientry; char *cur; /* Get pointer to client data */ dimsize_list = (Dimsize_list *) dst; /* Check for next argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Check that we have enough space in the list */ if (dimsize_list->nentries >= MAX_VAR_DIMS) { (void) fprintf(stderr, "Too many \"%s\" options.\n", key); exit(EXIT_FAILURE); } ientry = dimsize_list->nentries; /* Parse the argument (=) */ /* Remove leading space */ while (ISSPACE(*nextArg)) nextArg++; dimsize_list->name[ientry] = nextArg; /* Find the '=' */ size_string = strchr(nextArg, '='); if ((size_string == NULL) || (size_string == nextArg)) { (void) fprintf(stderr, "\"%s\" option requires the argument =\n", key); exit(EXIT_FAILURE); } /* Remove trailing blanks on name */ cur = size_string - 1; while ((cur>=nextArg) && ISSPACE(*cur)) cur--; cur++; *cur = '\0'; /* Get the size */ size_string++; dimsize_list->size[ientry] = strtol(size_string, &cur, 0); if (cur == size_string) { (void) fprintf(stderr, "\"%s\" option requires the argument =\n", key); exit(EXIT_FAILURE); } /* Check for extra stuff (spaces are allowed) */ while (ISSPACE(*cur)) cur++; if (*cur != '\0') { (void) fprintf(stderr, "\"%s\" option requires the argument =\n", key); exit(EXIT_FAILURE); } dimsize_list->nentries++; return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_axis_order @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE or FALSE (so that ParseArgv will discard nextArg only when needed) @DESCRIPTION: Routine called by ParseArgv to set the axis order @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_axis_order(char *dst, char *key, char *nextArg) /* ARGSUSED */ { char **axis_order; char *cur; int ndims; /* Get pointer to client data */ axis_order = (char **) dst; /* Check key */ if (strcmp(key, "-transverse") == 0) { axis_order[0] = MIzspace; axis_order[1] = MIyspace; axis_order[2] = MIxspace; return FALSE; } if (strcmp(key, "-sagittal") == 0) { axis_order[0] = MIxspace; axis_order[1] = MIzspace; axis_order[2] = MIyspace; return FALSE; } if (strcmp(key, "-coronal") == 0) { axis_order[0] = MIyspace; axis_order[1] = MIzspace; axis_order[2] = MIxspace; return FALSE; } /* Make sure that we have a "-dimorder" argument */ if (strcmp(key, "-dimorder") != 0) { (void) fprintf(stderr, "Unrecognized option \"%s\": internal program error.\n", key); exit(EXIT_FAILURE); } /* Check for next argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Set up pointers to end of string and first non-space character */ cur = nextArg; while (ISSPACE(*cur)) cur++; ndims = 0; /* Loop through string looking for space or comma-separated names */ while ((ndims < MAX_VAR_DIMS) && (*cur!='\0')) { /* Get string */ axis_order[ndims] = cur; /* Search for end of dimension name */ while (!ISSPACE(*cur) && (*cur != ARG_SEPARATOR) && (*cur != '\0')) cur++; if (*cur != '\0') { *cur = '\0'; cur++; } ndims++; /* Skip any spaces */ while (ISSPACE(*cur)) cur++; } /* Terminate list with NULL */ axis_order[ndims] = NULL; return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_axis_range @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE so that ParseArgv will discard nextArg @DESCRIPTION: Routine called by ParseArgv to set the axis range @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_axis_range(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Axis_ranges *axis_ranges; int ientry; char *num_string, *cur; /* Get pointer to client data */ axis_ranges = (Axis_ranges *) dst; /* Check for next argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Check that we have enough space in the list */ if (axis_ranges->nentries >= MAX_VAR_DIMS) { (void) fprintf(stderr, "Too many \"%s\" options.\n", key); exit(EXIT_FAILURE); } ientry = axis_ranges->nentries; /* Parse the argument (=,[]) */ /* Remove leading space */ while (ISSPACE(*nextArg)) nextArg++; axis_ranges->name[ientry] = nextArg; /* Find the '=' */ num_string = strchr(nextArg, '='); if ((num_string == NULL) || (num_string == nextArg)) { (void) fprintf(stderr, "\"%s\" option requires the argument =[,]\n", key); exit(EXIT_FAILURE); } /* Remove trailing blanks on name */ cur = num_string - 1; while ((cur>=nextArg) && ISSPACE(*cur)) cur--; cur++; *cur = '\0'; /* Get the start */ num_string++; axis_ranges->start[ientry] = strtol(num_string, &cur, 0); if ((cur == num_string) || !(ISSPACE(*cur) || (*cur == ARG_SEPARATOR) || (*cur == '\0'))) { (void) fprintf(stderr, "\"%s\" option requires the argument =[,]\n", key); exit(EXIT_FAILURE); } /* Skip any spaces */ while (ISSPACE(*cur)) cur++; /* Skip an optional comma */ if (*cur == ARG_SEPARATOR) cur++; /* Look for a count string */ num_string = cur; axis_ranges->count[ientry] = strtol(num_string, &cur, 0); if ((cur == num_string) || (axis_ranges->count[ientry] == 0)) { axis_ranges->count[ientry] = 0; } axis_ranges->nentries++; /* Check for extra stuff (spaces are allowed) */ while (ISSPACE(*cur)) cur++; if (*cur != '\0') { (void) fprintf(stderr, "\"%s\" option requires the argument =[,]\n", key); exit(EXIT_FAILURE); } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_arg_vector @INPUT : key - argv key string (-start, -count) nextArg - string from which vector should be read @OUTPUT : dst - pointer to vector of longs into which values should be written (padded with LONG_MIN) @RETURNS : TRUE, since nextArg is used (unless it is NULL) @DESCRIPTION: Parses a command-line argument into a vector of longs. The string should contain at most MAX_VAR_DIMS comma separated integer values (spaces are skipped). @METHOD : @GLOBALS : @CALLS : @CREATED : June 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_arg_vector(char *dst, char *key, char *nextArg) /* ARGSUSED */ { long *vector; int nvals, i; char *cur, *end, *prev; /* Check for following argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); return FALSE; } /* Get pointer to vector of longs */ vector = (long *) dst; /* Set up pointers to end of string and first non-space character */ end = nextArg + strlen(nextArg); cur = nextArg; while (ISSPACE(*cur)) cur++; nvals = 0; /* Loop through string looking for integers */ while ((nvals < MAX_VAR_DIMS) && (cur!=end)) { /* Get integer */ prev = cur; vector[nvals] = strtol(prev, &cur, 0); if ((cur == prev) || !(ISSPACE(*cur) || (*cur == VECTOR_SEPARATOR) || (*cur == '\0'))) { (void) fprintf(stderr, "expected vector of integers for \"%s\", but got \"%s\"\n", key, nextArg); exit(EXIT_FAILURE); } nvals++; /* Skip any spaces */ while (ISSPACE(*cur)) cur++; /* Skip an optional comma */ if (*cur == VECTOR_SEPARATOR) cur++; } /* Pad with LONG_MIN */ for (i=nvals; i < MAX_VAR_DIMS; i++) { vector[i] = LONG_MIN; } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_default_datatype @INPUT : mincid - id of input minc file @OUTPUT : datatype - datatype of file is_signed - TRUE if data is signed, FALSE if not. Defaults to FALSE for byte, TRUE otherwise. valid_range - DBL_MAX if not known @RETURNS : (nothing) @DESCRIPTION: Routine to get the datatype info from a file. If datatype is not MI_ORIGINAL_TYPE, then is_signed only is set to its default. Otherwise, is_signed is only modified if it is set to INT_MIN and valid_range is only modified if it is set to DBL_MAX. @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_default_datatype(int mincid, nc_type *datatype, int *is_signed, double valid_range[2]) { int imgid; int file_is_signed; nc_type file_datatype; int found_range, file_integer_type, integer_type; /* Get the image variable id */ imgid = ncvarid(mincid, MIimage); /* Get the file data type */ (void) miget_datatype(mincid, imgid, &file_datatype, &file_is_signed); /* Get the type and sign. If a type is specified, then the sign should be the default for that type. If it is not specified, then use the default from the file. */ if (*datatype != MI_ORIGINAL_TYPE) { if (*is_signed == INT_MIN) { *is_signed = ((*datatype == NC_BYTE) ? FALSE : TRUE); } } else { *datatype = file_datatype; if (*is_signed == INT_MIN) { *is_signed = file_is_signed; } } /* Set the valid_range if needed. For integer types, just get the default for the type. For float, get the valid range of the input if it is also float and is specified, otherwise get the image range. */ if (valid_range[0] == DBL_MAX) { /* Test for integer types */ integer_type = (*datatype != NC_FLOAT && *datatype != NC_DOUBLE); file_integer_type = (file_datatype != NC_FLOAT && file_datatype != NC_DOUBLE); /* Integer type */ if (integer_type) { (void) miget_default_range(*datatype, *is_signed, valid_range); } /* Float type */ else { found_range = FALSE; /* Just get input valid_range for float input */ if (!file_integer_type) { (void) miget_valid_range(mincid, imgid, valid_range); if (file_datatype == NC_FLOAT) found_range = (valid_range[1] != FLT_MAX); else if (file_datatype == NC_DOUBLE) found_range = (valid_range[1] != DBL_MAX); } /* If not float input, or did not find valid_range, then get it from the image range (image-max/min) */ if (!found_range) { /* Get the range if the variables exist, otherwise use the default */ if (mivar_exists(mincid, MIimagemax) && mivar_exists(mincid, MIimagemin)) { (void) miget_image_range(mincid, valid_range); } else if (!file_integer_type) { (void) miget_default_range(*datatype, *is_signed, valid_range); } else { valid_range[0] = MI_DEFAULT_MIN; valid_range[1] = MI_DEFAULT_MAX; } } } } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_dim_sizes @INPUT : mincid - id of input minc file dimsize_list - list of dimension names and sizes @OUTPUT : icvid - icvid to modify @RETURNS : (nothing) @DESCRIPTION: Routine to modify an icv so that the appropriate dimensions have given sizes @METHOD : @GLOBALS : @CALLS : @CREATED : May 18, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_dim_sizes(int icvid, int mincid, Dimsize_list *dimsize_list) { int ientry, idim; int imgid, dimid; int ndims; int dim[MAX_VAR_DIMS]; char dimname[MAX_NC_NAME]; int image_dim, n_image_dims; /* Get image dimension info */ imgid = ncvarid(mincid, MIimage); (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); if (ndims > 0) { (void) ncdiminq(mincid, dim[ndims-1], dimname, NULL); if (strcmp(dimname, MIvector_dimension) == 0) ndims--; } /* Get default number of image dimensions */ (void) miicv_inqint(icvid, MI_ICV_NUM_IMGDIMS, &n_image_dims); /* Loop through list of names, looking for dimensions */ for (ientry=0; ientry < dimsize_list->nentries; ientry++) { ncopts = 0; dimid = ncdimid(mincid, dimsize_list->name[ientry]); ncopts = NCOPTS_DEFAULT; for (idim=0; idim < ndims; idim++) { if (dim[idim] == dimid) break; } if (idim < ndims) { image_dim = ndims - idim - 1; (void) miicv_setint(icvid, MI_ICV_DIM_SIZE+image_dim, dimsize_list->size[ientry]); if (n_image_dims < image_dim+1) n_image_dims = image_dim+1; } else { (void) fprintf(stderr, "Unable to set size of dimension \"%s\"\n", dimsize_list->name[ientry]); exit(EXIT_FAILURE); } } /* Update number of image dimensions, if needed */ if (n_image_dims > 2) { (void) miicv_setint(icvid, MI_ICV_NUM_IMGDIMS, n_image_dims); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_reshaping_info @INPUT : mincid - id of input minc file do_norm - indicates if normalization is being done already through the icv fillvalue - value to use where there is no input value do_scalar - TRUE if vector image should be converted to scalar axis_order - order of dimensions by name axis_ranges - range of subscripts for each axis hs_start - starting coordinate of hyperslab to read hs_count - edge lengths of hyperslab to read max_chunk_size_in_kb - maximum size of copy buffer in kbytes. @OUTPUT : reshape_info - information describing the reshaping @RETURNS : (nothing) @DESCRIPTION: Routine to set up reshaping information. @METHOD : @GLOBALS : @CALLS : @CREATED : May 26, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_reshaping_info(int icvid, int mincid, int do_norm, double fillvalue, int do_scalar, char *axis_order[], Axis_ranges *axis_ranges, long hs_start[], long hs_count[], int max_chunk_size_in_kb, Reshape_info *reshape_info) { int input_ndims, input_dim[MAX_VAR_DIMS], order_dim[MAX_VAR_DIMS]; int output_ndims, norder; int idim, jdim, ientry, iloop, order_idim; int input_dim_used[MAX_VAR_DIMS]; char name[MAX_NC_NAME]; int *o2i, *i2o; nc_type datatype; int min_ndims, max_ndims, min_dim[MAX_VAR_DIMS], max_dim[MAX_VAR_DIMS]; int minid, maxid, dimid; long total_size, size; int nstart, ncount; int has_vector_dimension; int num_imgdims; int fastest_input_img_dim, fastest_output_img_dim; long length; long first, last; /* Get input file dimension info */ (void) ncvarinq(mincid, ncvarid(mincid, MIimage), NULL, NULL, &input_ndims, input_dim, NULL); (void) ncdiminq(mincid, input_dim[input_ndims-1], name, NULL); has_vector_dimension = (strcmp(name, MIvector_dimension) == 0); fastest_input_img_dim = (has_vector_dimension ? input_ndims-2 : input_ndims-1); if (do_scalar && has_vector_dimension) input_ndims--; reshape_info->input_ndims = input_ndims; /* Check length of hs_start and hs_count vectors */ for (nstart=0; (nstart input_ndims) || (nstart > input_ndims)) { (void) fprintf(stderr, "Start and/or count vectors are too long.\n"); exit(EXIT_FAILURE); } /* Get start and count from file info and from hs_start and hs_count */ (void) miicv_inqint(icvid, MI_ICV_NUM_IMGDIMS, &num_imgdims); for (idim=0; idim < input_ndims; idim++) { (void) ncdiminq(mincid, input_dim[idim], NULL, &reshape_info->input_size[idim]); if ((idim > fastest_input_img_dim-num_imgdims) && (idim <= fastest_input_img_dim)) { (void) miicv_inqlong(icvid, MI_ICV_DIM_SIZE+fastest_input_img_dim-idim, &length); if (length > 0) { reshape_info->input_size[idim] = length; } } if (idim < nstart) reshape_info->input_start[idim] = hs_start[idim]; else reshape_info->input_start[idim] = 0; if (idim < ncount) reshape_info->input_count[idim] = hs_count[idim]; else reshape_info->input_count[idim] = reshape_info->input_size[idim]; } /* Get input dimension start and count from axis_ranges variable */ for (ientry=0; ientry < axis_ranges->nentries; ientry++) { dimid = ncdimid(mincid, axis_ranges->name[ientry]); for (idim=0; idim < input_ndims; idim++) { if (dimid == input_dim[idim]) break; } if (idim >= input_ndims) { (void) fprintf(stderr, "Unknown image dimension \"%s\"\n", axis_ranges->name[ientry]); exit(EXIT_FAILURE); } reshape_info->input_start[idim] = axis_ranges->start[ientry]; reshape_info->input_count[idim] = axis_ranges->count[ientry]; } /* Check to see if we will need a fill value */ reshape_info->need_fillvalue = FALSE; for (idim=0; idim < input_ndims; idim++) { first = reshape_info->input_start[idim]; last = first; if (reshape_info->input_count[idim] > 0) last += reshape_info->input_count[idim] - 1; else if (reshape_info->input_count[idim] < 0) last += reshape_info->input_count[idim] + 1; if ((first < 0) || (first >= reshape_info->input_size[idim]) || (last < 0) || (last >= reshape_info->input_size[idim])) reshape_info->need_fillvalue = TRUE; } /* Get output dimensions in terms of input */ /* Add up number of output dimensions */ output_ndims = 0; for (idim=0; idim < input_ndims; idim++) { if (reshape_info->input_count[idim] != 0) output_ndims++; } reshape_info->output_ndims = output_ndims; /* Get dim ids for specified order */ for (norder=0; norder < MAX_VAR_DIMS+1; norder++) { if (axis_order[norder] == NULL) break; order_dim[norder] = ncdimid(mincid, axis_order[norder]); } if (norder > output_ndims) { for (idim=0; idim < output_ndims; idim++) { order_dim[idim] = order_dim[idim + norder - output_ndims]; } norder = output_ndims; } /* Keep track of input dims already used in output (dimensions that are disappearing are considered used) */ for (idim=0; idim < input_ndims; idim++) { input_dim_used[idim] = (reshape_info->input_count[idim] == 0); } /* Re-order dimensions */ for (idim=output_ndims-1; idim >= 0; idim--) { /* Output dim loop */ order_idim = idim - output_ndims + norder; for (jdim=input_ndims-1; jdim >= 0; jdim--) { /* Input dim loop */ /* For specified dimensions, look for corresponding input dim */ if (order_idim >= 0) { if (input_dim[jdim] == order_dim[order_idim]) break; } /* For remaining dims, take next available */ else { if (!input_dim_used[jdim]) break; } } /* Check for error */ if ((jdim < 0) || input_dim_used[jdim]) { if (order_idim >= 0) { (void) fprintf(stderr, "Cannot re-order dimension \"%s\" (not found, repeated or removed).\n", axis_order[order_idim]); } else { (void) fprintf(stderr, "Program error in re-ordering axes.\n"); } exit(EXIT_FAILURE); } /* Save dimension mapping */ input_dim_used[jdim] = TRUE; reshape_info->map_out_to_in[idim] = jdim; } /* Get mapping from input to output (-1 means no mapping) */ for (idim=0; idim < input_ndims; idim++) { reshape_info->map_in_to_out[idim] = -1; } for (idim=0; idim < output_ndims; idim++) { reshape_info->map_in_to_out[reshape_info->map_out_to_in[idim]] = idim; } /* Get fastest varying output image dimension (excluding vector dim) */ idim = input_dim[reshape_info->map_out_to_in[output_ndims-1]]; (void) ncdiminq(mincid, idim, name, NULL); fastest_output_img_dim = ((strcmp(name, MIvector_dimension) == 0) ? output_ndims-2 : output_ndims-1); /* Save dimensions used in blocks and chunks */ o2i = reshape_info->map_out_to_in; i2o = reshape_info->map_in_to_out; (void) miicv_inqint(reshape_info->icvid, MI_ICV_TYPE, (int *) &datatype); total_size = nctypelen(datatype); for (idim=0; idim < output_ndims; idim++) { reshape_info->dim_used_in_block[idim] = FALSE; reshape_info->chunk_count[idim] = 1; } for (iloop=0; iloop < 6; iloop++) { /* Go through possible dimensions in descending order of priority. We start with the fastest varying dimension, but allow for the possibility of vector dimensions in either volume (looping twice on the same dimension is not a problem). Note that idim refers to an output dimension. */ switch (iloop) { case 0: idim = output_ndims-1; break; case 1: idim = i2o[input_ndims-1]; break; case 2: idim = fastest_output_img_dim; break; case 3: idim = i2o[fastest_input_img_dim]; break; case 4: idim = fastest_output_img_dim-1; break; case 5: idim = i2o[fastest_input_img_dim-1]; break; default: idim = -1; } if (idim != -1) size = ABS(reshape_info->input_count[o2i[idim]]); else size = 0; if (size == 0) idim = -1; if ((idim != -1) && !reshape_info->dim_used_in_block[idim]) { reshape_info->dim_used_in_block[idim] = TRUE; if ((total_size * size) > (max_chunk_size_in_kb * 1024)) size = max_chunk_size_in_kb * 1024 / total_size; if (size < 1) size = 1; reshape_info->chunk_count[idim] = size; total_size *= size; } } /* Make sure that all input image dimensions are considered used in the block */ for (iloop=2; iloop < num_imgdims; iloop++) { idim = fastest_input_img_dim - iloop; if (idim >= 0) reshape_info->dim_used_in_block[i2o[idim]] = TRUE; } /* If we are doing icv normalization, then all dimensions are used in the block */ if (do_norm) { for (idim=0; idim < output_ndims; idim++) { reshape_info->dim_used_in_block[idim] = TRUE; } } /* Save fillvalue */ reshape_info->fillvalue = fillvalue; /* Are we doing normalization through the icv? */ reshape_info->do_icv_normalization = do_norm; /* Do we need to normalize to slices to a block min and max? */ if (do_norm) { reshape_info->do_block_normalization = FALSE; } else { reshape_info->do_block_normalization = FALSE; /* Loop through block dimensions and check if image-min/max varies on the dimension */ ncopts = 0; minid = ncvarid(mincid, MIimagemin); maxid = ncvarid(mincid, MIimagemax); ncopts = NCOPTS_DEFAULT; if ((minid != MI_ERROR) && (maxid != MI_ERROR)) { (void) ncvarinq(mincid, minid, NULL, NULL, &min_ndims, min_dim, NULL); (void) ncvarinq(mincid, maxid, NULL, NULL, &max_ndims, max_dim, NULL); for (idim=0; idim < input_ndims; idim++) { jdim = reshape_info->map_in_to_out[idim]; if ((jdim>=0) && reshape_info->dim_used_in_block[jdim]) { dimid = input_dim[idim]; for (jdim=0; jdim < min_ndims; jdim++) { if (min_dim[jdim] == dimid) { reshape_info->do_block_normalization = TRUE; } } for (jdim=0; jdim < max_ndims; jdim++) { if (max_dim[jdim] == dimid) { reshape_info->do_block_normalization = TRUE; } } } } } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : setup_output_file @INPUT : mincid - id of output minc file history - string to be added to history list reshape_info - information describing the reshaping @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Routine to set up the output file @METHOD : @GLOBALS : @CALLS : @CREATED : June 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void setup_output_file(int mincid, char *history, Reshape_info *reshape_info) { int output_ndims, output_dim[MAX_VAR_DIMS]; int input_ndims, input_dim[MAX_VAR_DIMS]; int minmax_ndims, minmax_dim[MAX_VAR_DIMS]; int idim, odim, iloop; int varid, icvid, imgid, varid2; char dimname[MAX_NC_NAME]; long length; int excluded_vars[2*MAX_VAR_DIMS + 10]; int nexcluded; nc_type datatype; char signtype[MI_MAX_ATTSTR_LEN]; double valid_range[2]; char *string; int att_length; int has_vector_dimension; int fastest_img_dim; /* Get useful info */ output_ndims = reshape_info->output_ndims; (void) ncvarinq(reshape_info->inmincid, ncvarid(reshape_info->inmincid, MIimage), NULL, NULL, &input_ndims, input_dim, NULL); input_ndims = reshape_info->input_ndims; /* Check for vector dimension */ (void) ncdiminq(reshape_info->inmincid, input_dim[input_ndims-1], dimname, NULL); has_vector_dimension = (strcmp(dimname, MIvector_dimension) == 0); fastest_img_dim = (has_vector_dimension ? input_ndims-2 : input_ndims-1); /* Create image dimensions */ for (odim=0; odim < output_ndims; odim++) { idim = reshape_info->map_out_to_in[odim]; length = ABS(reshape_info->input_count[idim]); (void) ncdiminq(reshape_info->inmincid, input_dim[idim], dimname, NULL); output_dim[odim] = ncdimdef(mincid, dimname, length); } /* Copy all variables except dimensions and dimension widths */ ncopts = 0; nexcluded = 0; for (idim = 0; idim < input_ndims; idim++) { (void) ncdiminq(reshape_info->inmincid, input_dim[idim], dimname, NULL); if ((varid=ncvarid(reshape_info->inmincid, dimname)) != MI_ERROR) excluded_vars[nexcluded++] = varid; (void) strncat(dimname, DIM_WIDTH_SUFFIX, sizeof(dimname)-strlen(dimname)-1); if ((varid=ncvarid(reshape_info->inmincid, dimname)) != MI_ERROR) excluded_vars[nexcluded++] = varid; } if ((varid=ncvarid(reshape_info->inmincid, MIimage)) != MI_ERROR) excluded_vars[nexcluded++] = varid; if ((varid=ncvarid(reshape_info->inmincid, MIimagemax)) != MI_ERROR) excluded_vars[nexcluded++] = varid; if ((varid=ncvarid(reshape_info->inmincid, MIimagemin)) != MI_ERROR) excluded_vars[nexcluded++] = varid; (void) micopy_all_var_defs(reshape_info->inmincid, mincid, nexcluded, excluded_vars); ncopts = NCOPTS_DEFAULT; /* Create image dimension variables */ for (odim=0; odim < output_ndims; odim++) { idim = reshape_info->map_out_to_in[odim]; create_dim_var(mincid, output_dim[odim], reshape_info->icvid, fastest_img_dim - idim, reshape_info->inmincid, reshape_info->input_start[idim], reshape_info->input_count[idim]); } /* Get basic image variable info */ icvid = reshape_info->icvid; (void) miicv_inqint(icvid, MI_ICV_TYPE, (int *) &datatype); (void) miicv_inqstr(icvid, MI_ICV_SIGN, signtype); (void) miicv_inqdbl(icvid, MI_ICV_VALID_MIN, &valid_range[0]); (void) miicv_inqdbl(icvid, MI_ICV_VALID_MAX, &valid_range[1]); /* Set the valid range to include 0.0 for floating point if needed */ if (reshape_info->need_fillvalue && ((datatype == NC_FLOAT) || (datatype == NC_DOUBLE)) && (reshape_info->fillvalue == NOFILL)) { if (0.0 < valid_range[0]) valid_range[0] = 0.0; if (0.0 > valid_range[1]) valid_range[1] = 0.0; } /* Create the imagemax/min variables */ minmax_ndims = 0; for (odim=0; odim < output_ndims; odim++) { if (!reshape_info->dim_used_in_block[odim]) { minmax_dim[minmax_ndims++] = output_dim[odim]; } } for (iloop=0; iloop < 2; iloop++) { if (iloop == 0) string = MIimagemin; else string = MIimagemax; varid = micreate_std_variable(mincid, string, NC_DOUBLE, minmax_ndims, minmax_dim); ncopts = 0; varid2 = ncvarid(reshape_info->inmincid, string); ncopts = NCOPTS_DEFAULT; if (varid2 != MI_ERROR) (void) micopy_all_atts(reshape_info->inmincid, varid2, mincid, varid); } /* Create the image variable */ imgid = micreate_std_variable(mincid, MIimage, datatype, output_ndims, output_dim); reshape_info->outimgid = imgid; (void) micopy_all_atts(reshape_info->inmincid, ncvarid(reshape_info->inmincid, MIimage), mincid, imgid); (void) miattputstr(mincid, imgid, MIsigntype, signtype); (void) miset_valid_range(mincid, imgid, valid_range); (void) miattputstr(mincid, imgid, MIcomplete, MI_FALSE); /* Add history */ ncopts=0; if ((ncattinq(mincid, NC_GLOBAL, MIhistory, &datatype, &att_length) == MI_ERROR) || (datatype != NC_CHAR)) att_length = 0; att_length += strlen(history) + 1; string = malloc(att_length); string[0] = '\0'; (void) miattgetstr(mincid, NC_GLOBAL, MIhistory, att_length, string); ncopts = NCOPTS_DEFAULT; (void) strcat(string, history); (void) miattputstr(mincid, NC_GLOBAL, MIhistory, string); free(string); /* Get into data mode */ (void) ncsetfill(mincid, NC_NOFILL); (void) ncendef(mincid); /* Copy all the other data */ (void) micopy_all_var_values(reshape_info->inmincid, mincid, nexcluded, excluded_vars); /* Copy the dimension variable values, if needed */ for (odim=0; odim < output_ndims; odim++) { idim = reshape_info->map_out_to_in[odim]; copy_dimension_values(mincid, output_dim[odim], reshape_info->inmincid, reshape_info->input_start[idim], reshape_info->input_count[idim]); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_dim_var @INPUT : outmincid - id of output minc file outdimid - id of output dimension inicvid - id of input icv cur_image_dim - image dim number of current dimension in input icv (0 is fastest varying dimension) inmincid - id of input minc file input_start - start index of input dimension input_count - count for input dimension (may be negative) @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Creates a dimension variable and sets attributes properly. @METHOD : @GLOBALS : @CALLS : @CREATED : June 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void create_dim_var(int outmincid, int outdimid, int inicvid, int cur_image_dim, int inmincid, long input_start, long input_count) { int invarid, outvarid; int num_image_dims, var_ndims; int is_regular, step_found, start_found, changed_spacing; double dim_start, dim_step, icv_start, icv_step; char dimname[MAX_NC_NAME]; char spacing[MAX_NC_NAME]; /* Get the dimension name */ (void) ncdiminq(outmincid, outdimid, dimname, NULL); /* Get number of image dimensions */ (void) miicv_inqint(inicvid, MI_ICV_NUM_IMGDIMS, &num_image_dims); /* Get step and start and spacing for dimension */ dim_step = 1.0; dim_start = 0.0; is_regular = TRUE; changed_spacing = ((input_start != 0) || (input_count <= 0)); ncopts = 0; invarid = ncvarid(inmincid, dimname); if (invarid != MI_ERROR) { step_found = (miattget1(inmincid, invarid, MIstep, NC_DOUBLE, &dim_step) != MI_ERROR); start_found = (miattget1(inmincid, invarid, MIstart, NC_DOUBLE, &dim_start) != MI_ERROR); (void) ncvarinq(inmincid, invarid, NULL, NULL, &var_ndims, NULL, NULL); if (var_ndims > 0) { (void) strcpy(spacing, MI_IRREGULAR); (void) miattgetstr(inmincid, invarid, MIspacing, sizeof(spacing), spacing); is_regular = (strcmp(spacing, MI_REGULAR) == 0); } } ncopts = NCOPTS_DEFAULT; /* Is the sampling changed because of the icv? */ if ((cur_image_dim < num_image_dims) && (cur_image_dim >= 0)) { (void) miicv_inqdbl(inicvid, MI_ICV_DIM_STEP+cur_image_dim, &icv_step); (void) miicv_inqdbl(inicvid, MI_ICV_DIM_START+cur_image_dim, &icv_start); if ((icv_step != dim_step) || (icv_start != dim_start)) { dim_step = icv_step; dim_start = icv_start; is_regular = TRUE; changed_spacing = TRUE; } } /* If spacing is not changed and the input variable does not exist don't create the variable */ if (!changed_spacing && (invarid == MI_ERROR)) return; /* Calculate the new dim_start and dim_step (if needed) */ dim_start += input_start * dim_step; if (input_count < 0) dim_step = -dim_step; /* Create the variable */ var_ndims = (is_regular ? 0 : 1); ncopts = 0; outvarid = micreate_std_variable(outmincid, dimname, NC_DOUBLE, var_ndims, &outdimid); ncopts = NCOPTS_DEFAULT; if (outvarid == MI_ERROR) { outvarid = ncvardef(outmincid, dimname, NC_DOUBLE, var_ndims, &outdimid); } if (invarid != MI_ERROR) (void) micopy_all_atts(inmincid, invarid, outmincid, outvarid); if (is_regular || step_found) (void) miattputdbl(outmincid, outvarid, MIstep, dim_step); if (is_regular || start_found) (void) miattputdbl(outmincid, outvarid, MIstart, dim_start); /* Create width variable if needed */ ncopts = 0; (void) strncat(dimname, DIM_WIDTH_SUFFIX, sizeof(dimname)-strlen(dimname)-1); invarid = ncvarid(inmincid, dimname); if (invarid != MI_ERROR) { (void) ncvarinq(inmincid, invarid, NULL, NULL, &var_ndims, NULL, NULL); if (var_ndims > 0) var_ndims = 1; outvarid = micreate_std_variable(outmincid, dimname, NC_DOUBLE, var_ndims, &outdimid); if (outvarid == MI_ERROR) { outvarid = ncvardef(outmincid, dimname, NC_DOUBLE, var_ndims, &outdimid); } if (invarid != MI_ERROR) (void) micopy_all_atts(inmincid, invarid, outmincid, outvarid); } ncopts = NCOPTS_DEFAULT; } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_dimension_values @INPUT : outmincid - id of output minc file outdimid - id of output dimension inmincid - id of input minc file input_start - start index of input dimension input_count - length of input dimension @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Copies the data for a dimension variable. @METHOD : @GLOBALS : @CALLS : @CREATED : June 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void copy_dimension_values(int outmincid, int outdimid, int inmincid, long input_start, long input_count) { char dimname[MAX_NC_NAME]; char varname[MAX_NC_NAME]; /* Get the dimension name */ (void) ncdiminq(outmincid, outdimid, dimname, NULL); (void) strcpy(varname, dimname); /* Copy the dimension coorindates */ copy_dim_var_values(outmincid, dimname, varname, inmincid, input_start, input_count); /* Copy the dimension widths */ (void) strncat(varname, DIM_WIDTH_SUFFIX, sizeof(varname)-strlen(varname)-1); copy_dim_var_values(outmincid, dimname, varname, inmincid, input_start, input_count); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_dim_var_values @INPUT : outmincid - id of output minc file dimname - name of dimension varname - name of variable to copy inmincid - id of input minc file input_start - start index of input dimension input_count - length of input dimension @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Copies the data for a dimension variable. @METHOD : @GLOBALS : @CALLS : @CREATED : June 16, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void copy_dim_var_values(int outmincid, char *dimname, char *varname, int inmincid, long input_start, long input_count) { int invarid, outvarid; int in_ndims, in_dim[MAX_VAR_DIMS], out_ndims; char string[MAX_NC_NAME]; int good_data, is_width, flip_dimension; long output_index, input_index, index, input_length; double value, dim_width, dim_step, dim_start; /* Do we need to copy data? */ ncopts = 0; outvarid = ncvarid(outmincid, varname); ncopts = NCOPTS_DEFAULT; if (outvarid == MI_ERROR) return; (void) ncvarinq(outmincid, outvarid, NULL, NULL, &out_ndims, NULL, NULL); if (out_ndims != 1) return; /* Is this a width variable? */ index = strlen(varname) - strlen(DIM_WIDTH_SUFFIX); if (index < 0) is_width = FALSE; else is_width = (strcmp(&varname[index], DIM_WIDTH_SUFFIX)); /* Check if there is a valid dimension variable from which to copy */ ncopts = 0; invarid = ncvarid(inmincid, varname); ncopts = NCOPTS_DEFAULT; good_data = (invarid != MI_ERROR); if (good_data) { (void) ncvarinq(inmincid, invarid, NULL, NULL, &in_ndims, in_dim, NULL); good_data = (in_ndims == 1); } if (good_data) { (void) ncdiminq(inmincid, in_dim[0], string, &input_length); good_data = (strcmp(string, dimname) == 0); } /* Get data from input file for estimating unknown values */ if (is_width) { /* Get width for width variables */ dim_width = 0.0; ncopts = 0; (void) miattget1(inmincid, invarid, MIwidth, NC_DOUBLE, &dim_width); ncopts = NCOPTS_DEFAULT; } else { /* Get step and start for coordinate variables */ dim_step = 1.0; dim_start = 0.0; if (good_data) { input_index = 0; (void) mivarget1(inmincid, invarid, &input_index, NC_DOUBLE, NULL, &dim_start); input_index = input_length - 1; if (input_length <= 1) { ncopts = 0; (void) miattget1(inmincid, invarid, MIstep, NC_DOUBLE, &dim_step); ncopts = NCOPTS_DEFAULT; } else { (void) mivarget1(inmincid, invarid, &input_index, NC_DOUBLE, NULL, &value); dim_step = (value - dim_start) / ((double) input_length - 1); } } else { ncopts = 0; (void) miattget1(inmincid, invarid, MIstep, NC_DOUBLE, &dim_step); (void) miattget1(inmincid, invarid, MIstart, NC_DOUBLE, &dim_start); ncopts = NCOPTS_DEFAULT; } if (dim_step == 0.0) dim_step = 1.0; } /* Loop through output values */ flip_dimension = (input_count < 0); input_count = ABS(input_count); for (output_index=0; output_index < input_count; output_index++) { /* Get input value */ if (!flip_dimension) { input_index = input_start + output_index; } else { input_index = input_start - output_index; } if (good_data && (input_index >= 0) && (input_index < input_length)) { (void) mivarget1(inmincid, invarid, &input_index, NC_DOUBLE, NULL, &value); } else { if (is_width) { value = dim_width; } else { value = input_index * dim_step + dim_start; } } (void) mivarput1(outmincid, outvarid, &output_index, NC_DOUBLE, NULL, &value); } } minc-2.2.00/progs/mincreshape/copy_data.c0000644000265600003100000007725212027132663015215 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : copy_data @DESCRIPTION: File containing routines to copy data when reshaping. @METHOD : @GLOBALS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : * $Log: copy_data.c,v $ * Revision 6.8 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.7 2008/01/13 09:38:54 stever * Avoid compiler warnings about functions and variables that are defined * but not used. Remove some such functions and variables, * conditionalize some, and move static declarations out of header files * into C files. * * Revision 6.6 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.5 2006/05/19 00:35:58 bert * Add config.h to several files that might need it * * Revision 6.4 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.3 2001/04/17 18:40:24 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.2 1999/10/19 14:45:28 neelin * Fixed Log subsitutions for CVS * * Revision 6.1 1998/08/19 13:05:28 neelin * Added code to free minmax buffer. * * Revision 6.0 1997/09/12 13:24:12 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:10 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:44 neelin * Release of minc version 0.4 * * Revision 3.1 1995/10/03 13:34:14 neelin * Fixed bug in truncate_input_vectors - was not handling out-of-range * start values properly. * * Revision 3.0 1995/05/15 19:32:36 neelin * Release of minc version 0.3 * * Revision 1.5 1995/03/20 13:32:03 neelin * Fixed -normalize option. * * Revision 1.4 1994/12/02 09:08:56 neelin * Moved nd_loop to proglib. * * Revision 1.3 94/11/23 11:46:38 neelin * Handle image-min/max properly when using icv for normalization. * * Revision 1.2 94/11/22 08:45:11 neelin * Fixed handling of normalization for number of image dimensions > 2. * Added appropriate default values of image-max and image-min. * * Revision 1.1 94/11/02 16:21:09 neelin * Initial revision * @COPYRIGHT : Copyright 1994 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "mincreshape.h" #define ROUND( x ) ((long) ((x) + ( ((x) >= 0) ? 0.5 : (-0.5) ) )) static void get_num_minmax_values(Reshape_info *reshape_info, long *block_start, long *block_count, long *num_min_values, long *num_max_values); static void handle_normalization(Reshape_info *reshape_info, long *block_start, long *block_count, double *minmax_buffer, double *fillvalue); static void get_block_min_and_max(Reshape_info *reshape_info, long *block_start, long *block_count, double *minmax_buffer, double *minimum, double *maximum); static void truncate_input_vectors(Reshape_info *reshape_info, long *input_start, long *input_count); static void translate_output_to_input(Reshape_info *reshape_info, long *output_start, long *output_count, long *input_start, long *input_count); static void translate_input_to_output(Reshape_info *reshape_info, long *input_start, long *input_count, long *output_start, long *output_count); static void copy_the_chunk(Reshape_info *reshape_info, long chunk_start[], long chunk_count[], void *chunk_data, double fillvalue); static void convert_value_from_double(double dvalue, nc_type datatype, int is_signed, void *ptr); /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_data @INPUT : reshape_info - information for reshaping volume @OUTPUT : (none) @RETURNS : (none) @DESCRIPTION: Copies data from one input volume to another, reorganizing it according to the reshaping info. @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void copy_data(Reshape_info *reshape_info) { int idim, odim, out_ndims; long block_begin[MAX_VAR_DIMS], block_end[MAX_VAR_DIMS]; long block_count[MAX_VAR_DIMS]; long block_cur_start[MAX_VAR_DIMS], block_cur_count[MAX_VAR_DIMS]; long chunk_begin[MAX_VAR_DIMS], chunk_end[MAX_VAR_DIMS]; long chunk_count[MAX_VAR_DIMS]; long chunk_cur_start[MAX_VAR_DIMS], chunk_cur_count[MAX_VAR_DIMS]; long total_size; long num_min_values, num_max_values, num_values; double fillvalue, *minmax_buffer; void *chunk_data; /* Get number of dimensions */ out_ndims = reshape_info->output_ndims; /* Set up variables for looping through blocks */ for (odim=0; odim < out_ndims; odim++) { idim = reshape_info->map_out_to_in[odim]; block_begin[odim] = 0; block_end[odim] = ABS(reshape_info->input_count[idim]); if (reshape_info->dim_used_in_block[odim]) block_count[odim] = ABS(reshape_info->input_count[idim]); else block_count[odim] = 1; } /* Figure out size of chunks and allocate space */ total_size = nctypelen(reshape_info->output_datatype); for (odim=0; odim < out_ndims; odim++) { total_size *= reshape_info->chunk_count[odim]; } chunk_data = malloc(total_size); /* Get enough space for image-min and max values for a block */ get_num_minmax_values(reshape_info, NULL, block_count, &num_min_values, &num_max_values); num_values = ((num_min_values > num_max_values) ? num_min_values : num_max_values); if (num_values > 0) minmax_buffer = malloc(num_values * sizeof(double)); else minmax_buffer = NULL; /* Print log message */ if (reshape_info->verbose) { (void) fprintf(stderr, "Copying chunks:"); (void) fflush(stderr); } /* Loop through blocks */ nd_begin_looping(block_begin, block_cur_start, out_ndims); while (!nd_end_of_loop(block_cur_start, block_end, out_ndims)) { /* Set up count for current block */ nd_update_current_count(block_cur_start, block_count, block_end, block_cur_count, out_ndims); /* Set up chunk begin, end and count */ for (odim=0; odim < out_ndims; odim++) { chunk_begin[odim] = block_cur_start[odim]; chunk_end[odim] = chunk_begin[odim] + block_cur_count[odim]; chunk_count[odim] = reshape_info->chunk_count[odim]; } /* Set up icv for normalization, set output image-max/min and calculate pixel fill value to use for current block */ handle_normalization(reshape_info, block_cur_start, block_cur_count, minmax_buffer, &fillvalue); /* Loop through chunks */ nd_begin_looping(chunk_begin, chunk_cur_start, out_ndims); while (!nd_end_of_loop(chunk_cur_start, chunk_end, out_ndims)) { /* Set up count for current chunk */ nd_update_current_count(chunk_cur_start, chunk_count, chunk_end, chunk_cur_count, out_ndims); /* Print log message for chunk */ if (reshape_info->verbose) { (void) fprintf(stderr, "."); (void) fflush(stderr); } /* Copy the chunk */ copy_the_chunk(reshape_info, chunk_cur_start, chunk_cur_count, chunk_data, fillvalue); /* Increment chunk loop count */ nd_increment_loop(chunk_cur_start, chunk_begin, chunk_count, chunk_end, out_ndims); } /* Increment block loop count */ nd_increment_loop(block_cur_start, block_begin, block_count, block_end, out_ndims); } /* Free the chunk space */ free(chunk_data); /* Free minmax buffer */ if (minmax_buffer != NULL) { free(minmax_buffer); } /* Print ending log message */ if (reshape_info->verbose) { (void) fprintf(stderr, "Done.\n"); (void) fflush(stderr); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_num_minmax_values @INPUT : reshape_info - information for reshaping volume block_start - start for a block (or NULL) block_count - count for a block @OUTPUT : num_min_values - number of image-min values to be read num_max_values - number of image-max values to be read @RETURNS : (nothing) @DESCRIPTION: Gets the number of image-min and image-max values that correspond to a block. If block_start is NULL, then it is assumed to translate to an input start of [0,0,...]. Note that only the true number of values for the specified block is computed (specifying a hyperslab that goes beyond file extents does not give a bigger number of values). @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_num_minmax_values(Reshape_info *reshape_info, long *block_start, long *block_count, long *num_min_values, long *num_max_values) { int iloop, idim, ndims; int varid, inimgid; long size; long minmax_count[MAX_VAR_DIMS]; long input_block_start[MAX_VAR_DIMS]; long input_block_count[MAX_VAR_DIMS]; long *num_values; /* Check for icv normalization */ if (reshape_info->do_icv_normalization) { *num_min_values = 0; *num_max_values = 0; return; } /* Translate output block count to input count */ translate_output_to_input(reshape_info, block_start, block_count, input_block_start, input_block_count); if (block_start != NULL) { truncate_input_vectors(reshape_info, input_block_start, input_block_count); } inimgid = ncvarid(reshape_info->inmincid, MIimage); /* Loop over image-min and image-max */ for (iloop=0; iloop < 2; iloop++) { /* Get varid and pointer to return value */ ncopts = 0; switch (iloop) { case 0: varid = ncvarid(reshape_info->inmincid, MIimagemin); num_values = num_min_values; /* Pointer to long */ break; case 1: varid = ncvarid(reshape_info->inmincid, MIimagemax); num_values = num_max_values; /* Pointer to long */ break; } ncopts = NCOPTS_DEFAULT; /* Translate block count to min or max count and work out the total number of values. */ size = 0; if (varid != MI_ERROR) { (void) ncvarinq(reshape_info->inmincid, varid, NULL, NULL, &ndims, NULL, NULL); (void) mitranslate_coords(reshape_info->inmincid, inimgid, input_block_count, varid, minmax_count); size = 1; for (idim=0; idim < ndims; idim++) { size *= minmax_count[idim]; } } *num_values = size; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : handle_normalization @INPUT : reshape_info - information for reshaping volume block_start - start of current block block_count - count for current block minmax_buffer - buffer space for getting min and max values @OUTPUT : fillvalue - pixel fill value to use for this block @RETURNS : (none) @DESCRIPTION: Sets up icv for normalization to ensure that block is internally normalized. Output image-max and min are set. The appropriate pixel fill value is calculated for this min and max (applies to the whole block). @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void handle_normalization(Reshape_info *reshape_info, long *block_start, long *block_count, double *minmax_buffer, double *fillvalue) { int iloop; int inmincid, inimgid, varid, icvid; long minmax_start[MAX_VAR_DIMS]; double minimum, maximum, *extreme, valid_min, valid_max, denom; char *varname; /* Get input minc id, image id and icv id*/ inmincid = reshape_info->inmincid; inimgid = ncvarid(inmincid, MIimage); icvid = reshape_info->icvid; /* Get input min and max for block */ get_block_min_and_max(reshape_info, block_start, block_count, minmax_buffer, &minimum, &maximum); /* Modify the icv if necessary */ if (reshape_info->do_block_normalization) { (void) miicv_detach(icvid); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MIN, minimum); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MAX, maximum); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_attach(icvid, inmincid, inimgid); } /* Save the image max and min for the block */ for (iloop=0; iloop < 2; iloop++) { /* Get varid and pointer to min or max value */ switch (iloop) { case 0: varname = MIimagemin; extreme = &minimum; break; case 1: varname = MIimagemax; extreme = &maximum; break; } /* Save the value */ ncopts = 0; varid = ncvarid(reshape_info->outmincid, varname); ncopts = NCOPTS_DEFAULT; if (varid != MI_ERROR) { (void) mitranslate_coords(reshape_info->outmincid, reshape_info->outimgid, block_start, varid, minmax_start); (void) mivarput1(reshape_info->outmincid, varid, minmax_start, NC_DOUBLE, NULL, extreme); } } /* Calculate the pixel fill value */ *fillvalue = ((reshape_info->fillvalue == NOFILL) ? 0.0 : reshape_info->fillvalue); if ((reshape_info->output_datatype != NC_FLOAT) && (reshape_info->output_datatype != NC_DOUBLE) && (*fillvalue != FILL)) { (void) miicv_inqdbl(icvid, MI_ICV_VALID_MIN, &valid_min); (void) miicv_inqdbl(icvid, MI_ICV_VALID_MAX, &valid_max); denom = maximum - minimum; if (denom == 0.0) { *fillvalue = valid_min; } else { *fillvalue = (*fillvalue - minimum) * (valid_max - valid_min) / denom + valid_min; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_block_min_and_max @INPUT : reshape_info - information for reshaping volume block_start - start of current block block_count - count for current block minmax_buffer - buffer space for getting min and max values @OUTPUT : minimum - input minimum for block maximum - input maximum for block @RETURNS : (none) @DESCRIPTION: Gets the min and max for the input file for a given output block. @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_block_min_and_max(Reshape_info *reshape_info, long *block_start, long *block_count, double *minmax_buffer, double *minimum, double *maximum) { int iloop; long num_min_values, num_max_values, ivalue; int inmincid, inimgid, varid, icvid; long minmax_start[MAX_VAR_DIMS], minmax_count[MAX_VAR_DIMS]; long input_block_start[MAX_VAR_DIMS], input_block_count[MAX_VAR_DIMS]; double *extreme; long num_values; char *varname; double sign, default_extreme; /* Get input minc id, image id and icv id*/ inmincid = reshape_info->inmincid; inimgid = ncvarid(inmincid, MIimage); icvid = reshape_info->icvid; /* Is the icv doing the normalization? */ if (reshape_info->do_icv_normalization) { (void) miicv_inqdbl(icvid, MI_ICV_NORM_MIN, minimum); (void) miicv_inqdbl(icvid, MI_ICV_NORM_MAX, maximum); return; } /* Translate output block count to input count */ translate_output_to_input(reshape_info, block_start, block_count, input_block_start, input_block_count); truncate_input_vectors(reshape_info, input_block_start, input_block_count); /* Get number of min and max values */ get_num_minmax_values(reshape_info, block_start, block_count, &num_min_values, &num_max_values); /* Loop over image-min and image-max getting block min and max */ for (iloop=0; iloop < 2; iloop++) { /* Get varid and pointer to min or max value */ switch (iloop) { case 0: num_values = num_min_values; varname = MIimagemin; extreme = minimum; sign = -1.0; default_extreme = 0.0; break; case 1: num_values = num_max_values; varname = MIimagemax; extreme = maximum; sign = +1.0; default_extreme = 1.0; break; } /* Get values from file */ if (num_values > 0) { varid = ncvarid(inmincid, varname); (void) mitranslate_coords(inmincid, inimgid, input_block_start, varid, minmax_start); (void) mitranslate_coords(inmincid, inimgid, input_block_count, varid, minmax_count); (void) mivarget(reshape_info->inmincid, varid, minmax_start, minmax_count, NC_DOUBLE, NULL, minmax_buffer); *extreme = minmax_buffer[0]; for (ivalue=1; ivalue < num_values; ivalue++) { if ((minmax_buffer[ivalue] * sign) > (*extreme * sign)) *extreme = minmax_buffer[ivalue]; } } else { *extreme = default_extreme; } if (reshape_info->need_fillvalue && (reshape_info->fillvalue == NOFILL) && (0.0 > (*extreme * sign))) *extreme = 0.0; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : truncate_input_vectors @INPUT : reshape_info - information for reshaping volume input_start - start of input hyperslab (or NULL) input_count - count for input hyperslab @OUTPUT : input_start - start of input hyperslab (or NULL) input_count - count for input hyperslab @RETURNS : (nothing) @DESCRIPTION: Input_start and input_count are truncated to specify a legal hyperslab for the input file (if not specified, input_start is assumed to be [0,0,...]). @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void truncate_input_vectors(Reshape_info *reshape_info, long *input_start, long *input_count) { int idim; long first, last; /* last is actually last_index+1 */ /* Check for NULL vectors */ if (input_count == NULL) return; /* Loop through input dimensions */ for (idim=0; idim < reshape_info->input_ndims; idim++) { first = ( (input_start != NULL) ? input_start[idim] : 0 ); last = first + input_count[idim]; if (first < 0) first = 0; else if (first >= reshape_info->input_size[idim]) first = reshape_info->input_size[idim] - 1; if (last < 0) last = 0; else if (last >= reshape_info->input_size[idim]) last = reshape_info->input_size[idim]; if (input_start != NULL) input_start[idim] = first; input_count[idim] = last - first; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : translate_output_to_input @INPUT : reshape_info - information for reshaping volume output_start - start of output hyperslab (or NULL) output_count - count for output hyperslab @OUTPUT : input_start - start of input hyperslab (or NULL) input_count - count for input hyperslab @RETURNS : (nothing) @DESCRIPTION: Translates an output start and count to an input start and count. If output_start or input_start are NULL, then only the count is translated. @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void translate_output_to_input(Reshape_info *reshape_info, long *output_start, long *output_count, long *input_start, long *input_count) { int idim, odim; /* Check for NULL vectors */ if ((input_count == NULL) || (output_count == NULL)) return; /* Loop through input dimensions */ for (idim=0; idim < reshape_info->input_ndims; idim++) { odim = reshape_info->map_in_to_out[idim]; input_count[idim] = ((odim >= 0) ? output_count[odim] : 1); if ((input_start != NULL) && (output_start != NULL)) { input_start[idim] = reshape_info->input_start[idim]; if (odim >= 0) { if (reshape_info->input_count[idim] > 0) input_start[idim] += output_start[odim]; else input_start[idim] -= (output_start[odim] + output_count[odim] - 1); } } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : translate_input_to_output @INPUT : reshape_info - information for reshaping volume input_start - start of output hyperslab (or NULL) input_count - count for output hyperslab @OUTPUT : output_start - start of input hyperslab (or NULL) output_count - count for input hyperslab @RETURNS : (nothing) @DESCRIPTION: Translates an input start and count to an output start and count. If output_start or input_start are NULL, then only the count is translated. @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void translate_input_to_output(Reshape_info *reshape_info, long *input_start, long *input_count, long *output_start, long *output_count) { int idim, odim; /* Check for NULL vectors */ if ((input_count == NULL) || (output_count == NULL)) return; /* Loop through output dimensions */ for (odim=0; odim < reshape_info->output_ndims; odim++) { idim = reshape_info->map_out_to_in[odim]; output_count[odim] = input_count[idim]; if ((input_start != NULL) && (output_start != NULL)) { if (reshape_info->input_count[idim] > 0) output_start[odim] = input_start[idim] - reshape_info->input_start[idim]; else output_start[odim] = reshape_info->input_start[idim] - (input_start[idim] + input_count[idim] - 1); } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_the_chunk @INPUT : reshape_info - information for reshaping volume chunk_start - start of current block chunk_count - count for current block chunk_data - pointer to enough space for chunk fillvalue - pixel value to zero volume, if necessary. @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Copies the chunk from the input file to the output file. @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void copy_the_chunk(Reshape_info *reshape_info, long chunk_start[], long chunk_count[], void *chunk_data, double fillvalue) { int idim, odim, in_ndims, out_ndims; long input_start[MAX_VAR_DIMS], input_count[MAX_VAR_DIMS]; long output_start[MAX_VAR_DIMS], output_count[MAX_VAR_DIMS]; long input_imap[MAX_VAR_DIMS], output_imap[MAX_VAR_DIMS]; void *output_origin; int datatype_size; long total_size, ipix, first, last; int zero_data, really_copy_the_data; union { char c; short s; long l; float f; double d; } value_buffer; /* Get number of dimensions */ out_ndims = reshape_info->output_ndims; in_ndims = reshape_info->input_ndims; /* Get size of output datatype */ datatype_size = nctypelen(reshape_info->output_datatype); /* Create input start and count */ translate_output_to_input(reshape_info, chunk_start, chunk_count, input_start, input_count); /* Find out if we need to zero the volume and if we need to copy any data */ zero_data = FALSE; really_copy_the_data = TRUE; total_size = 1; for (idim=0; idim < in_ndims; idim++) { first = input_start[idim]; last = input_start[idim] + input_count[idim] - 1; if ((first < 0) || (last >= reshape_info->input_size[idim])) zero_data = TRUE; if ((last < 0) || (first >= reshape_info->input_size[idim])) really_copy_the_data = FALSE; total_size *= input_count[idim]; } /* Make sure that input vectors are legal and translate them back to output */ truncate_input_vectors(reshape_info, input_start, input_count); translate_input_to_output(reshape_info, input_start, input_count, output_start, output_count); /* Write out zero data if needed */ if (zero_data) { convert_value_from_double(fillvalue, reshape_info->output_datatype, reshape_info->output_is_signed, &value_buffer); for (ipix=0; ipix < total_size; ipix++) { (void) memcpy((char *)chunk_data + ipix*datatype_size, &value_buffer, datatype_size); } (void) ncvarput(reshape_info->outmincid, reshape_info->outimgid, chunk_start, chunk_count, chunk_data); } /* Set up hypothetical imap variable for input */ for (idim=in_ndims-1; idim >= 0; idim--) { input_imap[idim] = ((idim == in_ndims-1) ? datatype_size : input_imap[idim+1] * input_count[idim+1]); } /* Create output imap variable from input one (re-ordering dimensions and flipping). Also work out the chunk origin (point to byte for output [0,0,0...]). */ output_origin = chunk_data; for (odim=0; odim < out_ndims; odim++) { idim = reshape_info->map_out_to_in[odim]; if (reshape_info->input_count[idim] > 0) { output_imap[odim] = input_imap[idim]; } else { output_imap[odim] = -input_imap[idim]; output_origin = (void *) ((char *)output_origin - (output_count[odim] - 1) * output_imap[odim]); } } /* Should we really copy the data? */ if (really_copy_the_data) { /* Read in the data */ (void) miicv_get(reshape_info->icvid, input_start, input_count, chunk_data); /* Write it out */ (void) ncvarputg(reshape_info->outmincid, reshape_info->outimgid, output_start, output_count, NULL, output_imap, output_origin); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_value_from_double @INPUT : dvalue - double value to convert datatype - type of desired value is_signed - TRUE if desired value is signed @OUTPUT : ptr - pointer to converted value @RETURNS : (nothing) @DESCRIPTION: Converts a value from double to some other value. @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void convert_value_from_double(double dvalue, nc_type datatype, int is_signed, void *ptr) { switch (datatype) { case NC_BYTE : if (!is_signed) { dvalue = MAX(0, dvalue); dvalue = MIN(UCHAR_MAX, dvalue); *((unsigned char *) ptr) = ROUND(dvalue); } else { dvalue = MAX(SCHAR_MIN, dvalue); dvalue = MIN(SCHAR_MAX, dvalue); *((signed char *) ptr) = ROUND(dvalue); } break; case NC_SHORT : if (!is_signed) { dvalue = MAX(0, dvalue); dvalue = MIN(USHRT_MAX, dvalue); *((unsigned short *) ptr) = ROUND(dvalue); } else { dvalue = MAX(SHRT_MIN, dvalue); dvalue = MIN(SHRT_MAX, dvalue); *((signed short *) ptr) = ROUND(dvalue); } break; case NC_INT : if (!is_signed) { dvalue = MAX(0, dvalue); dvalue = MIN(UINT_MAX, dvalue); *((unsigned int *) ptr) = ROUND(dvalue); } else { dvalue = MAX(INT_MIN, dvalue); dvalue = MIN(INT_MAX, dvalue); *((signed int *) ptr) = ROUND(dvalue); } break; case NC_FLOAT : dvalue = MAX(-FLT_MAX,dvalue); *((float *) ptr) = MIN(FLT_MAX,dvalue); break; case NC_DOUBLE : *((double *) ptr) = dvalue; break; } } minc-2.2.00/progs/mincsample/0000755000265600003100000000000012030114723012772 500000000000000minc-2.2.00/progs/mincsample/mt19937ar.h0000644000265600003100000000541512030075003014445 00000000000000/* A C-program for MT19937, with initialization improved 2002/1/26. Coded by Takuji Nishimura and Makoto Matsumoto. Before using, initialize the state by using init_genrand(seed) or init_by_array(init_key, key_length). Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any feedback is very welcome. http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ /* initializes mt[N] with a seed */ void init_genrand(unsigned long s); /* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ /* slight change for C++, 2004/2/26 */ void init_by_array(unsigned long init_key[], int key_length); /* generates a random number on [0,0xffffffff]-interval */ unsigned long genrand_int32(void); /* generates a random number on [0,0x7fffffff]-interval */ long genrand_int31(void); /* generates a random number on [0,1]-real-interval */ double genrand_real1(void); /* generates a random number on [0,1)-real-interval */ double genrand_real2(void); /* generates a random number on (0,1)-real-interval */ double genrand_real3(void); /* generates a random number on [0,1) with 53-bit resolution*/ double genrand_res53(void); minc-2.2.00/progs/mincsample/mincsample.c0000644000265600003100000004506612030075003015216 00000000000000/* mincsample.c * * Generate samplings from MINC files * * Andrew Janke - a.janke@gmail.com * Mark Griffin * * Copyright Andrew Janke and Mark Griffin, McConnell Brain Imaging Centre * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies. The * author and the University make no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. */ #include #include #include #include #include #include #include #include #include #include #include "mt19937ar.h" #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #define WORLD_NDIMS 3 #define DEFAULT_INT -1 /* typedefs */ typedef enum { SAMPLE_ALL, SAMPLE_RND } Sample_enum; typedef enum { OUTPUT_ASCII, OUTPUT_DOUBLE } Output_enum; typedef struct { Sample_enum sample_type; /* input parameters */ int masking; double mask_val; int mask_idx; /* sampling */ int rand_samples; int max_samples; /* output parameters */ int sample_mask; int sample_mask_idx; Output_enum output_type; int output_coords; FILE *outFP; } Loop_Data; /* function prototypes */ void count_points(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info); void get_points(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info); void write_data(FILE * fp, double value, Output_enum ot); void get_minc_attribute(int mincid, char *varname, char *attname, int maxvals, double vals[]); int get_minc_ndims(int mincid); void find_minc_spatial_dims(int mincid, int space_to_dim[], int dim_to_space[]); void get_minc_voxel_to_world(int mincid, double voxel_to_world[WORLD_NDIMS][WORLD_NDIMS + 1]); void normalize_vector(double vector[]); void transform_coord(double out_coord[], double transform[WORLD_NDIMS][WORLD_NDIMS + 1], double in_coord[]); /* global vars for printing coordinates */ int space_to_dim[WORLD_NDIMS] = { -1, -1, -1 }; int dim_to_space[MAX_VAR_DIMS]; int file_ndims = 0; double voxel_to_world[WORLD_NDIMS][WORLD_NDIMS + 1]; /* Argument variables and table */ static int verbose = FALSE; static int quiet = FALSE; static int clobber = FALSE; static int max_buffer = 4 * 1024; static char *mask_fname = NULL; static char *sample_fname = NULL; static char *out_fname = NULL; static int append_output = FALSE; static int rand_seed = DEFAULT_INT; static Loop_Data md = { SAMPLE_ALL, FALSE, 1.0, 0, 0, 0, FALSE, 0, OUTPUT_ASCII, FALSE, NULL }; static ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "General options:"}, {"-verbose", ARGV_CONSTANT, (char *)TRUE, (char *)&verbose, "print out extra information."}, {"-quiet", ARGV_CONSTANT, (char *)TRUE, (char *)&quiet, "be very quiet."}, {"-clobber", ARGV_CONSTANT, (char *)TRUE, (char *)&clobber, "clobber existing files."}, {"-max_buffer", ARGV_INT, (char *)1, (char *)&max_buffer, "maximum size of buffers (in kbytes)"}, {"-mask", ARGV_STRING, (char *)1, (char *)&mask_fname, "select voxels within the specified mask"}, {"-mask_val", ARGV_FLOAT, (char *)1, (char *)&(md.mask_val), "mask value to use"}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nSampling Types:"}, {"-all", ARGV_CONSTANT, (char *)SAMPLE_ALL, (char *)&md.sample_type, "sample all the data (Default)"}, {"-random_seed", ARGV_INT, (char *)1, (char *)&rand_seed, "Random seed to use (use to get reproducible runs) Default: use tv_usec"}, {"-random_samples", ARGV_INT, (char *)1, (char *)&md.rand_samples, "take # random samples from the input data"}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nOutput Options:"}, {"-sample", ARGV_STRING, (char *)1, (char *)&sample_fname, "Output a file of chosen points"}, {"-outfile", ARGV_STRING, (char *)1, (char *)&out_fname, " for output data (Default: stdout)"}, {"-append", ARGV_CONSTANT, (char *)TRUE, (char *)&append_output, "append output data to existing file"}, {"-ascii", ARGV_CONSTANT, (char *)OUTPUT_ASCII, (char *)&md.output_type, "Write out data as ascii strings (default)"}, {"-double", ARGV_CONSTANT, (char *)OUTPUT_DOUBLE, (char *)&md.output_type, "Write out data as double precision floating-point values"}, {"-coords", ARGV_CONSTANT, (char *)TRUE, (char *)&md.output_coords, "Write out world co-ordinates as well as values"}, {NULL, ARGV_HELP, NULL, NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char *argv[]) { char **infiles; char *outfiles[1]; int n_infiles, n_outfiles; char *arg_string; Loop_Options *loop_opts; int mincid; struct timeval timer; int i; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* get arguments */ if(ParseArgv(&argc, argv, argTable, 0) || (argc < 2)){ fprintf(stderr, "\nUsage: %s [options] ... \n", argv[0]); fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } /* check arguments */ if(md.rand_samples != 0){ md.sample_type = SAMPLE_RND; if(md.rand_samples < 0){ fprintf(stderr, "%s: -rand_samples (%d) must be greater than 0\n\n", argv[0], md.rand_samples); exit(EXIT_FAILURE); } } /* check arguments */ if(rand_seed != DEFAULT_INT && rand_seed < 0){ fprintf(stderr, "%s: -rand_seed (%d) must be 0 or greater\n\n", argv[0], rand_seed); exit(EXIT_FAILURE); } /* get infile names */ n_infiles = argc - 1; infiles = (char **)malloc(sizeof(char *) * (n_infiles + 1)); /* + 1 for mask */ for(i = 0; i < n_infiles; i++){ infiles[i] = argv[i + 1]; } if(mask_fname != NULL){ infiles[n_infiles] = mask_fname; md.masking = TRUE; md.mask_idx = n_infiles; n_infiles++; } /* check for the infile(s) */ for(i = 0; i < n_infiles; i++){ if(access(infiles[i], F_OK) != 0){ fprintf(stderr, "%s: Couldn't find input file: %s\n\n", argv[0], infiles[i]); exit(EXIT_FAILURE); } } /* set up and check for voxel_loop outfiles */ if(sample_fname != NULL){ if(access(sample_fname, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists, use -clobber to overwrite\n\n", argv[0], sample_fname); exit(EXIT_FAILURE); } md.sample_mask = TRUE; md.sample_mask_idx = 0; n_outfiles = 1; outfiles[0] = sample_fname; } else { n_outfiles = 0; } /* set up data outfile */ if(out_fname == NULL || strcmp(out_fname, "-") == 0){ md.outFP = stdout; } else { if(!append_output && access(out_fname, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists, use -clobber to overwrite\n\n", argv[0], out_fname); exit(EXIT_FAILURE); } if((md.outFP = fopen(out_fname, (append_output) ? "a" : "w")) == NULL){ fprintf(stderr, "%s: problems opening %s\n", argv[0], out_fname); exit(EXIT_FAILURE); } } /* Get some information from the first file for printing co-ordinates */ mincid = miopen(infiles[0], NC_NOWRITE | 0x8000); file_ndims = get_minc_ndims(mincid); find_minc_spatial_dims(mincid, space_to_dim, dim_to_space); get_minc_voxel_to_world(mincid, voxel_to_world); /* set up voxel loop options */ loop_opts = create_loop_options(); set_loop_verbose(loop_opts, FALSE); set_loop_clobber(loop_opts, clobber); set_loop_buffer_size(loop_opts, (long)1024 * max_buffer); /* set up random sampling if required */ if(md.sample_type == SAMPLE_RND){ void *tmp = NULL; /* for gettimeofday */ /* get max number of samples */ voxel_loop(1, (md.masking) ? &mask_fname : infiles, 0, NULL, NULL, loop_opts, count_points, (void *)&md); if(verbose){ fprintf(stderr, " | Got max # of points: %d\n", md.max_samples); } if(md.rand_samples > md.max_samples){ fprintf(stderr, "%s: -rand_samples (%d) must be less than max samples (%d)\n\n", argv[0], md.rand_samples, md.max_samples); exit(EXIT_FAILURE); } /* initialise random number generator */ if(rand_seed == DEFAULT_INT){ gettimeofday(&timer, tmp); rand_seed = timer.tv_usec; } if(verbose){ fprintf(stderr, " | Using random seed: %d\n", rand_seed); } init_genrand((unsigned long)rand_seed); } /* do the sampling */ voxel_loop(n_infiles, infiles, n_outfiles, outfiles, arg_string, loop_opts, get_points, (void *)&md); /* tidy up */ fclose(md.outFP); free_loop_options(loop_opts); return (EXIT_SUCCESS); } /* get points from file(s), write out to an input FP */ void get_points(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info) { Loop_Data *md = (Loop_Data *) caller_data; int i, idim, ivox; int n_infiles; int do_sample; double mask_value; int dim_index; long index[MAX_VAR_DIMS]; double voxel_coord[WORLD_NDIMS]; double world_coord[WORLD_NDIMS]; /* shut the compiler up */ (void)output_num_buffers; (void)output_vector_length; n_infiles = (md->masking) ? input_num_buffers - 1 : input_num_buffers; /* for each voxel */ for(ivox = 0; ivox < num_voxels * input_vector_length; ivox++){ /* nasty way that works for masking or not */ mask_value = 0; if(!md->masking || (md->masking && fabs(input_data[md->mask_idx][ivox] - md->mask_val) < 0.5)){ /* flag to sample */ do_sample = FALSE; switch (md->sample_type){ case SAMPLE_ALL: do_sample = TRUE; mask_value = 1.0; break; case SAMPLE_RND: /* if this voxel 'qualifies', write out data */ if(genrand_res53() < ((double)md->rand_samples / md->max_samples)){ md->rand_samples--; do_sample = TRUE; mask_value = 1.0; } md->max_samples--; break; default: fprintf(stderr, "ERROR - Sample type is undefined (%d)\n", md->sample_type); exit(EXIT_FAILURE); } /* now write out the data */ if(do_sample){ /* get and convert voxel to world coordinates */ if(md->output_coords){ get_info_voxel_index(loop_info, ivox, file_ndims, index); for(idim = 0; idim < WORLD_NDIMS; idim++){ dim_index = space_to_dim[idim]; if(dim_index >= 0){ voxel_coord[idim] = index[dim_index]; } } transform_coord(world_coord, voxel_to_world, voxel_coord); } switch (md->output_type){ case OUTPUT_ASCII: if(md->output_coords){ fprintf(md->outFP, "%.20g\t%.20g\t%.20g\t", world_coord[0], world_coord[1], world_coord[2]); } for(i = 0; i < n_infiles; i++){ fprintf(md->outFP, "%.20g\t", input_data[i][ivox]); } fprintf(md->outFP, "\n"); break; case OUTPUT_DOUBLE: if(md->output_coords){ fwrite(&(world_coord[0]), sizeof(double), 1, md->outFP); fwrite(&(world_coord[1]), sizeof(double), 1, md->outFP); fwrite(&(world_coord[2]), sizeof(double), 1, md->outFP); } for(i = 0; i < n_infiles; i++){ fwrite(&(input_data[i][ivox]), sizeof(double), 1, md->outFP); } break; default: fprintf(stderr, "ERROR - Output type is undefined (%d)\n", md->output_type); exit(EXIT_FAILURE); } } } /* output sampling mask */ if(md->sample_mask){ output_data[md->sample_mask_idx][ivox] = mask_value; } } } /* count points that are within a mask */ void count_points(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info) { Loop_Data *md = (Loop_Data *) caller_data; int ivox; /* shut the compiler up */ (void)input_num_buffers; (void)output_num_buffers; (void)output_vector_length; (void)output_data; (void)loop_info; for(ivox = 0; ivox < num_voxels * input_vector_length; ivox++){ if(md->masking){ if(fabs(input_data[0][ivox] - md->mask_val) < 0.5){ md->max_samples++; } } else { md->max_samples++; } } } inline void write_data(FILE * fp, double value, Output_enum ot) { switch (ot){ case OUTPUT_ASCII: fprintf(fp, "%.20g\n", value); break; case OUTPUT_DOUBLE: fwrite(&(value), sizeof(double), 1, fp); break; default: fprintf(stderr, "ERROR - Output type is undefined (%d)\n", ot); exit(EXIT_FAILURE); } } void normalize_vector(double vector[]) { int idim; double magnitude; magnitude = 0.0; for(idim = 0; idim < WORLD_NDIMS; idim++){ magnitude += (vector[idim] * vector[idim]); } magnitude = sqrt(magnitude); if(magnitude > 0.0){ for(idim = 0; idim < WORLD_NDIMS; idim++){ vector[idim] /= magnitude; } } } /* Transforms a coordinate through a linear transform -- from mincstats */ void transform_coord(double out_coord[], double transform[WORLD_NDIMS][WORLD_NDIMS + 1], double in_coord[]) { int idim, jdim; double homogeneous_coord[WORLD_NDIMS + 1]; for(idim = 0; idim < WORLD_NDIMS; idim++){ homogeneous_coord[idim] = in_coord[idim]; } homogeneous_coord[WORLD_NDIMS] = 1.0; for(idim = 0; idim < WORLD_NDIMS; idim++){ out_coord[idim] = 0.0; for(jdim = 0; jdim < WORLD_NDIMS + 1; jdim++){ out_coord[idim] += transform[idim][jdim] * homogeneous_coord[jdim]; } } } /* Get the voxel to world transform (for column vectors) -- from mincstats */ void get_minc_voxel_to_world(int mincid, double voxel_to_world[WORLD_NDIMS][WORLD_NDIMS + 1]) { int idim, jdim; double dircos[WORLD_NDIMS]; double step, start; char *dimensions[] = { MIxspace, MIyspace, MIzspace }; /* Zero the matrix */ for(idim = 0; idim < WORLD_NDIMS; idim++){ for(jdim = 0; jdim < WORLD_NDIMS + 1; jdim++) voxel_to_world[idim][jdim] = 0.0; } for(jdim = 0; jdim < WORLD_NDIMS; jdim++){ /* Set default values */ step = 1.0; start = 0.0; for(idim = 0; idim < WORLD_NDIMS; idim++) dircos[idim] = 0.0; dircos[jdim] = 1.0; /* Get the attributes */ get_minc_attribute(mincid, dimensions[jdim], MIstart, 1, &start); get_minc_attribute(mincid, dimensions[jdim], MIstep, 1, &step); get_minc_attribute(mincid, dimensions[jdim], MIdirection_cosines, WORLD_NDIMS, dircos); normalize_vector(dircos); /* Put them in the matrix */ for(idim = 0; idim < WORLD_NDIMS; idim++){ voxel_to_world[idim][jdim] = step * dircos[idim]; voxel_to_world[idim][WORLD_NDIMS] += start * dircos[idim]; } } } /* Get the mapping from spatial dimension - x, y, z - to file dimensions and vice-versa. -- from mincstats */ void find_minc_spatial_dims(int mincid, int space_to_dim[], int dim_to_space[]) { int imgid, dim[MAX_VAR_DIMS]; int idim, ndims, world_index; char dimname[MAX_NC_NAME]; /* Set default values */ for(idim = 0; idim < 3; idim++) space_to_dim[idim] = -1; for(idim = 0; idim < MAX_VAR_DIMS; idim++) dim_to_space[idim] = -1; /* Get the dimension ids for the image variable */ imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Loop over them to find the spatial ones */ for(idim = 0; idim < ndims; idim++){ /* Get the name and check that this is a spatial dimension */ (void)ncdiminq(mincid, dim[idim], dimname, NULL); if((dimname[0] == '\0') || (strcmp(&dimname[1], "space") != 0)){ continue; } /* Look for the spatial dimensions */ switch (dimname[0]){ case 'x': world_index = 0; break; case 'y': world_index = 1; break; case 'z': world_index = 2; break; default: world_index = 0; break; } space_to_dim[world_index] = idim; dim_to_space[idim] = world_index; } } /* Get a double attribute from a minc file -- from mincstats */ void get_minc_attribute(int mincid, char *varname, char *attname, int maxvals, double vals[]) { int varid; int old_ncopts; int att_length; if(!mivar_exists(mincid, varname)) return; varid = ncvarid(mincid, varname); old_ncopts = ncopts; ncopts = 0; (void)miattget(mincid, varid, attname, NC_DOUBLE, maxvals, vals, &att_length); ncopts = old_ncopts; } /* Get the total number of image dimensions in a minc file -- from mincstats */ int get_minc_ndims(int mincid) { int imgid; int ndims; imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, NULL, NULL); return ndims; } minc-2.2.00/progs/mincsample/mt19937ar.c0000644000265600003100000001437412030075003014444 00000000000000/* A C-program for MT19937, with initialization improved 2002/1/26. Coded by Takuji Nishimura and Makoto Matsumoto. Before using, initialize the state by using init_genrand(seed) or init_by_array(init_key, key_length). Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any feedback is very welcome. http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ /* Period parameters */ #define N 624 #define M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ static unsigned long mt[N]; /* the array for the state vector */ static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ /* initializes mt[N] with a seed */ void init_genrand(unsigned long s) { mt[0]= s & 0xffffffffUL; for (mti=1; mti> 30)) + mti); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ mt[mti] &= 0xffffffffUL; /* for >32 bit machines */ } } /* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ /* slight change for C++, 2004/2/26 */ void init_by_array(unsigned long init_key[], int key_length) { int i, j, k; init_genrand(19650218UL); i=1; j=0; k = (N>key_length ? N : key_length); for (; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + init_key[j] + j; /* non linear */ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; j++; if (i>=N) { mt[0] = mt[N-1]; i=1; } if (j>=key_length) j=0; } for (k=N-1; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i; /* non linear */ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; if (i>=N) { mt[0] = mt[N-1]; i=1; } } mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ } /* generates a random number on [0,0xffffffff]-interval */ unsigned long genrand_int32(void) { unsigned long y; static unsigned long mag01[2]={0x0UL, MATRIX_A}; /* mag01[x] = x * MATRIX_A for x=0,1 */ if (mti >= N) { /* generate N words at one time */ int kk; if (mti == N+1) /* if init_genrand() has not been called, */ init_genrand(5489UL); /* a default initial seed is used */ for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; } for (;kk> 1) ^ mag01[y & 0x1UL]; } y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; mti = 0; } y = mt[mti++]; /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } /* generates a random number on [0,0x7fffffff]-interval */ long genrand_int31(void) { return (long)(genrand_int32()>>1); } /* generates a random number on [0,1]-real-interval */ double genrand_real1(void) { return genrand_int32()*(1.0/4294967295.0); /* divided by 2^32-1 */ } /* generates a random number on [0,1)-real-interval */ double genrand_real2(void) { return genrand_int32()*(1.0/4294967296.0); /* divided by 2^32 */ } /* generates a random number on (0,1)-real-interval */ double genrand_real3(void) { return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); /* divided by 2^32 */ } /* generates a random number on [0,1) with 53-bit resolution*/ double genrand_res53(void) { unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; return(a*67108864.0+b)*(1.0/9007199254740992.0); } /* These real versions are due to Isaku Wada, 2002/01/09 added */ // int main(void) // { // int i; // unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4; // init_by_array(init, length); // printf("1000 outputs of genrand_int32()\n"); // for (i=0; i<1000; i++) { // printf("%10lu ", genrand_int32()); // if (i%5==4) printf("\n"); // } // printf("\n1000 outputs of genrand_real2()\n"); // for (i=0; i<1000; i++) { // printf("%10.8f ", genrand_real2()); // if (i%5==4) printf("\n"); // } // return 0; // } minc-2.2.00/progs/mincstats/0000755000265600003100000000000012030114723012647 500000000000000minc-2.2.00/progs/mincstats/mincstats.man10000644000265600003100000002437012027132663015371 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 2001 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/mincstats/mincstats.man1,v 1.5 2004-05-20 21:52:09 bert Exp $ .\" .TH MINCSTATS 1 "$Date: 2004-05-20 21:52:09 $" "" "MINC User's Guide" .SH NAME mincstats - calculate simple statistics across voxels of a minc file .SH SYNOPSIS .B mincstats [] .mnc .SH DESCRIPTION \fIMincstats\fR will calculate simple statistical measures across all voxels of a minc file. Note that these are global statistical measures and not voxel-by-voxel measures (see \fImincaverage\fR for that). By default all statistics are calculated. If any statistics are requested via a command-line option, then only the requested statistics are printed. A very useful feature of this program is the ability to restrict the set of voxels included in the statistic calculation, either by restricting the range of included values, or by using a mask file with a restricted range. Multiple ranges for the input file or mask file can be specified. For each range of included volume values, and for each range of mask values, the relevant statistics are printed out (n*m values, where n is the number of volume ranges and m the number of mask ranges). These calculations are done in a single pass through the data, so specifying multiple ranges is much faster than running the program repeatedly. This is quite helpful when calculating many regional averages with a VOI mask volume. Special mention should be given to histograms and related statistical measures. The default range of the histogram is from the smallest value in the file to the largest. In the not uncommon, but special, case when the number of histogram bins exactly matches the number of possible values in the file (e.g. 256 bins for full-range byte data), the histogram can end up with some odd features when using the default histogram range. This arises from the discretization of the data that are then rebinned into a slightly mismatched histgram. For the example of byte data, the values that should be used are 256 bins and a histogram range that extends half a bin below the smallest value and half a bin above the largest. Use option \fB-discrete_histogram\fR to work this out automatically, or use \fB-integer_histogram\fR to have bins of unit width if the input data are inherently integer (e.g. label data). In general, one should be careful about the rebinning of discretized data to a histogram with a bin size that is close to the level of discretization. .SH OPTIONS Note that options can be specified in abbreviated form (as long as they are unique) and can be given anywhere on the command line. .SH General options .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-verbose\fR Print out extra information (more than the default). .TP \fB\-quiet\fR Print out only the requested numbers .TP \fB\-max_buffer_size_in_kb\fR\ \fIsize\fR Specify the maximum size of the internal buffers (in kbytes). Default is 4 MB. .SH Invalid value options .TP \fB\-ignore_nan\fR Exclude invalid values (outside valid range) from statistic calculations. This is the default. .TP \fB\-include_nan\fR Treat invalid values as zeros and include them in statistic calculations. .TP \fB\-replace_nan\fR\ \fIvalue\fR Replace invalid values with the specified value and include the new value in statistic calculations. .SH Volume range options .TP \fB\-floor\fR\ \fImin1\fR,\fImin2\fR,... Comma-separated list of lower bounds for ranges of data to include in statistic calculation. .TP \fB\-ceil\fR\ \fImax1\fR,\fImax2\fR,... Comma-separated list of upper bounds for ranges of data to include in statistic calculation. .TP \fB\-range\fR\ \fImin1\fR,\fImax1\fR,\fImin2\fR,\fImax2\fR,... Comma-separated list of lower and upper bounds for ranges of data to include in statistic calculation. .TP \fB\-binvalue\fR \fIval1\fR,\fIval2\fR,... Comma-separated list of integer values to include in statistic calculation. A range of +/- 0.5 is defined around each specified value. .TP \fB\-mask\fR\ \fIfilename.mnc\fR Name of file to be used for masking data included in statistic calculation. For this to have any effect, you must specify a mask range with one of the following options. .TP \fB\-mask_floor\fR\ \fImin1\fR,\fImin2\fR,...: Like \fB\-floor\fR, but applied to the mask file. .TP \fB\-mask_ceil\fR\ \fImax1\fR,\fImax2\fR,... Like \fB\-ceil\fR, but applied to the mask file. .TP \fB\-mask_range\fR\ \fImin1\fR,\fImax1\fR,\fImin2\fR,\fImax2\fR,... Like \fB\-range\fR, but applied to the mask file. .TP \fB\-mask_binvalue\fR\ \fIval1\fR,\fIval2\fR,... Like \fB\-binvalue\fR, but applied to the mask file. .SH Histogram options .TP \fB\-histogram\fR\ \fIfilename\fR Specify the name of a file into which the histogram is written. If multiple ranges or mask ranges are specified, then all histograms are written in this file, separated by blank lines. Information describing each histogram is written before it in lines starting with the hash (pound) character. These files can be loaded into gnuplot. .TP \fB\-hist_bins\fR \fInumber-of-bins\fR Specify number of bins in histogram. .TP \fB-bins\fR \fInumber-of-bins\fR Synonym for \fB\-hist_bins\fR. .TP \fB\-hist_floor\fR\ \fImin\fR Specify lower bound for histogram. .TP \fB\-hist_ceil\fR\ \fImax\fR Specify upper bound for histogram. .TP \fB\-hist_range\fR\ \fImin\fR\ \fImax\fR Specify a range for the histogram .TP \fB\-integer_histogram\fR Create bins of unit width, centred around integer values. This is useful for integer data such as labels. The histogram range is rounded to the nearest integer, then the min is lowered and the max is raised by 0.5. The number of bins is taken as the difference of these two values. Note that 0.01 is added to the minimum and subtracted from the maximum prior to the rounding in order to ensure that a correctly specified range (e.g. [0.5,255.5]) is preserved. If you want to have integer bins that are wider than one, you will have to work out the histogram range and number of bins yourself and not use this option. .TP \fB\-discrete_histogram\fR Attempt to match the histogram to the discretization of the input data. This is appropriate for continuous data that are stored in an integer representation and when a bin width close to the discretization is desired. This is similar to \fB\-integer_histogram\fR, except that the the histogram range is first converted to voxel values which are rounded and extended by half a bin on either side. This new voxel range is then converted back to real values. The number of bins is taken as the difference in the voxel value range. Note that this does not account for variations in slice-to-slice scaling, so odd histogram effects may still occur. This option is intended to give behaviour similar to that of \fIvolume_stats\fR. .TP \fB\-int_max_bins\fR \fInumber-of-bins\fR Specify the largest histogram that can be automatically sized with the above options. The limit prevents accidental creation of huge histograms. This option replaced the old \fB-max_bins\fR option in MINC 1.1. .SH Basic statistics .TP \fB\-all\fR Compute all statistical measures. This is the default. .TP \fB\-none\fR Synonym for \fB\-count\fR (for similarity to volume_stats). Note that although this was necessary for \fIvolume_stats\fR, it is not needed here, since specifying any of these options automatically turns off \fB\-all\fR .TP \fB\-count\fR Count the number of voxels that are within the range and mask. .TP \fB\-percent\fR Print the percentage of voxels within the range and mask .TP \fB\-volume\fR Print the volume of the voxels within the range and mask (in mm-cubed). .TP \fB\-min\fR Print the minimum value. .TP \fB\-max\fR Print the maximum value. .TP \fB\-sum\fR Print the sum of all values. .TP \fB\-sum2\fR Print the sum of the squares of all values. .TP \fB\-mean\fR Print the mean. .TP \fB\-variance\fR Print the variance. .TP \fB\-stddev\fR Print the standard deviation. .TP \fB\-CoM\fR Print the centre of mass. Both the voxel coordinate and the world coordinates are printed. The voxel coordinates are printed in file order, whilst the world coordinates are printed in x,y,z order. .TP \fB\-com\fR Synonym for \fB\-CoM\fR. .TP \fB\-world_only\fR Print the centre of mass in world coordinates only. .SH Histogram statistics .P Note that histogram statistics are derived solely from the histogram counts and bin centres, so results such as the median will not be exactly the same as the true value for all included voxels. For example, the error on the median can be as large as a half bin width. Furthermore, if the histogram range is less than that of included voxels, then the result applies only to voxels included in the histogram. .TP \fB\-hist_count\fR Print number of voxels in histogram. This may be different from the number of included and masked voxels if the histogram range is less than the range of the included data. .TP \fB\-hist_percent\fR Print percentage of voxels included in histogram. .TP \fB\-median\fR Print the histogram median. .TP \fB\-majority\fR Print the bin centre (intensity value) for the bin with the most counts. .TP \fB\-biModalT\fR Print the bi-modal threshold calculated using the method described in Otsu N, "A Threshold Selection Method from Grey-level Histograms", IEEE Trans on Systems, Man and Cybernetics. 1979, 9:1; 62-66. .TP \fB\-pctT\fR Print the threshold needed for a particular critical percentage of the histogram. .TP \fB\-entropy\fR Print the Shannon entropy. H(x) = - Sum(P(i) * log2(P(i)) where P(i) is the bin probability .SH Generic options for all commands: .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Andrew Janke .SH COPYRIGHTS .P Program: Copyright \(co 2000 by Andrew Janke .P Man page: Copyright \(co 2001 by Peter Neelin minc-2.2.00/progs/mincstats/mincstats.c0000644000265600003100000017253312027132663014764 00000000000000/* mincstats.c * * Andrew Janke - a.janke@gmail.com * Centre for Magnetic Resonance * University of Queensland, Australia * * $Log: mincstats.c,v $ * Revision 1.24 2007-12-11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 1.23 2007/09/27 01:06:31 rotor * * bugfix to histogram stats with a zero volume, discovered by Simon, fixed by * Claude * * Revision 1.22 2005/07/29 16:46:21 bert * Add warning message for mincstats -mask w/o -mask_range, -mask_binvalue, etc. * * Revision 1.21 2005/07/25 19:56:52 bert * Fix pct_T calculation by taking into account a possibly non-zero histogram floor * * Revision 1.20 2005/05/20 15:39:45 bert * Remove and/or conditionalize test code for memory-mapped files (see HDF5_MMAP_TEST) * * Revision 1.19 2004/12/14 23:39:36 bert * New bimodal threshold algorithms * * Revision 1.18 2004/12/06 15:28:50 rotor * * Hopefully the final bug-fix for the BiModalT calculation * * Revision 1.17 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 1.16 2004/10/18 08:20:35 rotor * * Changes to mincstats * - Fixed bug in calculation of BiModalT * - changed default # of histogram bins to 65536 (from 10000) * * Revision 1.15 2004/04/27 15:29:22 bert * Added milog_init() call during initialization * * Revision 1.14 2003/09/05 18:29:40 bert * Avoid passing NULL to fprintf when no mask file is specified, to avoid seg. faults reported by Richard Boyes. * * Revision 1.13 2003/08/20 05:52:55 rotor * * INDENTATION changes only (merging my and peter neelins code!) * * Revision 1.12 2003/08/20 05:45:10 rotor * * Fixed broken calculation of Median value from histogram. * * Revision 1.11 2002/09/05 00:41:57 rotor * ---------------------------------------------------------------------- * Fixed clash of C/L arguments in mincstats (-max and -max_bins) * -max_bins has now been changed to -int_max_bins * * Committing in . * * Modified Files: * mincstats.c * ---------------------------------------------------------------------- * * Revision 1.10 2002/04/08 21:46:34 jgsled * fixed problem where mincstats segmentation fault when trying to close a NULL file pointer * * Revision 1.9 2002/01/09 13:23:16 neelin * Removed extraneous newline for histogram output with -quiet turned on. * * Revision 1.8 2001/12/11 14:36:00 neelin * Added -discrete_histogram and -integer_histogram, as well as * -world_only options. * * Revision 1.7 2001/12/10 14:11:45 neelin * Obtained speed improvement by only doing CoM summing when needed. * * Revision 1.6 2001/12/06 21:54:25 neelin * Check for -quiet when printing volume and mask ranges. * * Revision 1.5 2001/12/06 21:48:16 neelin * Significant modifications to get mincstats working. Also added support * for multiple ranges in the volume and the mask. Added -binvalue and * -maskbinvalue options. * * Revision 1.4 2001/12/05 17:20:13 neelin * Lots of fixes to get it working. Also fixed up centre of mass calculation * and display. * * Revision 1.2 2001/11/28 21:59:39 neelin * Significant modifications. Removed dependencies on volume_io. * Added support for centre-of-mass calculation. * Compiles but crashes under linux. * * Revision 1.1 2001/11/28 21:54:08 neelin * *** empty log message *** * * * Thu Feb 1 17:16:21 EST 2001 - completed filename checking and other * mundane stuff - first release 1.0 * Wed Jan 31 14:33:30 EST 2001 - finished -entropy, -median and -histogram * Fri Jan 19 15:25:44 EST 2001 - created first version from minccount as a * mirror of Alex Zijdenbos + John Sleds * volume_stats proggy with less memory * overhead * Original version - 1999 sometime.. * * A few notes on the stats in here. * Median - This is a "histogram median" based upon calculating * the volume of histogram above and below the median * Thus the more bins the more accurate the approximation * Majority - This is the centre of the largest bin in the histogram * BiModalT - The Bi-Modal Threshold calculated using the method described in * Otsu N, "A Threshold Selection Method from Grey-level Histograms" * IEEE Trans on Systems, Man and Cybernetics. 1979, 9:1;62-66. * Entropy - This is what is called "Shannon Entropy" of a histogram * H(x) = - Sum(P(i) * log2(P(i)) * Where P(i) is the bin probability * PctT - The threshold needed for a particular "Critical percentage" of * of a histogram. */ #include "config.h" #include #include #if HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ #include #if HAVE_FLOAT_H #include #endif /* HAVE_FLOAT_H */ #include #include #include #include #include #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define SQR(x) ((x)*(x)) #define WORLD_NDIMS 3 #define DEFAULT_BOOLEAN (-1) #define BINS_DEFAULT 2000 /* Double_Array structure */ typedef struct { int numvalues; double *values; } Double_Array; /* Stats structure */ typedef struct { double vol_range[2]; double mask_range[2]; float *histogram; double hvoxels; double vvoxels; double volume; double vol_per; double hist_per; double min; double max; double sum; double sum2; double mean; double variance; double stddev; double voxel_com_sum[WORLD_NDIMS]; double voxel_com[WORLD_NDIMS]; double world_com[WORLD_NDIMS]; double median; double majority; double biModalT; double pct_T; double entropy; } Stats_Info; /* Function prototypes */ void do_math(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info); void do_stats(double value, long index[], Stats_Info * stats); void print_result(char *title, double result); long get_minc_nvoxels(int mincid); double get_minc_voxel_volume(int mincid); void get_minc_attribute(int mincid, char *varname, char *attname, int maxvals, double vals[]); int get_minc_ndims(int mincid); void find_minc_spatial_dims(int mincid, int space_to_dim[], int dim_to_space[]); void get_minc_voxel_to_world(int mincid, double voxel_to_world[WORLD_NDIMS][WORLD_NDIMS + 1]); void normalize_vector(double vector[]); void transform_coord(double out_coord[], double transform[WORLD_NDIMS][WORLD_NDIMS + 1], double in_coord[]); void print_com(Stats_Info * stats); int get_double_list(char *dst, char *key, char *nextarg); void verify_range_options(Double_Array * min, Double_Array * max, Double_Array * range, Double_Array * binvalue); void init_stats(Stats_Info * stats, int hist_bins); void free_stats(Stats_Info * stats); /* Argument variables */ int max_buffer_size_in_kb = 4 * 1024; static int verbose = FALSE; static int quiet = FALSE; static int clobber = FALSE; static int ignoreNaN = DEFAULT_BOOLEAN; static double fillvalue = -DBL_MAX; static int All = FALSE; static int Vol_Count = FALSE; static int Vol_Per = FALSE; static int Vol = FALSE; static int Min = FALSE; static int Max = FALSE; static int Sum = FALSE; static int Sum2 = FALSE; static int Mean = FALSE; static int Variance = FALSE; static int Stddev = FALSE; static int CoM = FALSE; static int World_Only = FALSE; static int Hist = FALSE; static int Hist_Count = FALSE; static int Hist_Per = FALSE; static int Median = FALSE; static int Majority = FALSE; static int BiModalT = FALSE; static int PctT = FALSE; static double pctT = 0.0; static int Entropy = FALSE; /* Alternative methods of calculating the bimodal threshold */ #define BMT_OTSU 1 /* Otsu algorithm (default) */ #define BMT_KITTLER 2 /* Kittler-Illingworth algorithm */ #define BMT_KAPUR 3 /* Kapur et al. algorithm */ #define BMT_SIMPLE 4 /* Simple mean-of-means, citation unknown */ static int BMTMethod = BMT_OTSU; static Double_Array vol_min = { 0, NULL }; static Double_Array vol_max = { 0, NULL }; static Double_Array vol_range = { 0, NULL }; static Double_Array vol_binvalue = { 0, NULL }; static int num_ranges; char *mask_file; static Double_Array mask_min = { 0, NULL }; static Double_Array mask_max = { 0, NULL }; static Double_Array mask_range = { 0, NULL }; static Double_Array mask_binvalue = { 0, NULL }; static int num_masks; char *hist_file; static int hist_bins = BINS_DEFAULT; static double hist_sep; static double hist_range[2] = { -DBL_MAX, DBL_MAX }; static int discrete_histogram = FALSE; static int integer_histogram = FALSE; static int max_bins = 65536; /* Global Variables to store info for stats */ Stats_Info **stats_info = NULL; double voxel_volume; double nvoxels; int space_to_dim[WORLD_NDIMS] = { -1, -1, -1 }; int dim_to_space[MAX_VAR_DIMS]; int file_ndims = 0; /* Argument table */ static ArgvInfo argTable[] = { {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "General options:"}, {"-verbose", ARGV_CONSTANT, (char *)TRUE, (char *)&verbose, "Print out extra information."}, {"-quiet", ARGV_CONSTANT, (char *)TRUE, (char *)&quiet, "Print requested values only."}, {"-clobber", ARGV_CONSTANT, (char *)TRUE, (char *)&clobber, "Clobber existing files."}, {"-noclobber", ARGV_CONSTANT, (char *)FALSE, (char *)&clobber, "Do not clobber existing files (default)."}, {"-max_buffer_size_in_kb", ARGV_INT, (char *)1, (char *)&max_buffer_size_in_kb, "maximum size of internal buffers."}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nVoxel selection options:"}, {"-floor", ARGV_FUNC, (char *)get_double_list, (char *)&vol_min, "Ignore voxels below this value (list)"}, {"-ceil", ARGV_FUNC, (char *)get_double_list, (char *)&vol_max, "Ignore voxels above this value (list)"}, {"-range", ARGV_FUNC, (char *)get_double_list, (char *)&vol_range, "Ignore voxels outside this range (list)"}, {"-binvalue", ARGV_FUNC, (char *)get_double_list, (char *)&vol_binvalue, "Include voxels within 0.5 of this value (list)"}, {"-mask", ARGV_STRING, (char *)1, (char *)&mask_file, " Use mask file for calculations."}, {"-mask_floor", ARGV_FUNC, (char *)get_double_list, (char *)&mask_min, "Exclude mask voxels below this value (list)"}, {"-mask_ceil", ARGV_FUNC, (char *)get_double_list, (char *)&mask_max, "Exclude mask voxels above this value (list)"}, {"-mask_range", ARGV_FUNC, (char *)get_double_list, (char *)&mask_range, "Exclude voxels outside this range (list)"}, {"-mask_binvalue", ARGV_FUNC, (char *)get_double_list, (char *)&mask_binvalue, "Include mask voxels within 0.5 of this value (list)"}, {"-ignore_nan", ARGV_CONSTANT, (char *)TRUE, (char *)&ignoreNaN, "Exclude NaN values from stats (default)."}, {"-include_nan", ARGV_CONSTANT, (char *)FALSE, (char *)&ignoreNaN, "Treat NaN values as zero."}, {"-replace_nan", ARGV_FLOAT, (char *)1, (char *)&fillvalue, "Replace NaNs with specified value."}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nHistogram Options:"}, {"-histogram", ARGV_STRING, (char *)1, (char *)&hist_file, " Compute histogram."}, {"-hist_bins", ARGV_INT, (char *)1, (char *)&hist_bins, " of bins in each histogram."}, {"-bins", ARGV_INT, (char *)1, (char *)&hist_bins, "synonym for -hist_bins."}, {"-hist_floor", ARGV_FLOAT, (char *)1, (char *)&hist_range[0], "Histogram floor value. (incl)"}, {"-hist_ceil", ARGV_FLOAT, (char *)1, (char *)&hist_range[1], "Histogram ceiling value. (incl)"}, {"-hist_range", ARGV_FLOAT, (char *)2, (char *)&hist_range, "Histogram floor and ceiling. (incl)"}, {"-discrete_histogram", ARGV_CONSTANT, (char *)TRUE, (char *)&discrete_histogram, "Match histogram bins to data discretization"}, {"-integer_histogram", ARGV_CONSTANT, (char *)TRUE, (char *)&integer_histogram, "Set histogram bins to unit width"}, {"-int_max_bins", ARGV_INT, (char *)1, (char *)&max_bins, "Set maximum number of histogram bins for integer histograms"}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nStatistics (Printed in this order)"}, {"-all", ARGV_CONSTANT, (char *)TRUE, (char *)&All, "all statistics (default)."}, {"-none", ARGV_CONSTANT, (char *)TRUE, (char *)&Vol_Count, "synonym for -count. (from volume_stats)"}, {"-count", ARGV_CONSTANT, (char *)TRUE, (char *)&Vol_Count, "# of voxels."}, {"-percent", ARGV_CONSTANT, (char *)TRUE, (char *)&Vol_Per, "percentage of valid voxels."}, {"-volume", ARGV_CONSTANT, (char *)TRUE, (char *)&Vol, "volume (in mm3)."}, {"-min", ARGV_CONSTANT, (char *)TRUE, (char *)&Min, "minimum value."}, {"-max", ARGV_CONSTANT, (char *)TRUE, (char *)&Max, "maximum value."}, {"-sum", ARGV_CONSTANT, (char *)TRUE, (char *)&Sum, "sum."}, {"-sum2", ARGV_CONSTANT, (char *)TRUE, (char *)&Sum2, "sum of squares."}, {"-mean", ARGV_CONSTANT, (char *)TRUE, (char *)&Mean, "mean value."}, {"-variance", ARGV_CONSTANT, (char *)TRUE, (char *)&Variance, "variance."}, {"-stddev", ARGV_CONSTANT, (char *)TRUE, (char *)&Stddev, "standard deviation."}, {"-CoM", ARGV_CONSTANT, (char *)TRUE, (char *)&CoM, "centre of mass of the volume."}, {"-com", ARGV_CONSTANT, (char *)TRUE, (char *)&CoM, "centre of mass of the volume."}, {"-world_only", ARGV_CONSTANT, (char *)TRUE, (char *)&World_Only, "print CoM in world coords only."}, {NULL, ARGV_HELP, (char *)NULL, (char *)NULL, "\nHistogram Dependant Statistics:"}, {"-hist_count", ARGV_CONSTANT, (char *)TRUE, (char *)&Hist_Count, "# of voxels portrayed in Histogram."}, {"-hist_percent", ARGV_CONSTANT, (char *)TRUE, (char *)&Hist_Per, "percentage of histogram voxels."}, {"-median", ARGV_CONSTANT, (char *)TRUE, (char *)&Median, "median value."}, {"-majority", ARGV_CONSTANT, (char *)TRUE, (char *)&Majority, "most frequently occurring histogram bin."}, {"-biModalT", ARGV_CONSTANT, (char *)TRUE, (char *)&BiModalT, "value separating a volume into 2 classes."}, {"-pctT", ARGV_FLOAT, (char *)1, (char *)&pctT, "<%> threshold at the supplied % of data."}, {"-entropy", ARGV_CONSTANT, (char *)TRUE, (char *)&Entropy, "entropy of the volume."}, {"-otsu", ARGV_CONSTANT, (char *)BMT_OTSU, (char *)&BMTMethod, "Use Otsu '97 algorithm for bimodal threshold (default)"}, {"-kittler", ARGV_CONSTANT, (char *)BMT_KITTLER, (char *)&BMTMethod, "Use Kittler&Illingworth '86 algorithm for bimodal threshold"}, {"-kapur", ARGV_CONSTANT, (char *)BMT_KAPUR, (char *)&BMTMethod, "Use Kapur et al. '85 algorithm for bimodal threshold"}, {"-simple", ARGV_CONSTANT, (char *)BMT_SIMPLE, (char *)&BMTMethod, "Use simple mean-of-means algorithm for bimodal threshold"}, {NULL, ARGV_HELP, NULL, NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Alternative thresholding algorithm. This is more computationally * expensive than some of the alternatives, and doesn't seem to do a * great job. On the other hand it doesn't seem to fail like the * current algorithm. */ static double simple_threshold(float *histogram, float *hist_centre, int hist_bins) { double sum1, sum2; double mean1, mean2; double testthreshold; double newthreshold; int newthreshold_bin; double count1, count2; int c; /* Start with a guess of the bimodal threshold. */ newthreshold = ceil(hist_centre[hist_bins / 2]); newthreshold_bin = hist_bins / 2; for (;;) { sum1 = 0.0; sum2 = 0.0; count1 = 0.0; count2 = 0.0; /* Calculate the mean of the bins on each side of the * proposed threshold. */ for (c = 0; c < newthreshold_bin; c++) { sum1 += (hist_centre[c] * histogram[c]); count1 += histogram[c]; } for (c = newthreshold_bin; c < hist_bins; c++) { sum2 += (hist_centre[c] * histogram[c]); count2 += histogram[c]; } /* Avoid divide by zero */ if (count1 == 0.0 || count2 == 0.0) { continue; } mean1 = sum1 / count1; mean2 = sum2 / count2; /* The new threshold is the mean of the means. */ testthreshold = ceil((mean1 + mean2) / 2); /* If the threshold is unchanged, that is our final * guess. */ if (newthreshold == testthreshold) { break; /* Return result */ } else { /* Adopt the new guess and try again until we converge. */ newthreshold = testthreshold; for (c = 0; c < hist_bins; c++) { if (newthreshold == ceil(hist_centre[c])) { newthreshold_bin = c; break; } } } } return (newthreshold); } /** This copyright applies to the following functions: * * otsu_threshold() * kittler_threshold() * kapur_threshold() * * These functions were extracted from the "xite" package from this * source. The functions were extensively modified, however, by me * to generalize the functions for our purposes. Any bugs are * therefore my responsibility (bert 2004-12-14). * * Copyright 1990, Blab, UiO * Image processing lab, Department of Informatics * University of Oslo * E-mail: blab@ifi.uio.no *________________________________________________________________ * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that this copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation and that the name of B-lab, * Department of Informatics or University of Oslo not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. * * B-LAB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL B-LAB BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Otsu, N. "A threshold selection method from gray-level histograms", * IEEE Transactions on Systems, Man, and Cybernetics, vol T-SMC 9, * No 1, pp 62-66, 1979. */ static double otsu_threshold(float histo[], float hist_centre[], int hist_bins) { double threshold; double criterion; double expr_1; /* Temporary for common subexpression */ int i, k; /* Generic loop counters */ double *p = malloc(hist_bins * sizeof(double)); double omega_k; double sigma_b_k; double sigma_T; double mu_T; double mu_k; double sum; int k_low, k_high; double mu_0, mu_1, mu; /* If memory allocation fails, abandon ship!!! */ if (p == NULL) { return (0.0); } sum = 0.0; for (i = 0; i < hist_bins; i++) sum += (double)histo[i]; for (i = 0; i < hist_bins; i++) p[i] = (double)histo[i] / sum; mu_T = 0.0; for (i = 0; i < hist_bins; i++) mu_T += hist_centre[i] * p[i]; sigma_T = 0.0; for (i = 0; i < hist_bins; i++) sigma_T += (hist_centre[i] - mu_T) * (hist_centre[i] - mu_T) * p[i]; /* Ignore outlying zero bins */ for (k_low = 0; (p[k_low] == 0) && (k_low < hist_bins - 1); k_low++) ; for (k_high = hist_bins - 1; (p[k_high] == 0) && (k_high > 0); k_high--) ; criterion = 0.0; threshold = hist_centre[hist_bins / 2]; mu_0 = hist_centre[hist_bins / 2 - 1]; mu_1 = hist_centre[hist_bins / 2 + 1]; omega_k = 0.0; mu_k = 0.0; for (k = k_low; k <= k_high ; k++) { omega_k += p[k]; mu_k += hist_centre[k] * p[k]; expr_1 = (mu_T * omega_k - mu_k); sigma_b_k = expr_1 * expr_1 / (omega_k * (1 - omega_k)); if (criterion < sigma_b_k / sigma_T) { criterion = sigma_b_k / sigma_T; threshold = hist_centre[k]; mu_0 = mu_k / omega_k; mu_1 = (mu_T - mu_k) / (1.0 - omega_k); } } mu = mu_T; free(p); return threshold; } /* Kittler, J. & Illingworth J., "Minimum error thresholding", Pattern * Recognition, vol 19, pp 41-47, 1986. */ static double kittler_threshold (float hist_bin[], float hist_centre[], int hist_size) { double threshold; double criterion; int g; double n; int T_low, T_high; double P_1_T, P_2_T, P_tot; double mu_1_T, mu_2_T; double sum_gh_1, sum_gh_2, sum_gh_tot; double sum_ggh_1, sum_ggh_2, sum_ggh_tot; double sigma_1_T, sigma_2_T; double J_T; double mu, mu_1, mu_2; criterion = 1e10; threshold = hist_centre[hist_size / 2 + 1]; J_T = criterion; T_low = 0; while ((hist_bin[T_low] == 0) && (T_low < hist_size - 1)) { T_low++; } T_high = hist_size - 1; while ((hist_bin[T_high] == 0) && (T_high > 0)) { T_high--; } n = 0; for (g = T_low; g <= T_high; g++) { n += hist_bin[g]; } P_1_T = hist_bin[T_low]; P_tot = 0; for (g = T_low; g <= T_high; g++) { P_tot += hist_bin[g]; } sum_gh_1 = hist_centre[T_low] * hist_bin[T_low]; sum_gh_tot = 0.0; for (g = T_low; g <= T_high; g++) { sum_gh_tot += hist_centre[g] * hist_bin[g]; } mu = sum_gh_tot * 1.0 / n; sum_ggh_1 = hist_centre[T_low] * hist_centre[T_low] * hist_bin[T_low]; sum_ggh_tot = 0.0; for (g = T_low; g <= T_high; g++) { sum_ggh_tot += hist_centre[g] * hist_centre[g] * hist_bin[g]; } for (g = T_low + 1; g < T_high - 1; g++) { P_1_T += hist_bin[g]; P_2_T = P_tot - P_1_T; sum_gh_1 += hist_centre[g] * hist_bin[g]; sum_gh_2 = sum_gh_tot - sum_gh_1; mu_1_T = sum_gh_1 / P_1_T; mu_2_T = sum_gh_2 / P_2_T; sum_ggh_1 += hist_centre[g] * hist_centre[g] * hist_bin[g]; sum_ggh_2 = sum_ggh_tot - sum_ggh_1; sigma_1_T = sum_ggh_1 / P_1_T - mu_1_T * mu_1_T; sigma_2_T = sum_ggh_2 / P_2_T - mu_2_T * mu_2_T; /* Equation (15) in the article */ if ((sigma_1_T != 0.0) && (P_1_T != 0) && (sigma_2_T != 0.0) && (P_2_T != 0)) { J_T = 1 + 2 * (P_1_T * log(sigma_1_T) + P_2_T * log(sigma_2_T)) - 2 * (P_1_T * log(P_1_T) + P_2_T * log(P_2_T) ); } if (criterion > J_T) { criterion = J_T; threshold = hist_centre[g]; mu_1 = mu_1_T; mu_2 = mu_2_T; } } return threshold; } /* Kapur, Sahoo & Wong "A new method for Gray-level picture thresholding using the entropy of the histogram", Computer Vision, Graphics, and Image Processing, vol 29, pp 273-285, 1985. */ #define BIN_TINY 1e-6 static double kapur_threshold(float histo[], float hist_centre[], int hist_bins) { double threshold; double Phi, Phi_max; int i, k; double *p = malloc(sizeof(double) * hist_bins); double *P = malloc(sizeof(double) * hist_bins); double *H = malloc(sizeof(double) * hist_bins); double sum; sum = 0; for (i = 0; i < hist_bins; i++) { sum += histo[i]; } for (i = 0; i < hist_bins; i++) { p[i] = histo[i] * 1.0 / sum; } P[0] = p[0]; for (i = 1; i < hist_bins; i++) { P[i] = P[i - 1] + p[i]; } if (histo[0] == 0) { H[0] = 0; } else { H[0] = -p[0] * log(p[0]); } for (i = 1; i < hist_bins; i++) { if (histo[i] == 0) { H[i] = H[i - 1]; } else { H[i] = H[i - 1] - p[i] * log(p[i]); } } Phi_max = -10e10; threshold = hist_centre[hist_bins / 2]; for (k = 0; k <= hist_bins - 1; k++) { if ((P[k] > BIN_TINY) && (1 - P[k] > BIN_TINY)) { Phi = log(P[k] * (1 - P[k])) + H[k] / P[k] + (H[hist_bins - 1] - H[k]) / (1.0 - P[k]); if (Phi_max < Phi) { Phi_max = Phi; threshold = hist_centre[k]; } } } free(p); free(P); free(H); return threshold; } int main(int argc, char *argv[]) { char **infiles; int nfiles; Loop_Options *loop_options; int mincid, imgid; int idim; int irange, imask; double real_range[2], valid_range[2]; nc_type datatype; int is_signed; double voxel_to_world[WORLD_NDIMS][WORLD_NDIMS + 1]; Stats_Info *stats; FILE *FP; double scale, voxmin, voxmax; milog_init(argv[0]); /* Get arguments */ if(ParseArgv(&argc, argv, argTable, 0) || (argc != 2)) { (void)fprintf(stderr, "\nUsage: %s [options] \n", argv[0]); (void)fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } nfiles = argc - 1; infiles = &argv[1]; infiles[1] = &mask_file[0]; if(infiles[1] != NULL) { nfiles++; } /* Check for NaN options */ if(ignoreNaN == DEFAULT_BOOLEAN) { ignoreNaN = (fillvalue != -DBL_MAX); } if(ignoreNaN && fillvalue == -DBL_MAX) { fillvalue = 0.0; } /* Check range options: not over-specified and put values in vol_min/vol_max */ verify_range_options(&vol_min, &vol_max, &vol_range, &vol_binvalue); num_ranges = vol_min.numvalues; /* Check mask range options: not over-specified and put values in mask_min/mask_max */ verify_range_options(&mask_min, &mask_max, &mask_range, &mask_binvalue); num_masks = mask_min.numvalues; if (mask_file != NULL && num_masks == 1 && *mask_min.values == -DBL_MAX && *mask_max.values == DBL_MAX) { fprintf(stderr, "%s: Warning: Mask specified without a range. Mask will be ignored.\n", argv[0]); } /* Check histogramming options */ if((discrete_histogram && integer_histogram) || ((discrete_histogram || integer_histogram) && (hist_bins != BINS_DEFAULT))) { (void)fprintf(stderr, "Please specify only -discrete_histogram, -integer_histogram or -bins\n"); exit(EXIT_FAILURE); } /* init PctT boolean before checking */ if(pctT > 0.0) { PctT = TRUE; pctT /= 100; } /* if nothing selected, do everything */ if(!Vol_Count && !Vol_Per && !Vol && !Min && !Max && !Sum && !Sum2 && !Mean && !Variance && !Stddev && !Hist_Count && !Hist_Per && !Median && !Majority && !BiModalT && !PctT && !Entropy && !CoM) { All = TRUE; Hist = TRUE; } if((hist_file != NULL) || Hist_Count || Hist_Per || Median || Majority || BiModalT || PctT || Entropy) { Hist = TRUE; } if(hist_bins <= 0) Hist = FALSE; /* do checking on arguments */ if(hist_bins < 1) { (void)fprintf(stderr, "%s: Must have one or more bins for a histogram\n", argv[0]); exit(EXIT_FAILURE); } if(access(infiles[0], 0) != 0) { (void)fprintf(stderr, "%s: Couldn't find %s\n", argv[0], infiles[0]); exit(EXIT_FAILURE); } if(infiles[1] != NULL && access(infiles[1], 0) != 0) { (void)fprintf(stderr, "%s: Couldn't find mask file: %s\n", argv[0], infiles[1]); exit(EXIT_FAILURE); } if(hist_file != NULL && !clobber && access(hist_file, 0) != -1) { (void)fprintf(stderr, "%s: Histogram %s exists! (use -clobber to overwrite)\n", argv[0], hist_file); exit(EXIT_FAILURE); } /* Open the file to get some information */ mincid = miopen(infiles[0], NC_NOWRITE); imgid = ncvarid(mincid, MIimage); nvoxels = get_minc_nvoxels(mincid); voxel_volume = get_minc_voxel_volume(mincid); (void)miget_datatype(mincid, imgid, &datatype, &is_signed); (void)miget_image_range(mincid, real_range); (void)miget_valid_range(mincid, imgid, valid_range); file_ndims = get_minc_ndims(mincid); find_minc_spatial_dims(mincid, space_to_dim, dim_to_space); get_minc_voxel_to_world(mincid, voxel_to_world); /* Check whether discrete histogramming makes sense - i.e. not floating-point. Silently ignore the option if it does not make sense. */ if(datatype == NC_FLOAT || datatype == NC_DOUBLE) { discrete_histogram = FALSE; } /* set up the histogram definition, if needed */ if(Hist) { if(hist_range[0] == -DBL_MAX) { if(vol_min.numvalues == 1 && vol_min.values[0] != -DBL_MAX) hist_range[0] = vol_min.values[0]; else hist_range[0] = real_range[0]; } if(hist_range[1] == DBL_MAX) { if(vol_max.numvalues == 1 && vol_max.values[0] != DBL_MAX) hist_range[1] = vol_max.values[0]; else hist_range[1] = real_range[1]; } if(discrete_histogram) { /* Convert histogram range to voxel values and round, then convert back. */ scale = (real_range[1] == real_range[0]) ? 0.0 : (valid_range[1] - valid_range[0]) / (real_range[1] - real_range[0]); voxmin = rint((hist_range[0] - real_range[0]) * scale + valid_range[0]); voxmax = rint((hist_range[1] - real_range[0]) * scale + valid_range[0]); if(real_range[1] != real_range[0]) scale = 1.0 / scale; hist_range[0] = (voxmin - valid_range[0]) * scale + real_range[0]; hist_range[1] = (voxmax - valid_range[0]) * scale + real_range[0]; /* Figure out number of bins and bin width */ hist_bins = voxmax - voxmin; if(hist_bins <= 0) { hist_sep = 1.0; hist_bins = 0; } else { hist_sep = (hist_range[1] - hist_range[0]) / hist_bins; } /* Shift the ends of the histogram down and up by half a bin and add one to the number of bins */ hist_range[0] -= hist_sep / 2.0; hist_range[1] += hist_sep / 2.0; hist_bins++; } else if(integer_histogram) { /* Add and subtract the 0.01 in order to ensure that a range that is already properly specified stays that way. Ie. [-0.5,255.5] does not change, regardless of the type of rounding done to .5 */ hist_range[0] = (int)rint(hist_range[0] + 0.01); hist_range[1] = (int)rint(hist_range[1] - 0.01); hist_bins = hist_range[1] - hist_range[0] + 1.0; hist_range[0] -= 0.5; hist_range[1] += 0.5; hist_sep = 1.0; } else { hist_sep = (hist_range[1] - hist_range[0]) / hist_bins; } if((discrete_histogram || integer_histogram) && (hist_bins > max_bins)) { (void)fprintf(stderr, "Too many bins in histogram (%d) - please increase -int_max_bins if appropriate\n", hist_bins); exit(EXIT_FAILURE); } } /* Initialize the stats structure */ stats_info = malloc(num_ranges * sizeof(*stats_info)); for(irange = 0; irange < num_ranges; irange++) { stats_info[irange] = malloc(num_masks * sizeof(**stats_info)); for(imask = 0; imask < num_masks; imask++) { stats = &stats_info[irange][imask]; init_stats(stats, hist_bins); stats->vol_range[0] = vol_min.values[irange]; stats->vol_range[1] = vol_max.values[irange]; stats->mask_range[0] = mask_min.values[imask]; stats->mask_range[1] = mask_max.values[imask]; } } /* Do math */ loop_options = create_loop_options(); set_loop_first_input_mincid(loop_options, mincid); set_loop_verbose(loop_options, verbose); set_loop_buffer_size(loop_options, (long)1024 * max_buffer_size_in_kb); voxel_loop(nfiles, infiles, 0, NULL, NULL, loop_options, do_math, NULL); free_loop_options(loop_options); /* Open the histogram file if it will be needed */ if(hist_file == NULL) { FP = NULL; } else { FP = fopen(hist_file, "w"); if(FP == NULL) { perror("Error opening histogram file"); exit(EXIT_FAILURE); } } /* Loop over ranges and masks, calculating results */ for(irange = 0; irange < num_ranges; irange++) { for(imask = 0; imask < num_masks; imask++) { stats = &stats_info[irange][imask]; stats->vol_per = stats->vvoxels / nvoxels * 100; stats->hist_per = stats->hvoxels / nvoxels * 100; stats->mean = (stats->vvoxels > 0) ? stats->sum / stats->vvoxels : 0.0; stats->variance = (stats->vvoxels > 1) ? (stats->sum2 - SQR(stats->sum) / stats->vvoxels) / (stats->vvoxels - 1) : 0.0; stats->stddev = sqrt(stats->variance); stats->volume = voxel_volume * stats->vvoxels; for(idim = 0; idim < WORLD_NDIMS; idim++) { if(stats->sum != 0.0) stats->voxel_com[idim] = stats->voxel_com_sum[idim] / stats->sum; else stats->voxel_com[idim] = 0.0; } transform_coord(stats->world_com, voxel_to_world, stats->voxel_com); /* Do the histogram calculations */ if(Hist) { int c; float *hist_centre; float *pdf; /* probability density Function */ float *cdf; /* cumulative density Function */ int majority_bin = 0; int median_bin = 0; int pctt_bin = 0; int bimodalt_bin = 0; /* BiModal Threshold variables */ double zero_moment = 0.0; double first_moment = 0.0; double var = 0.0; double max_var = 0.0; /* Allocate space for histograms */ hist_centre = calloc(hist_bins, sizeof(float)); pdf = calloc(hist_bins, sizeof(float)); cdf = calloc(hist_bins, sizeof(float)); if(hist_centre == NULL || pdf == NULL || cdf == NULL) { (void)fprintf(stderr, "Memory allocation error\n"); exit(EXIT_FAILURE); } for(c = 0; c < hist_bins; c++) { hist_centre[c] = (c * hist_sep) + hist_range[0] + (hist_sep / 2); /* Probability and Cumulative density functions */ pdf[c] = (stats->hvoxels > 0) ? stats->histogram[c] / stats->hvoxels : 0.0; cdf[c] = (c == 0) ? pdf[c] : cdf[c - 1] + pdf[c]; /* Majority */ if(stats->histogram[c] > stats->histogram[majority_bin]) { majority_bin = c; } /* Entropy */ if(stats->histogram[c] > 0.0) { stats->entropy -= pdf[c] * (log(pdf[c]) / log(2.0)); } /* Histogram Median */ if(cdf[c] < 0.5) { median_bin = c; } /* BiModal Threshold */ zero_moment += pdf[c]; first_moment += hist_centre[c] * pdf[c]; if(c > 0 && zero_moment > 0.0 && zero_moment < 1.0) { var = SQR((stats->mean * zero_moment) - first_moment) / (zero_moment * (1 - zero_moment)); if(var > max_var) { bimodalt_bin = c; max_var = var; } } /* pct Threshold */ if(cdf[c] < pctT) { pctt_bin = c; } } /* median */ if(median_bin == 0) { stats->median = 0.5 * pdf[median_bin] * hist_sep; } else { stats->median = ((double)median_bin + (0.5 - cdf[median_bin]) * pdf[median_bin + 1]) * hist_sep; } stats->median += hist_centre[0]; stats->majority = hist_centre[majority_bin]; stats->biModalT = hist_centre[bimodalt_bin]; /* pct Threshold */ if(pctt_bin == 0) { stats->pct_T = pctT * pdf[pctt_bin] * hist_sep; } else { stats->pct_T = ((double)pctt_bin + (pctT - cdf[pctt_bin]) * pdf[pctt_bin + 1]) * hist_sep; } stats->pct_T += hist_centre[0]; /* Add histogram minimum */ switch (BMTMethod) { case BMT_KITTLER: stats->biModalT = kittler_threshold(stats->histogram, hist_centre, hist_bins); break; case BMT_KAPUR: stats->biModalT = kapur_threshold(stats->histogram, hist_centre, hist_bins); break; case BMT_SIMPLE: stats->biModalT = simple_threshold(stats->histogram, hist_centre, hist_bins); break; default: stats->biModalT = otsu_threshold(stats->histogram, hist_centre, hist_bins); break; } /* output the histogram */ if(hist_file != NULL) { (void)fprintf(FP, "# histogram for: %s\n", infiles[0]); (void)fprintf(FP, "# mask file: %s\n", (infiles[1] != NULL) ? infiles[1] : "(null)"); if(stats->vol_range[0] != -DBL_MAX || stats->vol_range[1] != DBL_MAX) { (void)fprintf(FP, "# volume range: %g %g\n", stats->vol_range[0], stats->vol_range[1]); } if(stats->mask_range[0] != -DBL_MAX || stats->mask_range[1] != DBL_MAX) { (void)fprintf(FP, "# mask range: %g %g\n", stats->mask_range[0], stats->mask_range[1]); } (void)fprintf(FP, "# domain: %g %g\n", hist_range[0], hist_range[1]); (void)fprintf(FP, "# entropy: %g\n", stats->entropy);; (void)fprintf(FP, "# bin centres counts\n"); for(c = 0; c < hist_bins; c++) (void)fprintf(FP, " %-20.10g %12g\n", hist_centre[c], stats->histogram[c]); (void)fprintf(FP, "\n"); } /* Free the space */ free(hist_centre); free(pdf); free(cdf); } /* end histogram calculations */ /* Print range of data allowed */ if(verbose || (num_ranges > 1 && !quiet)) { (void)fprintf(stdout, "Included Range: %g %g\n", stats->vol_range[0], stats->vol_range[1]); } if(verbose || (num_masks > 1 && !quiet)) { (void)fprintf(stdout, "Mask Range: %g %g\n", stats->mask_range[0], stats->mask_range[1]); } /* Print warnings about ranges */ if(!quiet && real_range[0] != stats->min && stats->vol_range[0] == -DBL_MAX && stats->mask_range[0] == -DBL_MAX) { (void)fprintf(stderr, "*** %s - reported min (%g) doesn't equal header (%g)\n", argv[0], stats->min, real_range[0]); } if(!quiet && real_range[1] != stats->max && stats->vol_range[1] == DBL_MAX && stats->mask_range[1] == DBL_MAX) { (void)fprintf(stderr, "*** %s - reported max (%g) doesn't equal header (%g)\n", argv[0], stats->max, real_range[1]); } /* Output stats */ if(Hist) { if(verbose) { (void)fprintf(stdout, "Histogram Range: %g\t%g\n", hist_range[0], hist_range[1]); (void)fprintf(stdout, "Histogram bins: %i of Width (separation): %f\n", hist_bins, hist_sep); } } if(All && !quiet) { (void)fprintf(stdout, "File: %s\n", infiles[0]); } if(All && !quiet) { (void)fprintf(stdout, "Mask file: %s\n", (infiles[1] != NULL) ? infiles[1] : "(null)"); } if(All && !quiet) { print_result("Total voxels: ", nvoxels); } if(All || Vol_Count) { print_result("# voxels: ", stats->vvoxels); } if(All || Vol_Per) { print_result("% of total: ", stats->vol_per); } if(All || Vol) { print_result("Volume (mm3): ", stats->volume); } if(All || Min) { print_result("Min: ", stats->min); } if(All || Max) { print_result("Max: ", stats->max); } if(All || Sum) { print_result("Sum: ", stats->sum); } if(All || Sum2) { print_result("Sum^2: ", stats->sum2); } if(All || Mean) { print_result("Mean: ", stats->mean); } if(All || Variance) { print_result("Variance: ", stats->variance); } if(All || Stddev) { print_result("Stddev: ", stats->stddev); } if(All || CoM) { print_com(stats); } if(Hist) { if(All && !quiet) { (void)fprintf(stdout, "\nHistogram: %s\n", hist_file); } if(All && !quiet) { print_result("Total voxels: ", nvoxels); } if(All || Hist_Count) { print_result("# voxels: ", stats->hvoxels); } if(All || Hist_Per) { print_result("% of total: ", stats->hist_per); } if(All || Median) { print_result("Median: ", stats->median); } if(All || Majority) { print_result("Majority: ", stats->majority); } if(All || BiModalT) { print_result("BiModalT: ", stats->biModalT); } if(All || PctT) { char str[100]; (void)sprintf(str, "PctT [%3d%%]: ", (int)(pctT * 100)); print_result(str, stats->pct_T); } if(All || Entropy) { print_result("Entropy : ", stats->entropy); } if(!quiet) { (void)fprintf(stdout, "\n"); } } } /* End of loop over masks */ } /* End of loop over ranges */ /* Close the histogram file */ if(FP != NULL) { (void)fclose(FP); } /* Free things up */ for(irange = 0; irange < num_ranges; irange++) { for(imask = 0; imask < num_masks; imask++) { free_stats(&stats_info[irange][imask]); } free(stats_info[irange]); } free(stats_info); return EXIT_SUCCESS; } void do_math(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info * loop_info) /* ARGSUSED */ { long ivox; long index[MAX_VAR_DIMS]; int imask, irange; double mask_min, mask_max; Stats_Info *stats; /* Loop through the voxels - a bit of optimization in case we have a brain-dead compiler */ if(mask_file != NULL) { for(irange = 0; irange < num_ranges; irange++) { for(imask = 0; imask < num_masks; imask++) { stats = &stats_info[irange][imask]; mask_min = stats->mask_range[0]; mask_max = stats->mask_range[1]; if(CoM || All) { for(ivox = 0; ivox < num_voxels * input_vector_length; ivox++) { if((input_data[1][ivox] >= mask_min) && (input_data[1][ivox] <= mask_max)) { get_info_voxel_index(loop_info, ivox, file_ndims, index); do_stats(input_data[0][ivox], index, stats); } } } else { for(ivox = 0; ivox < num_voxels * input_vector_length; ivox++) { if((input_data[1][ivox] >= mask_min) && (input_data[1][ivox] <= mask_max)) { do_stats(input_data[0][ivox], NULL, stats); } } } } } } else { for(irange = 0; irange < num_ranges; irange++) { stats = &stats_info[irange][0]; if(CoM || All) { for(ivox = 0; ivox < num_voxels * input_vector_length; ivox++) { get_info_voxel_index(loop_info, ivox, file_ndims, index); do_stats(input_data[0][ivox], index, stats); } } else { for(ivox = 0; ivox < num_voxels * input_vector_length; ivox++) { do_stats(input_data[0][ivox], NULL, stats); } } } } return; } void do_stats(double value, long index[], Stats_Info * stats) { int idim; int hist_index, dim_index; /* Check for NaNs */ if(value == -DBL_MAX) { if(ignoreNaN) value = fillvalue; else return; } /* Collect stats if we are within range */ if((value >= stats->vol_range[0]) && (value <= stats->vol_range[1])) { stats->vvoxels++; stats->sum += value; stats->sum2 += SQR(value); if(value < stats->min) { stats->min = value; } if(value > stats->max) { stats->max = value; } /* Get voxel index */ if(CoM || All) { for(idim = 0; idim < WORLD_NDIMS; idim++) { dim_index = space_to_dim[idim]; if(dim_index >= 0) { stats->voxel_com_sum[idim] += value * index[dim_index]; } } } if(Hist && (value >= hist_range[0]) && (value <= hist_range[1]) && (hist_sep > 0.0) ) { /*lower limit <= value < upper limit */ hist_index = (int)floor((value - hist_range[0]) / hist_sep); if(hist_index >= hist_bins) { hist_index = hist_bins - 1; } stats->histogram[hist_index]++; stats->hvoxels++; } } } void print_result(char *title, double result) { if(!quiet) { (void)fprintf(stdout, "%s", title); } (void)fprintf(stdout, "%.10g\n", result); } /* Get the number of voxels in the file - this is the total number, not just spatial dimensions */ long get_minc_nvoxels(int mincid) { int imgid, dim[MAX_VAR_DIMS]; int idim, ndims; long nvoxels, length; /* Get the dimension ids for the image variable */ imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Loop over them to get the total number of voxels */ nvoxels = 1; for(idim = 0; idim < ndims; idim++) { (void)ncdiminq(mincid, dim[idim], NULL, &length); nvoxels *= length; } return nvoxels; } /* Get the volume of a spatial voxel */ double get_minc_voxel_volume(int mincid) { int imgid, dim[MAX_VAR_DIMS]; int idim, ndims; double volume, step; char dimname[MAX_NC_NAME]; /* Get the dimension ids for the image variable */ imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Loop over them to get the total spatial volume */ volume = 1.0; for(idim = 0; idim < ndims; idim++) { /* Get the name and check that this is a spatial dimension */ (void)ncdiminq(mincid, dim[idim], dimname, NULL); if((dimname[0] == '\0') || (strcmp(&dimname[1], "space") != 0) || !(dimname[0] == 'x' || dimname[0] == 'y' || dimname[0] == 'z')) { continue; } /* Get the step attribute of the coordinate variable */ step = 1.0; get_minc_attribute(mincid, dimname, MIstep, 1, &step); /* Make sure that it is positive and calculate the volume */ if(step < 0.0) step = -step; volume *= step; } return volume; } /* Get a double attribute from a minc file */ void get_minc_attribute(int mincid, char *varname, char *attname, int maxvals, double vals[]) { int varid; int old_ncopts; int att_length; if(!mivar_exists(mincid, varname)) return; varid = ncvarid(mincid, varname); old_ncopts = ncopts; ncopts = 0; (void)miattget(mincid, varid, attname, NC_DOUBLE, maxvals, vals, &att_length); ncopts = old_ncopts; } /* Get the total number of image dimensions in a minc file */ int get_minc_ndims(int mincid) { int imgid; int ndims; imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, NULL, NULL); return ndims; } /* Get the mapping from spatial dimension - x, y, z - to file dimensions and vice-versa. */ void find_minc_spatial_dims(int mincid, int space_to_dim[], int dim_to_space[]) { int imgid, dim[MAX_VAR_DIMS]; int idim, ndims, world_index; char dimname[MAX_NC_NAME]; /* Set default values */ for(idim = 0; idim < 3; idim++) space_to_dim[idim] = -1; for(idim = 0; idim < MAX_VAR_DIMS; idim++) dim_to_space[idim] = -1; /* Get the dimension ids for the image variable */ imgid = ncvarid(mincid, MIimage); (void)ncvarinq(mincid, imgid, NULL, NULL, &ndims, dim, NULL); /* Loop over them to find the spatial ones */ for(idim = 0; idim < ndims; idim++) { /* Get the name and check that this is a spatial dimension */ (void)ncdiminq(mincid, dim[idim], dimname, NULL); if((dimname[0] == '\0') || (strcmp(&dimname[1], "space") != 0)) { continue; } /* Look for the spatial dimensions */ switch (dimname[0]) { case 'x': world_index = 0; break; case 'y': world_index = 1; break; case 'z': world_index = 2; break; default: world_index = 0; break; } space_to_dim[world_index] = idim; dim_to_space[idim] = world_index; } } /* Get the voxel to world transform (for column vectors) */ void get_minc_voxel_to_world(int mincid, double voxel_to_world[WORLD_NDIMS][WORLD_NDIMS + 1]) { int idim, jdim; double dircos[WORLD_NDIMS]; double step, start; char *dimensions[] = { MIxspace, MIyspace, MIzspace }; /* Zero the matrix */ for(idim = 0; idim < WORLD_NDIMS; idim++) { for(jdim = 0; jdim < WORLD_NDIMS + 1; jdim++) voxel_to_world[idim][jdim] = 0.0; } for(jdim = 0; jdim < WORLD_NDIMS; jdim++) { /* Set default values */ step = 1.0; start = 0.0; for(idim = 0; idim < WORLD_NDIMS; idim++) dircos[idim] = 0.0; dircos[jdim] = 1.0; /* Get the attributes */ get_minc_attribute(mincid, dimensions[jdim], MIstart, 1, &start); get_minc_attribute(mincid, dimensions[jdim], MIstep, 1, &step); get_minc_attribute(mincid, dimensions[jdim], MIdirection_cosines, WORLD_NDIMS, dircos); normalize_vector(dircos); /* Put them in the matrix */ for(idim = 0; idim < WORLD_NDIMS; idim++) { voxel_to_world[idim][jdim] = step * dircos[idim]; voxel_to_world[idim][WORLD_NDIMS] += start * dircos[idim]; } } } void normalize_vector(double vector[]) { int idim; double magnitude; magnitude = 0.0; for(idim = 0; idim < WORLD_NDIMS; idim++) { magnitude += (vector[idim] * vector[idim]); } magnitude = sqrt(magnitude); if(magnitude > 0.0) { for(idim = 0; idim < WORLD_NDIMS; idim++) { vector[idim] /= magnitude; } } } /* Prints out centre of mass with correct file order */ void print_com(Stats_Info * stats) { char *spatial_codes[WORLD_NDIMS] = { "x", "y", "z" }; /* In x,y,z order */ int idim; int first; /* Print out voxel coord info */ if(!World_Only) { if(!quiet) { (void)fprintf(stdout, "CoM_voxel("); first = TRUE; for(idim = 0; idim < MAX_VAR_DIMS; idim++) { if(dim_to_space[idim] >= 0) { if(first) first = FALSE; else (void)fprintf(stdout, ","); (void)fprintf(stdout, "%s", spatial_codes[dim_to_space[idim]]); } } (void)fprintf(stdout, "): "); } first = TRUE; for(idim = 0; idim < MAX_VAR_DIMS; idim++) { if(dim_to_space[idim] >= 0) { if(first) first = FALSE; else (void)fprintf(stdout, " "); (void)fprintf(stdout, "%.10g", stats->voxel_com[dim_to_space[idim]]); } } (void)fprintf(stdout, "\n"); } /* Print out world coord info */ if(!quiet) { (void)fprintf(stdout, "CoM_real(x,y,z): "); } (void)fprintf(stdout, "%.10g %.10g %.10g\n", stats->world_com[0], stats->world_com[1], stats->world_com[2]); } /* Transforms a coordinate through a linear transform */ void transform_coord(double out_coord[], double transform[WORLD_NDIMS][WORLD_NDIMS + 1], double in_coord[]) { int idim, jdim; double homogeneous_coord[WORLD_NDIMS + 1]; for(idim = 0; idim < WORLD_NDIMS; idim++) { homogeneous_coord[idim] = in_coord[idim]; } homogeneous_coord[WORLD_NDIMS] = 1.0; for(idim = 0; idim < WORLD_NDIMS; idim++) { out_coord[idim] = 0.0; for(jdim = 0; jdim < WORLD_NDIMS + 1; jdim++) { out_coord[idim] += transform[idim][jdim] * homogeneous_coord[jdim]; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_double_list @INPUT : dst - client data passed by ParseArgv key - matching key in argv nextarg - argument following key in argv @OUTPUT : (none) @RETURNS : TRUE since nextarg is used. @DESCRIPTION: Gets a list (array) of double values. @METHOD : @GLOBALS : @CALLS : @CREATED : March 8, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ int get_double_list(char *dst, char *key, char *nextarg) { #define VECTOR_SEPARATOR ',' int num_elements; int num_alloc; double *double_list; double dvalue; char *cur, *end, *prev; Double_Array *double_array; /* Check for a following argument */ if(nextarg == NULL) { (void)fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get pointers to array variables */ double_array = (Double_Array *) dst; /* Set up pointers to end of string and first non-space character */ end = nextarg + strlen(nextarg); cur = nextarg; while(isspace(*cur)) cur++; num_elements = 0; num_alloc = 0; double_list = NULL; /* Loop through string looking for doubles */ while(cur != end) { /* Get double */ prev = cur; dvalue = strtod(prev, &cur); if(cur == prev) { (void)fprintf(stderr, "expected vector of doubles for \"%s\", but got \"%s\"\n", key, nextarg); exit(EXIT_FAILURE); } /* Add the value to the list */ num_elements++; if(num_elements > num_alloc) { num_alloc += 20; if(double_list == NULL) { double_list = malloc(num_alloc * sizeof(*double_list)); } else { double_list = realloc(double_list, num_alloc * sizeof(*double_list)); } } double_list[num_elements - 1] = dvalue; /* Skip any spaces */ while(isspace(*cur)) cur++; /* Skip an optional comma */ if(*cur == VECTOR_SEPARATOR) cur++; } /* Update the global variables */ double_array->numvalues = num_elements; if(double_array->values != NULL) { free(double_array->values); } double_array->values = double_list; return TRUE; } /* Check range options and set appropriate values. At least one value will be set up for min and max. */ void verify_range_options(Double_Array * min, Double_Array * max, Double_Array * range, Double_Array * binvalue) { int overspecified = FALSE; int min_defaults, max_defaults; int num_values; int ivalue; /* Check the min and max */ if(min->numvalues != 0 && max->numvalues != 0 && min->numvalues != max->numvalues) { (void)fprintf(stderr, "Number of floor ceil values differs\n"); exit(EXIT_FAILURE); } num_values = min->numvalues; if(num_values == 0) num_values = max->numvalues; /* Check for range */ if(range->numvalues > 0) { if(num_values == 0) num_values = range->numvalues / 2; else overspecified = TRUE; } /* Check for binvalue */ if(binvalue->numvalues > 0) { if(num_values == 0) num_values = binvalue->numvalues; else overspecified = TRUE; } /* Print an error if too many options have been given */ if(overspecified) { (void)fprintf(stderr, "Set only one of floor/ceil, range or binvalue\n"); exit(EXIT_FAILURE); } /* Double-check that we got the sizes right */ if((min->numvalues > 0 && min->numvalues != num_values) || (max->numvalues > 0 && max->numvalues != num_values)) { (void)fprintf(stderr, "Problem with range specification\n"); exit(EXIT_FAILURE); } /* Check if we are setting default values. Make sure that at least one value is set */ if(num_values <= 0) { num_values = 1; min_defaults = max_defaults = TRUE; } else { min_defaults = (min->numvalues == 0 && max->numvalues > 0); max_defaults = (max->numvalues == 0 && min->numvalues > 0); } /* Allocate the space */ if(min->numvalues <= 0) { min->numvalues = num_values; min->values = malloc(num_values * sizeof(double)); } if(max->numvalues <= 0) { max->numvalues = num_values; max->values = malloc(num_values * sizeof(double)); } if(min->values == NULL || max->values == NULL) { (void)fprintf(stderr, "Memory allocation error\n"); exit(EXIT_FAILURE); } /* Set defaults, if needed */ if(min_defaults) { for(ivalue = 0; ivalue < num_values; ivalue++) min->values[ivalue] = -DBL_MAX; } if(max_defaults) { for(ivalue = 0; ivalue < num_values; ivalue++) max->values[ivalue] = DBL_MAX; } /* Set min and max from range, if needed */ if(range->numvalues > 0) { /* Check for odd number of values - they should be in pairs */ if((vol_range.numvalues % 2) != 0) { (void)fprintf(stderr, "Specify range values in pairs (even number)\n"); exit(EXIT_FAILURE); } /* Loop over values */ for(ivalue = 0; ivalue * 2 + 1 < range->numvalues; ivalue++) { min->values[ivalue] = range->values[ivalue * 2]; max->values[ivalue] = range->values[ivalue * 2 + 1]; } } /* Set min and max from binvalue, if needed */ if(binvalue->numvalues > 0) { for(ivalue = 0; ivalue < binvalue->numvalues; ivalue++) { min->values[ivalue] = binvalue->values[ivalue] - 0.5; max->values[ivalue] = binvalue->values[ivalue] + 0.5; } } } /* Initialiaze a Stats_Info structure */ void init_stats(Stats_Info * stats, int hist_bins) { stats->vol_range[0] = -DBL_MAX; stats->vol_range[1] = DBL_MAX; stats->mask_range[0] = -DBL_MAX; stats->mask_range[1] = DBL_MAX; if(Hist && hist_bins > 0) { stats->histogram = calloc(hist_bins, sizeof(float)); if(stats->histogram == NULL) { (void)fprintf(stderr, "Memory allocation error\n"); exit(EXIT_FAILURE); } } else { stats->histogram = NULL; } stats->hvoxels = 0.0; /* number of voxels in histogram */ stats->vvoxels = 0.0; /* number of valid voxels */ stats->volume = 0.0; stats->vol_per = 0.0; stats->hist_per = 0.0; stats->min = DBL_MAX; stats->max = -DBL_MAX; stats->sum = 0.0; stats->sum2 = 0.0; stats->mean = 0.0; stats->variance = 0.0; stats->stddev = 0.0; stats->voxel_com_sum[0] = 0.0; stats->voxel_com_sum[1] = 0.0; stats->voxel_com_sum[2] = 0.0; stats->voxel_com[0] = 0.0; stats->voxel_com[1] = 0.0; stats->voxel_com[2] = 0.0; stats->world_com[0] = 0.0; stats->world_com[1] = 0.0; stats->world_com[2] = 0.0; stats->median = 0.0; stats->majority = 0.0; stats->biModalT = 0.0; stats->pct_T = 0.0; stats->entropy = 0.0; } /* Free things from a Stats_Info structure */ void free_stats(Stats_Info * stats) { if(stats->histogram != NULL) free(stats->histogram); } minc-2.2.00/progs/minctoraw/0000755000265600003100000000000012030114723012645 500000000000000minc-2.2.00/progs/minctoraw/minctoraw.man10000644000265600003100000000242412027132663015361 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MINCTORAW 1 "$Date: 2004-05-20 21:52:09 $" "" "MINC User's Guide" .SH NAME minctoraw \- copy data from a MINC file. .SH SYNOPSIS .B minctoraw .BI [options] .BI mincfile .SH DESCRIPTION \fIminctoraw\fR dumps a chunk of MINC file data to standard output in the format of your choice. .P This program is largely superceded by \fImincextract\fR. .SH OPTIONS .TP \fB\-byte\fR Write out data as 8-bit integers .TP \fB\-short\fR Write out data as 16-bit integers .TP \fB\-int\fR Write out data as 32-bit integers .TP \fB\-long\fR Superseded by \fB\-int\fR .TP \fB\-float\fR Write out data as single precision floating-point values .TP \fB\-double\fR Write out data as double precision floating-point values .TP \fB\-signed\fR Write out signed data (applies only to integer types) .TP \fB\-unsigned\fR Write out unsigned data (applies only to integer types) .TP \fB\-range\fR \fIlow\ high\fR Specify the range of output values .TP \fB\-normalize\fR Normalize integer pixel values to file max and min (Default) .TP \fB\-nonormalize\fR Turn off pixel normalization .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH "SEE ALSO" .LP .BR mincextract (1) minc-2.2.00/progs/minctoraw/minctoraw.c0000644000265600003100000002243712027132663014755 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minctoraw @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to dump minc file data @METHOD : @GLOBALS : @CALLS : @CREATED : February 11, 1993 (Peter Neelin) @MODIFIED : * $Log: minctoraw.c,v $ * Revision 6.12 2008-01-17 02:33:06 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.11 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.10 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.9 2006/05/19 00:35:58 bert * Add config.h to several files that might need it * * Revision 6.8 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.7 2003/10/28 20:32:09 bert * Get rid of a few compiler warnings * * Revision 6.6 2001/08/16 16:41:36 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.5 2001/08/16 16:18:47 neelin * Fixed typo for compile * * Revision 6.4 2001/08/16 16:17:22 neelin * Added hint about normalization in error message of previous change. * * Revision 6.3 2001/08/16 16:10:50 neelin * Force user to specify either -normalize or -nonormalize. * * Revision 6.2 2001/04/17 18:40:25 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.1 1999/10/19 14:45:30 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:26 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:27 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:01 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:01 neelin * Release of minc version 0.3 * * Revision 2.2 1995/01/23 09:05:31 neelin * changed ncclose to miclose * * Revision 2.1 95/01/23 09:03:19 neelin * Changed ncopen to miopen. * * Revision 2.0 94/09/28 10:33:06 neelin * Release of minc version 0.2 * * Revision 1.8 94/09/28 10:33:03 neelin * Pre-release * * Revision 1.7 93/08/11 15:23:15 neelin * Added RCS logging in source. * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define BOOLEAN_DEFAULT -1 /* Variables used for argument parsing */ static int output_datatype = INT_MAX; static int output_signed = INT_MAX; static double valid_range[2] = {DBL_MAX, DBL_MAX}; static int normalize_output = BOOLEAN_DEFAULT; /* Argument table */ static ArgvInfo argTable[] = { {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &output_datatype, "Write out data as bytes"}, {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &output_datatype, "Write out data as short integers"}, {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &output_datatype, "Write out data as 32-bit integers"}, {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &output_datatype, "Superseded by -int"}, {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &output_datatype, "Write out data as single precision floating-point values"}, {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &output_datatype, "Write out data as double precision floating-point values"}, {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &output_signed, "Write out signed data"}, {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &output_signed, "Write out unsigned data"}, {"-range", ARGV_FLOAT, (char *) 2, (char *) valid_range, "Specify the range of output values"}, {"-normalize", ARGV_CONSTANT, (char *) TRUE, (char *) &normalize_output, "Normalize integer pixel values to file max and min"}, {"-nonormalize", ARGV_CONSTANT, (char *) FALSE, (char *) &normalize_output, "Turn off pixel normalization"}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *filename; int mincid, imgid, icvid, ndims, dims[MAX_VAR_DIMS]; nc_type datatype; int is_signed; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS], end[MAX_VAR_DIMS]; long size; int idim; void *data; double temp; /* Check arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc != 2)) { (void) fprintf(stderr, "\nUsage: %s [] \n", argv[0]); (void) fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } filename = argv[1]; /* Check that a normalization option was specified */ if (normalize_output == BOOLEAN_DEFAULT) { (void) fprintf(stderr, "Please specify either -normalize or -nonormalize\n"); (void) fprintf(stderr, "Usually -normalize is most appropriate\n"); exit(EXIT_FAILURE); } /* Open the file */ mincid = miopen(filename, NC_NOWRITE); /* Inquire about the image variable */ imgid = ncvarid(mincid, MIimage); (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dims, NULL); (void)miget_datatype(mincid, imgid, &datatype, &is_signed); /* Check if arguments set */ /* Get output data type */ if (output_datatype == INT_MAX) output_datatype = datatype; /* Get output sign */ if (output_signed == INT_MAX) { if (output_datatype == datatype) output_signed = is_signed; else output_signed = (output_datatype != NC_BYTE); } /* Get output range */ if (valid_range[0] == DBL_MAX) { if ((output_datatype == datatype) && (output_signed == is_signed)) { (void) miget_valid_range(mincid, imgid, valid_range); } else { (void) miget_default_range(output_datatype, output_signed, valid_range); } } if (valid_range[0] > valid_range[1]) { temp = valid_range[0]; valid_range[0] = valid_range[1]; valid_range[1] = temp; } /* Set up image conversion */ icvid = miicv_create(); (void) miicv_setint(icvid, MI_ICV_TYPE, output_datatype); (void) miicv_setstr(icvid, MI_ICV_SIGN, (output_signed ? MI_SIGNED : MI_UNSIGNED)); (void) miicv_setdbl(icvid, MI_ICV_VALID_MIN, valid_range[0]); (void) miicv_setdbl(icvid, MI_ICV_VALID_MAX, valid_range[1]); if ((output_datatype == NC_FLOAT) || (output_datatype == NC_DOUBLE)) { (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); } else if (normalize_output) { (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); } (void) miicv_attach(icvid, mincid, imgid); /* Set input file start, count and end vectors for reading a slice at a time */ for (idim=0; idim < ndims; idim++) { (void) ncdiminq(mincid, dims[idim], NULL, &end[idim]); } (void) miset_coords(ndims, (long) 0, start); (void) miset_coords(ndims, (long) 1, count); size = nctypelen(output_datatype); for (idim=ndims-2; idim < ndims; idim++) { count[idim] = end[idim]; size *= count[idim]; } /* Allocate space */ data = malloc(size); /* Loop over input slices */ while (start[0] < end[0]) { /* Read in the slice */ (void) miicv_get(icvid, start, count, data); /* Write out the slice */ if (fwrite(data, sizeof(char), (size_t) size, stdout) != size) { (void) fprintf(stderr, "Error writing data.\n"); exit(EXIT_FAILURE); } /* Increment start counter */ idim = ndims-1; start[idim] += count[idim]; while ( (idim>0) && (start[idim] >= end[idim])) { start[idim] = 0; idim--; start[idim] += count[idim]; } } /* End loop over slices */ /* Clean up */ (void) miclose(mincid); (void) miicv_free(icvid); free(data); exit(EXIT_SUCCESS); } minc-2.2.00/progs/mincview/0000755000265600003100000000000012030114723012463 500000000000000minc-2.2.00/progs/mincview/mincview0000755000265600003100000000633112027132663014166 00000000000000#! /bin/bash # # Script for viewing a minc file. # uses display from ImageMagick to display the images. PGM_CODE="P5" PPM_CODE="P6" # Check arguments if [ $# -lt "1" ] || \ [ $# -gt "2" ] || \ [ "$1" = "-help" ] || \ [ "$1" = "-h" ] then cat < [] Images are displayed with the patients left on the left side of the screen. END exit -1 fi infile="$1" # Create temporary directory tmpdir="/tmp/mincview-$$" # cleanup nicely trap "rm -rf $tmpdir" 0 1 2 3 13 15 mkdir -p $tmpdir # Get dimension names dims=( $(mincinfo -vardims image $infile ) ) echo " + Dimensions: ${dims[*]}" # Check for vector dimension pnm_code=$PGM_CODE if [ "${dims[${#dims[*]} - 1]}" = "vector_dimension" ] then ndims=$(( ${#dims[*]} - 1 )) nvec=$(mincinfo $infile -dimlength $dims[$#dims]) start_suffix=",0" if [ $nvec != 3 ] then count_suffix=",1" else count_suffix=",3" pnm_code=$PPM_CODE fi else ndims="${#dims[*]}" start_suffix="" count_suffix="" fi echo " + ndims: $ndims" if [ $ndims -gt 3 ] then nprefix=$(( $ndims - 3 )) start_prefix=$(awk 'BEGIN{for (i=0;i<$nprefix;i++) print "0,"}' < /dev/null) count_prefix=$(awk 'BEGIN{for (i=0;i<$nprefix;i++) print "1,"}' < /dev/null) elif [ $ndims -lt "2" ] then echo "No image found in file $infile" exit -1 else start_prefix="" count_prefix="" fi # Get number of slices and image dimensions ind1=$(( $ndims - 3 )) ind2=$(( $ndims - 2 )) ind3=$(( $ndims - 1 )) if [ $ind1 -gt "-1" ] then nslices=$(mincinfo $infile -dimlength ${dims[$ind1]}) else nslices=1 fi # figure out which slices to get allslices=$(seq 0 $(($nslices - 1))) slices_to_get=${2:-"$allslices"} if [ "$slices_to_get" = "$2" ] then if [ "$slices_to_get" -ge "$nslices" ] || [ "$slices_to_get" -lt "0" ] then echo "" echo "$0: Slice number $slices_to_get out of range (0-$nslices)" echo "" exit -1 fi fi # Check for inverting images to get standard orientation imgsize=( $(mincinfo -dimlength ${dims[$ind2]} -dimlength ${dims[$ind3]} $infile) ) echo " + imgsize: ${imgsize[0]}x${imgsize[1]}" echo " + nslices $nslices" # Loop through slices, if needed echo -n "Loading slices" for slice in $slices_to_get do echo -n "." if [ $ndims -gt 2 ] then start="${start_prefix}$slice,0,0${start_suffix}" count="${count_prefix}1,${imgsize[0]},${imgsize[1]}${count_suffix}" else start="0,0$start_suffix" count="${imgsize[0]},${imgsize[1]}$count_suffix" fi output_file=$(printf "$tmpdir/slice-%04d.pgm" $slice) echo "$pnm_code" > $output_file echo "${imgsize[1]} ${imgsize[0]}" >> $output_file echo "255" >> $output_file mincextract -byte \ -start $start \ -count $count \ -positive_direction \ $infile >> $output_file slice=$(($slice + 1)) done echo "Done" cat < to advance to the next image The image number is displayed in the title of the window -------------------------------------------------------------- END # Display the images display -monitor -geometry 512x512 -flip $tmpdir/slice-*.pgm minc-2.2.00/progs/mincview/invert_raw_image.man10000644000265600003100000000116612027132663016520 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH INVERT_RAW_IMAGE 1 .SH NAME invert_raw_image \- invert 2D image along either or both axes .SH SYNOPSIS .B invert_raw_image .BI xsize .BI xsize .BI [bytesperpixel] .SH DESCRIPTION .B invert_raw_image reads an image from standard input and copies it to standard output, inverting along either or both dimensions according to the arguments. The parameter .BI xsize specifies the number of pixels in the x-direction. Use a negative number to flip the image along this axis. Ditto for .BI ysize. The number of bytes per pixel defaults to 1 if not specified. minc-2.2.00/progs/mincview/mincview.man10000644000265600003100000000133412027132663015014 00000000000000.TH MINCVIEW 1 "$Date: 2011-02-15 02:48:11 $" "" "MINC User's Guide" .SH NAME mincview \- view a MINC file .SH SYNOPSIS \fBmincview\ \fImincfile [slicenumber]\fR .SH DESCRIPTION \fImincview\fR converts the image into PNM format and loads one or all of the slices into \fIdisplay\fR from Imagemagick. This is a very primitive tool, mostly useful for debugging but at least being a very low level tool should always work. Controls for display are simple, use the key for the next image or the right mouse button on the image for a more detailed menu interface The programs Display or register are more suited for typical use. .SH "SEE ALSO" .LP .BR display (1), .BR ImageMagick (1), .BR Display (1), .BR register (1). minc-2.2.00/progs/mincview/invert_raw_image.c0000644000265600003100000000647412027132663016115 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : invert_raw_image.c @INPUT : argc - number of arguments argv - arguments 1 - image size in x (-ve means invert) 2 - image size in y (-ve means invert) 3 - number of bytes per pixel (optional - default = 1) @OUTPUT : (none) @DESCRIPTION: Reads an image from standard input and copies it to standard output, inverting along either or both dimensions according to the arguments @METHOD : @GLOBALS : @CALLS : @CREATED : December 3,1991 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ #include #include #include #define ABS( x ) ( ((x) > (0)) ? (x) : (-(x)) ) #define MAX( x, y ) ( ((x) >= (y)) ? (x) : (y) ) #define SIGN( x ) ( ((x) > (0)) ? (1) : (-1) ) #define ERROR_STATUS -1 #define NORMAL_STATUS 0 /* Argument table */ ArgvInfo argTable[] = { {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char *argv[]) { int i,j,k,oi,image_size,offset,bytes_per_pixel,row_size,nread,nwritten; int xsize,ysize,xstart,ystart,xstop,ystop,xstep,ystep; char *pname; char *buffer,*outbuf; /* Check arguments */ pname=argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || (argc < 3) || (argc > 4)) { (void) fprintf(stderr,"Usage : %s xsize ysize \n",pname); exit(ERROR_STATUS); } xsize = atol(argv[1]); ysize = atol(argv[2]); if (argc == 4) { bytes_per_pixel = atol(argv[3]); if (bytes_per_pixel <=0) { (void) fprintf(stderr,"%s : Negative bytes per pixel\n",pname); } } else { bytes_per_pixel = 1; } if ((xsize == 0) || (ysize == 0)) { (void) fprintf(stderr,"%s : Illegal image size\n",pname); exit(ERROR_STATUS); } image_size = ABS(xsize*ysize); row_size = ABS(xsize); if (((buffer=malloc(image_size*bytes_per_pixel)) == NULL) || ((outbuf=malloc(row_size*bytes_per_pixel)) == NULL)){ (void) fprintf(stderr,"%s : Image too large\n",pname); exit(ERROR_STATUS); } /* Get range of loop */ xstart = MAX(0,-xsize-1); xstop = MAX(0,xsize-1); xstep = SIGN(xsize); ystart = MAX(0,-ysize-1); ystop = MAX(0,ysize-1); ystep = SIGN(ysize); /* Loop through images */ while ((nread=fread(buffer, bytes_per_pixel, image_size, stdin)) == image_size) { /* Write out inverted image */ for (j=ystart; ystep*j <= ystop; j += ystep) { offset=j*ABS(xsize); for (i=xstart, oi=0; xstep*i <= xstop; i += xstep, oi++) { for (k=0; k0) { (void) fprintf(stderr,"%s : Insufficient data\n", pname); exit(ERROR_STATUS); } return NORMAL_STATUS; } minc-2.2.00/progs/mincwindow/0000755000265600003100000000000012030114723013020 500000000000000minc-2.2.00/progs/mincwindow/mincwindow.man10000644000265600003100000000221312027132663015703 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MINCWINDOW 1 "$Date: 2004-05-20 21:52:09 $" "" "MINC User's Guide" .SH NAME mincwindow \- limit voxel values to a given range .SH SYNOPSIS .B mincwindow .BI [options] .BI in.mnc .BI out.mnc .BI min .BI max .BI [newvalue] .SH DESCRIPTION \fImincwindow\fR copies \fIin.mnc\fR to \fIout.mnc\fR. Each voxel value that lies within the window [\fImin\fR,\fImax\fR] is copied unmodified. If the voxel value is outside that window and \fInewvalue\fR is specified, then that voxel is set to \fInewvalue\fR. Otherwise, the voxel value is set to \fImin\fR if it is less than \fImin\fR, and to \fImax\fR if it is higher than \fImax\fR. .SH OPTIONS .TP \fB\-2\fR Create MINC 2.0 format output files. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-noclobber\fR Don't overwrite an existing file (default). .TP \fB\-verbose\fR Print out log messages (default). .TP \fB\-quiet\fR Do not print log messages. .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH "SEE ALSO" .LP .BR mincmath (1), .BR minccalc (1) minc-2.2.00/progs/mincwindow/mincwindow.c0000644000265600003100000001756212027132663015306 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : mincwindow @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to limit voxel values to a given range @METHOD : @GLOBALS : @CALLS : @CREATED : January 10, 1994 (Peter Neelin) @MODIFIED : * $Log: mincwindow.c,v $ * Revision 6.7 2008-01-17 02:33:06 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.6 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.5 2007/12/11 12:43:01 rotor * * added static to all global variables in main programs to avoid linking * problems with libraries (compress in mincconvert and libz for example) * * Revision 6.4 2005/08/26 21:07:18 bert * Use #if rather than #ifdef with MINC2 symbol, and be sure to include config.h whereever MINC2 is used * * Revision 6.3 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.2 2004/04/27 15:28:39 bert * Added -2 option * * Revision 6.1 1999/10/19 14:45:30 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:24:05 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:25:05 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:01:34 neelin * Release of minc version 0.4 * * Revision 3.2 1995/11/16 13:15:11 neelin * Added include of math.h to get declaration of strtod under SunOs * * Revision 3.1 1995/10/25 17:36:49 neelin * Fixed check of arguments: comparing char to NULL. * * Revision 3.0 1995/05/15 19:32:20 neelin * Release of minc version 0.3 * * Revision 2.4 1995/03/21 14:35:25 neelin * Changed usage message and handle vector volumes properly. * * Revision 2.3 1995/03/21 14:05:00 neelin * Modified calls to voxel_loop routines. * * Revision 2.2 1995/02/08 19:31:47 neelin * Moved ARGSUSED statements for irix 5 lint. * * Revision 2.1 1994/12/14 10:20:23 neelin * Changed to use standard (Proglib) voxel_loop routines. * * Revision 2.0 94/09/28 10:36:27 neelin * Release of minc version 0.2 * * Revision 1.4 94/09/28 10:36:20 neelin * Pre-release * * Revision 1.3 94/01/12 10:18:33 neelin * Added logging. Turned off filling. Added miclose for files. * * Revision 1.2 94/01/11 15:56:17 neelin * Added optional newvalue argument. * * Revision 1.1 94/01/11 15:02:56 neelin * Initial revision * ---------------------------------------------------------------------------- */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Structure for window information */ typedef struct { int use_newvalue; double newvalue; double minimum; double maximum; } Window_Data; /* Function prototypes */ static void do_window(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info); /* Argument variables */ static int clobber = FALSE; static int verbose = TRUE; #if MINC2 static int v2format = FALSE; #endif /* MINC2 */ /* Argument table */ static ArgvInfo argTable[] = { #if MINC2 {"-2", ARGV_CONSTANT, (char *) TRUE, (char *) &v2format, "Produce a MINC 2.0 format output file."}, #endif /* MINC2 */ {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out log messages (default)."}, {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, "Do not print out log messages."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *infile, *outfile; char *arg_string; Window_Data window_data; char *endptr; Loop_Options *loop_options; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Get arguments */ if (ParseArgv(&argc, argv, argTable, 0) || (argc < 5) || (argc > 6)) { (void) fprintf(stderr, "\nUsage: %s [options] []\n", argv[0]); (void) fprintf(stderr, "Usage: %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; window_data.minimum = strtod(argv[3], &endptr); if ((endptr == argv[3]) || (*endptr != '\0')) { (void) fprintf(stderr, "Cannot get min value from %s\n", argv[3]); exit(EXIT_FAILURE); } window_data.maximum = strtod(argv[4], &endptr); if ((endptr == argv[4]) || (*endptr != '\0')) { (void) fprintf(stderr, "Cannot get max value from %s\n", argv[4]); exit(EXIT_FAILURE); } if (argc == 6) { window_data.use_newvalue = TRUE; window_data.newvalue = strtod(argv[5], &endptr); if ((endptr == argv[5]) || (*endptr != '\0')) { (void) fprintf(stderr, "Cannot get newvalue from %s\n", argv[5]); exit(EXIT_FAILURE); } } else { window_data.use_newvalue = FALSE; window_data.newvalue = 0.0; } /* Do loop */ loop_options = create_loop_options(); set_loop_verbose(loop_options, verbose); set_loop_clobber(loop_options, clobber); #if MINC2 set_loop_v2format(loop_options, v2format); #endif /* MINC2 */ voxel_loop(1, &infile, 1, &outfile, arg_string, loop_options, do_window, (void *) &window_data); exit(EXIT_SUCCESS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : do_window @INPUT : voxel_data - pointer to structure containing windowing info nvoxels - number of voxels to operate on data - array of voxels @OUTPUT : data @RETURNS : (nothing) @DESCRIPTION: Routine to loop through an array of voxels and limit the range of values. @METHOD : @GLOBALS : @CALLS : @CREATED : January 11, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void do_window(void *caller_data, long num_voxels, int input_num_buffers, int input_vector_length, double *input_data[], int output_num_buffers, int output_vector_length, double *output_data[], Loop_Info *loop_info) /* ARGSUSED */ { Window_Data *window_data; long ivox; /* Get pointer to window info */ window_data = (Window_Data *) caller_data; /* Check arguments */ if ((input_num_buffers != 1) || (output_num_buffers != 1) || (output_vector_length != input_vector_length)) { (void) fprintf(stderr, "Bad arguments to do_window!\n"); exit(EXIT_FAILURE); } /* Loop through the voxels */ for (ivox=0; ivox < num_voxels*input_vector_length; ivox++) { if (input_data[0][ivox] < window_data->minimum) { if (window_data->use_newvalue) output_data[0][ivox] = window_data->newvalue; else output_data[0][ivox] = window_data->minimum; } else if (input_data[0][ivox] > window_data->maximum) { if (window_data->use_newvalue) output_data[0][ivox] = window_data->newvalue; else output_data[0][ivox] = window_data->maximum; } else { output_data[0][ivox] = input_data[0][ivox]; } } return; } minc-2.2.00/progs/Proglib/0000755000265600003100000000000012030114723012240 500000000000000minc-2.2.00/progs/Proglib/convert_origin_to_start.h0000644000265600003100000000314312027132662017310 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : convert_origin_to_start.h @DESCRIPTION: Header file for covnert_origin_to_start.c @METHOD : @GLOBALS : @CREATED : November 7, 1995 (Peter Neelin) @MODIFIED : * $Log: convert_origin_to_start.h,v $ * Revision 6.1 1999-10-19 14:45:13 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 1.1 1995/11/10 20:01:27 neelin * Initial revision * @COPYRIGHT : Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ int convert_origin_to_start(double origin[], double xdircos[], double ydircos[], double zdircos[], double start[]); minc-2.2.00/progs/Proglib/minc_def.h0000644000265600003100000000536512027132662014116 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : minc_def.h @DESCRIPTION: Header file to define general things needed for minc programs @GLOBALS : @CALLS : @CREATED : July 7, 1993 (Peter Neelin) @MODIFIED : * $Log: minc_def.h,v $ * Revision 6.2 1999-10-19 15:57:17 neelin * Fixed log message containing log substitution * * Revision 6.1 1999/10/19 14:45:13 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:35 neelin * Release of minc version 0.3 * * Revision 2.1 1994/12/02 09:03:05 neelin * Added definitions of public and private. * * Revision 2.0 94/09/28 10:34:30 neelin * Release of minc version 0.2 * * Revision 1.6 94/09/28 10:34:22 neelin * Pre-release * * Revision 1.5 93/08/11 13:23:31 neelin * Modified ROUND macro to cast to (long) * * Revision 1.4 93/08/11 13:21:51 neelin * Added macros ROUND and STR_EQ. * * Revision 1.3 93/08/04 13:03:30 neelin * Added RCS Log to keep track of modifications in source * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #ifndef public # define public #endif #ifndef private # define private static #endif #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifndef SEEK_SET # define SEEK_SET 0 #endif #ifdef MALLOC # undef MALLOC #endif #ifdef FREE # undef FREE #endif #ifdef REALLOC # undef REALLOC #endif #ifdef CALLOC # undef CALLOC #endif #define MALLOC(size) ((void *) malloc(size)) #define FREE(ptr) free(ptr) #define REALLOC(ptr, size) ((void *) realloc(ptr, size)) #define CALLOC(nelem, elsize) ((void *) calloc(nelem, elsize)) /* Define useful macros */ #ifdef ROUND # undef ROUND #endif #ifdef STR_EQ # undef STR_EQ #endif #define ROUND( x ) ((long) ((x) + ( ((x) >= 0) ? 0.5 : (-0.5) ) )) #define STR_EQ(s1,s2) (strcmp(s1,s2)==0) minc-2.2.00/progs/Proglib/convert_origin_to_start.c0000644000265600003100000001466412027132662017315 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : convert_origin_to_start.c @DESCRIPTION: File containing routine to convert an origin specified in world coordinates to 3 minc start values by parallel projection. @METHOD : @GLOBALS : @CREATED : November 7, 1995 (Peter Neelin) @MODIFIED : * $Log: convert_origin_to_start.c,v $ * Revision 6.3 2008-01-17 02:33:02 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.2 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.1 1999/10/19 14:45:12 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:41 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:41 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:50 neelin * Release of minc version 0.4 * * Revision 1.1 1995/11/10 20:01:27 neelin * Initial revision * @COPYRIGHT : Copyright 1995 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include /* Constant definition */ #define public #define private static #define WORLD_NDIMS 3 /* Function declarations */ private void calculate_orthogonal_vector(double vector1[], double vector2[], double result[]); /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_origin_to_start @INPUT : origin - point to project xdircos - vector specifying X direction cosine ydircos - vector specifying Y direction cosine zdircos - vector specifying Z direction cosine @OUTPUT : start - array giving X, Y and Z start values @RETURNS : 0 on success, 1 if some direction cosines have zero length, 2 if some direction cosines are parallel. @DESCRIPTION: Routine to convert an origin specified in world coordinates to an array of minc start positions by projecting the point along the edges of the parallelopiped formed by the 3 direction cosines. Direction cosines are normalized. @METHOD : @GLOBALS : @CALLS : @CREATED : November 7, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ public int convert_origin_to_start(double origin[], double xdircos[], double ydircos[], double zdircos[], double start[]) { int idim, jdim; int nparallel; double *axes[WORLD_NDIMS]; double normal[WORLD_NDIMS], lengths[WORLD_NDIMS]; double numerator, denominator, normal_length; /* Set up dircos matrix */ axes[0] = xdircos; axes[1] = ydircos; axes[2] = zdircos; /* Calculate lengths of direction cosines, checking for zero lengths and parallel vectors. */ nparallel = 0; for (idim=0; idim < WORLD_NDIMS; idim++) { calculate_orthogonal_vector(axes[idim], axes[(idim+1)%WORLD_NDIMS], normal); lengths[idim] = 0.0; normal_length = 0.0; for (jdim=0; jdim < WORLD_NDIMS; jdim++) { lengths[idim] += axes[idim][jdim] * axes[idim][jdim]; normal_length += normal[jdim] * normal[jdim]; } lengths[idim] = sqrt(lengths[idim]); if (lengths[idim] == 0.0) { return 1; } if (normal_length == 0.0) { nparallel++; } } if (nparallel != 0) return 2; /* Loop over axes, calculating projections */ for (idim=0; idim < WORLD_NDIMS; idim++) { /* Calculate vector normal to other two axes by doing cross product */ calculate_orthogonal_vector(axes[(idim+1)%WORLD_NDIMS], axes[(idim+2)%WORLD_NDIMS], normal); /* Calculate dot product of origin with normal (numerator) and dot product of current axis with normal (denominator) */ denominator = numerator = 0.0; for (jdim=0; jdim < WORLD_NDIMS; jdim++) { numerator += origin[jdim] * normal[jdim]; denominator += axes[idim][jdim] * normal[jdim]; } /* Calculate parallel projection */ if (denominator != 0.0) start[idim] = lengths[idim] * numerator / denominator; else start[idim] = 0.0; } return 0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : calculate_orthogonal_vector @INPUT : vector1 - first vector vector2 - second vector @OUTPUT : result - vector orthogonal to vector1 and vector2 @RETURNS : (nothing) @DESCRIPTION: Routine to calculate a vector that is orthogonal to 2 other vectors by doing a cross product. The vectors are copied before the calculation so the result vector can be one of the input vectors. @METHOD : @GLOBALS : @CALLS : @CREATED : November 7, 1995 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ private void calculate_orthogonal_vector(double vector1[], double vector2[], double result[]) { int idim; double v1[WORLD_NDIMS], v2[WORLD_NDIMS]; /* Make a copy of the vectors */ for (idim=0; idim < WORLD_NDIMS; idim++) { v1[idim] = vector1[idim]; v2[idim] = vector2[idim]; } for (idim=0; idim < WORLD_NDIMS; idim++) { result[idim] = v1[(idim+1)%WORLD_NDIMS] * v2[(idim+2)%WORLD_NDIMS] - v2[(idim+1)%WORLD_NDIMS] * v1[(idim+2)%WORLD_NDIMS]; } } minc-2.2.00/progs/rawtominc/0000755000265600003100000000000012030114723012645 500000000000000minc-2.2.00/progs/rawtominc/rawtominc.man10000644000265600003100000003200412027132663015356 00000000000000.\" Hey, EMACS: -*- nroff -*- .\" Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, .\" Montreal Neurological Institute, McGill University. .\" Permission to use, copy, modify, and distribute this .\" software and its documentation for any purpose and without .\" fee is hereby granted, provided that the above copyright .\" notice appear in all copies. The author and McGill University .\" make no representations about the suitability of this .\" software for any purpose. It is provided "as is" without .\" express or implied warranty. .\" .\" $Header: /private-cvsroot/minc/progs/rawtominc/rawtominc.man1,v 6.6 2005-02-09 19:27:18 bert Exp $ .\" .TH RAWTOMINC 1 "$Date: 2005-02-09 19:27:18 $" "" "MINC User's Guide" .SH NAME rawtominc - converts a stream of binary image data to a minc format file .SH SYNOPSIS .B rawtominc [\fIoptions\fR] \fIoutput.mnc\fR [[\fIsz4\fR] \fIsz3\fR] \fIsz2\fR \fIsz1\fR .SH DESCRIPTION .I Rawtominc reads a stream of binary data (byte, short, long, float or double) from standard input (unless the \fB\-input\fR option is used) and writes it into the minc format file \fIoutput.mnc\fR. The user specifies the dimension sizes from slowest varying to fastest varying. At least two dimensions must be given (an image) but there can be up to four. Options give the user control over dimension names, data types and voxel to world coordinate conversion. Vector type data (such as RGB pixel data) can be read in as well. .SH PIXEL VALUE SPECIFICATION Pixel values are specified by a type and a sign (e.g. signed short integer). They are also characterized by a range of legal values. For example, many scanners produce images stored with short integer pixel values. Some have values in the range 0 to 4095, others 0 to 32000, others -32768 to 32767. This range is the valid range, specified by the \fB\-range\fR option (for floating point values, the valid range is the maximum and minimum of the whole dataset). \fIRawtominc\fR allows the user to specify both the input type, sign and range as well as the output type, sign and range (read short values, store byte values, for example). .P There is a further twist. Integer pixel values are generally taken to be simply scaled pixel representations of real (meaningful) physical values. Floating point values are taken to be the real value itself. Thus floating point values are scanned for the maximum and minimum, since they could be anything (they are stored in the MINC variables \fBimage-max\fR and \fBimage-min\fR). Integer values, however, are not scanned by default, since their range can be given by an option. To force scanning of integer values when the maximum and minimum are not known (some scanners produce files with variable ranges), use the option \fB\-scan_range\fR. .SH WORLD COORDINATES World coordinates refer to millimetric coordinates relative to some physical origin (either the scanner or some anatomical structure). Voxel coordinates are simply the indices into the image volume of a given voxel. It is worth describing briefly how MINC coordinate conversions work since this will affect how successful the new MINC file will be. Each dimension of MINC image is specified by name - the spatial dimensions are \fIxspace\fR, \fIyspace\fR and \fIzspace\fR. The convention is that positive \fIxspace\fR coordinates run from the patient's left side to right side, positive \fIyspace\fR coordinates run from patient posterior to anterior and positive \fIzspace\fR coordinates run from inferior to superior. For each of these spatial dimensions, the world coordinate conversion is specified by a pair of attributes: \fIstep\fR and \fIstart\fR. The \fIxspace\fR world coordinate, for example, is calculated using x = v*step + start, where x is the x world coordinate and v is the voxel count (starting at zero). Thus the magnitude of the \fIstep\fR attribute specifies the distance between voxels and the sign of the \fIstep\fR attribute specifies the orientation of the axis. Programs will use this information to display images with the correct aspect ratio and orientation, so make sure that you get it right. Many scanners store transverse images with the first pixel at the patient's anterior/right side, so it would be necessary to give negative x and y step values. Other conventions have the opposite: first pixel at patient's posterior/left, so step values are positive. Sometimes the first slice is inferior, so the z step should be positive. Other times it is superior, so z step is negative. The image axes do not have to be aligned with the world coordinate axes. The axis directions are recorded in the file as direction cosines - unit vectors - one for each spatial axis. In this case, the \fIstep\fR and \fIstart\fR attributes described in the previous paragraph refer to distances along the axis, not to coordinates of the first voxel. This makes them invariant under a change of axis direction (the whole coordinate system can in fact be rotated just by changing the direction cosines). If the coordinate of the first voxel is known, then it can be converted (projected) to a set of start values by using the \fB\-origin\fR option. .SH OPTIONS .SH Dimension ordering .TP \fB\-transverse\fR Transverse images : [[time] z] y x (Default) .TP \fB\-sagittal\fR Sagittal images : [[time] x] z y .TP \fB\-coronal\fR Coronal images : [[time] y] z x .TP \fB\-time\fR Time ordered images : [[z] time] y x .TP \fB\-xyz\fR Dimension order : [[time] x] y z .TP \fB\-xzy\fR Dimension order : [[time] x] z y .TP \fB\-yxz\fR Dimension order : [[time] y] x z .TP \fB\-yzx\fR Dimension order : [[time] y] z x .TP \fB\-zxy\fR Dimension order : [[time] z] x y .TP \fB\-zyx\fR Dimension order : [[time] z] y x .TP \fB\-dimorder\fR\ \fIdim1\fR,\fIdim2\fR[,\fIdim3\fR[,\fIdim4\fR]] Specify an arbitrary dimension order, given by an comma-separated list of between 2 and 4 dimension names. .TP \fB\-vector\fR\ \fIsize\fR Gives the size of a vector dimension (always the fastest varying dimension). Default is no vector dimension. .SH Input data type and range .TP \fB-byte\fR 8-bit integer values (default). .TP \fB\-short\fR 16-bit integer values. .TP \fB\-int\fR 32-bit integer values. .TP \fB\-long\fR Superseded by \fB\-int\fR. .TP \fB\-float\fR Single-precision floating point values. .TP \fB\-double\fR Double-precision floating point values. .TP \fB\-signed\fR Values are signed integers (default for short and long). Ignored for floating point types. .TP \fB\-unsigned\fR Values are unsigned integers (default for byte). Ignored for floating point types. .TP \fB\-range\fR\ \fImin\fR \fImax\fR specifies the valid range of pixel values. Default is the full range for the type and sign. This option is ignored for floating point values. .TP \fB\-real_range\fR\ \fImin\fR \fImax\fR specifies the real range of image values that corresponds to the pixel values of option \fB\-range\fR. Default is to not store the real image minimum and maximum. If \fB\-scan_range\fR is used, then the image minimum and maximum corresponding to the scanned pixel minimum and maximum are calculated and stored. This option is ignored for floating point values. .TP \fB\-swap_bytes\fR Input values (either \fB\-short\fR or \fB\-int\fR) need to be converted between Motorola (big-endian) and Intel (little-endian) data format. If "short" input is specified, adjacent bytes are swapped. If "int" input is specified, inner and outer byte pairs are swapped. This option has no effect with other input types. .SH Output data type and range .TP \fB\-obyte\fR Store 8-bit integer values (default is input type). .TP \fB\-oshort\fR Store 16-bit integer values (default is input type). .TP \fB\-oint\fR Store 32-bit integer values (default is input type). .TP \fB\-olong\fR Superseded by \fB\-oint\fR. .TP \fB\-ofloat\fR Single-precision floating point values (default is input type). .TP \fB\-odouble\fR Double-precision floating point values (default is input type). .TP \fB\-osigned\fR Values are signed integers (default for short and long). Ignored for floating point types. If output type is not specified, then default is input sign type. .TP \fB\-ounsigned\fR Values are unsigned integers (default for byte). Ignored for floating point types. If output type is not specified, then default is input sign type. .TP \fB\-orange\fR\ \fImin\fR \fImax\fR specifies the valid range of pixel values. Default is the full range for the type and sign. This option is ignored for floating point values. If output type and sign are not specified, then the default is the input range. .SH Scanning integers for range .TP \fB\-noscan_range\fR Do not scan integer values for their minimum and maximum - assume that the -range option gives the appropriate range of pixel values (default). No rescaling of pixel values is done (unless the output type differs from the input type) and the created images are assumed to have a real (not pixel value) minimum and maximum of zero and one. .TP \fB\-scan_range\fR Integer values are scanned for their minimum and maximum. Pixel values are rescaled to give the full range of pixel values and the real minimum and maximum are set to the pixel minimum and maximum (unless -real_range is used). This should be equivalent to converting the input to a floating point type and reading it in with -float -oshort (for example) assuming that -real_range is not used. .SH Writing output file .TP \fB\-2\fR Create MINC 2.0 format output files. .TP \fB\-clobber\fR Overwrite existing minc file (default). .TP \fB-noclobber\fR Don't overwrite existing minc file. .SH Reading from input file .TP \fB\-input\fR\ \fIinputfile\fR Read input data from \fIinputfile\fR instead of standard input. .TP \fB\-skip\fR\ \fIlength\fR Skip the first \fIlength\fR bytes of the input. .SH World coordinate conversion .TP \fB\-xstep\fR\ \fIxstep\fR Step size for x dimension (default = none). .TP \fB\-ystep\fR\ \fIystep\fR Step size for y dimension (default = none). .TP \fB\-zstep\fR\ \fIzstep\fR Step size for z dimension (default = none). .TP \fB\-xstart\fR\ \fIxstart\fR Starting coordinate for x dimension (default = none). This is a distance parallel to the axis. .TP \fB\-ystart\fR\ \fIystart\fR Starting coordinate for y dimension (default = none). This is a distance parallel to the axis. .TP \fB\-zstart\fR\ \fIzstart\fR Starting coordinate for z dimension (default = none). This is a distance parallel to the axis. .TP \fB\-xdircos\fR\ \fIx1\fR\ \fIx2\fR\ \fIx3\fR Direction cosines for x dimension (default = none). .TP \fB\-ydircos\fR\ \fIy1\fR\ \fIy2\fR\ \fIy3\fR Direction cosines for y dimension (default = none). .TP \fB\-zdircos\fR\ \fIz1\fR \fIz2\fR\ \fIz3\fR Direction cosines for z dimension (default = none). .TP \fB\-origin\fR \fIo1\fR\ \fIo2\fR\ \fIo3\fR Specify the spatial coordinates of the first voxel. If the direction cosines are not given or are the default ones, this option will give the same results as using the -start options. Otherwise, the coordinate is projected parallel to the axes to determine the appropriate start values. .SH Frame time and length specification .TP \fB\-frame_times\fR \fIt1\fR,\fIt2\fR,\fIt3\fR,... Specify the start of each time frame. The number of values given must be equal to the length of the time dimension specified on the command line. All of the values given must be in one argument (no spaces between them, or the string must be quoted). Separation by spaces instead of commas is permitted. .TP \fB\-frame_widths\fR\ \fIw1\fR,\fIw2\fR,\fIw3\fR,... Specify the length of each time frame. The comments for \fI-frame_times\fR apply here as well. .P To set the start and step values for a functional file with a constant frame times, use the \fI\-dattribute\fR\ flag described below as follows: -dattribute time:step=1 -dattribute time:start=0 .SH Imaging modality .TP \fB-nomodality\fR Do not store modality type in file (default). .TP \fB\-pet\fR PET data. .TP \fB\-mri\fR MRI data. .TP \fB\-spect\fR SPECT data. .TP \fB\-gamma\fR Data from a gamma camera. .TP \fB\-mrs\fR MR spectroscopy data. .TP \fB\-mra\fR MR angiography data. .TP \fB\-ct\fR CT data. .TP \fB-dsa\fR DSA data .TP \fB\-dr\fR Digital radiography data. .SH Attribute specification .TP \fB\-sattribute\fR \fIvariable\fR:\fIattribute\fR=\fIvalue\fR Specify that \fIvariable\fR should be created with string \fIattribute\fR set to \fIvalue\fR. The complete specification, including \fIvariable\fR, \fIattribute\fR and \fIvalue\fR, should be contained in only one argument to the program - quoting may be needed for strings containing blanks. .TP \fB\-dattribute\fR\ \fIvariable\fR:\fIattribute\fR=\fIvalue\fR : Like \fB\-sattribute\fR, but for specifying double-precision attribute values. .TP \fB\-attribute\fR\ \fIvariable\fR:\fIattribute\fR=\fIvalue\fR Like \fB\-sattribute\fR or \fB\-dattribute\fR, except that the type is chosen by first trying to interpret the value as double precision - if that fails, then the value is assumed to be a string. .SH Generic options .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 by Peter Neelin minc-2.2.00/progs/rawtominc/rawtominc.c0000644000265600003100000020064012027132663014747 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : rawtominc @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : error status @DESCRIPTION: Converts a raw volume of data values (read from standard input) to a minc format file. @METHOD : @GLOBALS : @CALLS : @CREATED : September 25, 1992 (Peter Neelin) @MODIFIED : * $Log: rawtominc.c,v $ * Revision 6.29 2008-08-13 06:26:29 rotor * * added Claudes (many) 64 bit fixes to dicom code and updates * * 64 bit fix for rawtominc's use of ParseArgv * * Revision 6.28 2008/01/17 02:33:06 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.27 2008/01/13 04:30:28 stever * Add braces around static initializers. * * Revision 6.26 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.25 2008/01/11 07:17:08 stever * Remove unused variables. * * Revision 6.24 2007/02/20 18:24:45 baghdadi * make sure the global scaling happens when input is float and output is float or double * * Revision 6.23 2007/02/02 18:53:46 baghdadi * Create global scaling for float dat * * Revision 6.22 2007/01/09 21:56:59 baghdadi * Added -2 option for minc2.0 support * * Revision 6.21 2006/07/28 18:17:15 baghdadi * Added -like option to list of arguments similar behaviour like mincresample. * * Revision 6.20 2006/05/11 15:09:57 claude * added float and double to -swap_bytes * * Revision 6.13.2.2 2005/03/16 19:02:52 bert * Port changes from 2.0 branch * * Revision 6.13.2.1 2004/09/28 20:07:30 bert * Minor portability fixes for Windows * * Revision 6.13 2004/02/02 18:24:58 bert * Include a ARGV_VERINFO record in the argTable[] * * Revision 6.12 2003/11/14 16:52:24 stever * More last-minute fixes. * * Revision 6.11 2003/11/03 19:43:18 bert * Handle unspecified dimension order correctly * * Revision 6.10 2003/10/29 17:50:18 bert * Added -dimorder option * * Revision 6.9 2003/10/21 22:22:09 bert * Added -swap_bytes option for int or short input, per A. Janke. * * Revision 6.8 2002/08/05 00:53:50 neelin * Added slightly modified code from Colin Holmes to support -skip option * * Revision 6.7 2001/09/18 15:33:00 neelin * Create image variable last to allow big images and to fix compatibility * problems with 2.3 and 3.x. * * Revision 6.6 2001/08/16 16:41:37 neelin * Added library functions to handle reading of datatype, sign and valid range, * plus writing of valid range and setting of default ranges. These functions * properly handle differences between valid_range type and image type. Such * difference can cause valid data to appear as invalid when double to float * conversion causes rounding in the wrong direction (out of range). * Modified voxel_loop, volume_io and programs to use these functions. * * Revision 6.5 2001/04/24 13:38:46 neelin * Replaced NC_NAT with MI_ORIGINAL_TYPE. * * Revision 6.4 2001/04/17 18:40:25 neelin * Modifications to work with NetCDF 3.x * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints). * Changed NC_UNSPECIFIED to NC_NAT. * A few fixes to the configure script. * * Revision 6.3 1999/10/19 14:45:31 neelin * Fixed Log subsitutions for CVS * * Revision 6.2 1998/06/22 14:06:01 neelin * Fixed bug in handling of default types and signs. * * Revision 6.1 1997/09/29 12:22:46 neelin * Clarified argument error messages. * * Revision 6.0 1997/09/12 13:23:25 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:26 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 19:59:55 neelin * Release of minc version 0.4 * * Revision 3.3 1997/04/21 20:19:17 neelin * Added -origin option. * * Revision 3.2 1996/06/19 18:24:16 neelin * Check errors on fopen when -input is used. * Try opening input before creating minc file. * * Revision 3.1 1995/11/16 13:11:16 neelin * Added include of math.h to get declaration of strtod under SunOs * * Revision 3.0 1995/05/15 19:31:00 neelin * Release of minc version 0.3 * * Revision 2.7 1995/03/30 13:00:05 neelin * Added -sattribute and -dattribute options. * * Revision 2.6 1995/02/15 18:10:35 neelin * Added check for global attribute specified with -attribute. * * Revision 2.5 1995/02/08 19:31:47 neelin * Moved ARGSUSED statements for irix 5 lint. * * Revision 2.4 1995/01/23 09:07:46 neelin * changed ncclose to miclose. * * Revision 2.3 95/01/23 08:59:31 neelin * Changed nccreate to micreate * * Revision 2.2 95/01/03 13:09:24 neelin * Added direction cosine support. * * Revision 2.1 94/10/11 16:18:50 neelin * Fixed scanning of integers for max and min (conversion to double had * signed and unsigned reversed). * * Revision 2.0 94/09/28 10:33:01 neelin * Release of minc version 0.2 * * Revision 1.15 94/09/28 10:32:55 neelin * Pre-release * * Revision 1.14 94/09/23 08:30:52 neelin * Added -xyz, etc options for image/volume orientation. * * Revision 1.13 94/06/10 15:24:41 neelin * Added option -real_range. * * Revision 1.12 94/05/05 10:31:53 neelin * Added -scan_range, -frame_time, -frame_width, -input, -attribute and * modality options. * * Revision 1.11 93/10/06 10:14:17 neelin * Added include of string.h. * * Revision 1.10 93/08/11 15:25:05 neelin * Added RCS logging to source. * December 2, 1992 (P.N.) - changed to parse argv with ParseArgv @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "config.h" #include #include #include #include #include #if HAVE_FLOAT_H #include #endif /* HAVE_FLOAT_H */ #include #if HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ #include #include #include /* Some constants */ #define VECTOR_SEPARATOR ',' #define NORMAL_STATUS 0 #define ERROR_STATUS 1 #define MIN_DIMS 2 #define MAX_DIMS 4 #define DEF_TYPE 0 #define BYTE_TYPE 1 #define SHORT_TYPE 2 #define INT_TYPE 3 #define FLOAT_TYPE 4 #define DOUBLE_TYPE 5 #define DEF_SIGN 0 #define SIGNED 1 #define UNSIGNED 2 #define TRUE 1 #define FALSE 0 #define X 0 #define Y 1 #define Z 2 #define WORLD_NDIMS 3 #define DEF_STEP DBL_MAX #define DEF_START DBL_MAX #define DEF_RANGE DBL_MAX #define DEF_DIRCOS DBL_MAX #define DEF_ORIGIN DBL_MAX #define ARG_SEPARATOR ',' /* LB. needed for volume_def */ #define VOL_NDIMS 3 /* Number of volume dimensions */ #define WORLD_NDIMS 3 /* Number of world spatial dimensions */ int Specified_like = FALSE; /* Macros */ #define STR_EQ(s1,s2) (strcmp(s1,s2)==0) /* LB. For referring to world axes in arrays subscripted by WORLD_NDIMS */ #define NO_AXIS -1 #define XAXIS 0 #define YAXIS 1 #define ZAXIS 2 typedef struct { char *name; int mincid; int imgid; int maxid; int minid; int ndims; nc_type datatype; int is_signed; double vrange[2]; /* [0]=min, [1]=max */ long nelements[MAX_VAR_DIMS]; /* Size of each dimension */ int world_axes[MAX_VAR_DIMS]; /* Relates variable index to X, Y, Z or NO_AXIS */ int indices[VOL_NDIMS]; /* Indices of volume dimenions (subscripted from slowest to fastest) */ int axes[WORLD_NDIMS]; /* Relates world X,Y,Z (index) to dimension order (value=0,1,2; 0=slowest varying) */ int using_icv; /* True if we are using an icv to read data */ int icvid; /* Id of icv (if used) */ long slices_per_image; /* Number of volume slices (row, column) per minc file image */ long images_per_file; /* Number of minc file images in the file */ int do_slice_renormalization; /* Flag indicating that we need to loop through the data a second time, recomputing the slices to normalize images properly */ int keep_real_range; /* Flag indicating whether we should keep the real range of the input data or not */ } File_Info; typedef struct { int axes[WORLD_NDIMS]; /* Relates world X,Y,Z (index) to dimension order (value=0,1,2; 0=slowest varying) */ long nelements[WORLD_NDIMS]; /* These are subscripted by X, Y and Z */ double step[WORLD_NDIMS]; double start[WORLD_NDIMS]; double dircos[WORLD_NDIMS][WORLD_NDIMS]; double *coords[WORLD_NDIMS]; char units[WORLD_NDIMS][MI_MAX_ATTSTR_LEN]; char spacetype[WORLD_NDIMS][MI_MAX_ATTSTR_LEN]; } Volume_Definition; /* Function declarations */ static void parse_args(int argc, char *argv[]); static void usage_error(char *pname); static int get_attribute(char *dst, char *key, char *nextarg); static int get_times(char *dst, char *key, char *nextarg); static int get_axis_order(char *dst, char *key, char *nextArg); /* LB. function prototypes */ static void get_file_info(char *filename, int initialized_volume_def, Volume_Definition *volume_def, File_Info *file_info); static int get_model_file(char *dst, char *key, char *nextArg); /* Array containing information about signs. It is subscripted by [signtype][type]. Note that the first row should never be used, since default_signs should be used instead. */ char *sign_names[][6] = { {MI_SIGNED, MI_UNSIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED}, {MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED}, {MI_SIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED} }; /* Array containing default signs subscripted by [type] (default, byte, short, int, float, double) */ int default_signs[] = { SIGNED, UNSIGNED, SIGNED, SIGNED, SIGNED, SIGNED }; /* Information converting types for argument processing to NetCDF types */ nc_type convert_types[] = { MI_ORIGINAL_TYPE, NC_BYTE, NC_SHORT, NC_INT, NC_FLOAT, NC_DOUBLE }; /* enum for modality types to avoid problems with passing pointers in ParseArgv */ typedef enum { MODALITY_NONE, MODALITY_PET, MODALITY_MRI, MODALITY_SPECT, MODALITY_GAMMA, MODALITY_MRS, MODALITY_MRA, MODALITY_CT, MODALITY_DSA, MODALITY_DR } Modality_code; /* Argument variables */ char *pname; char *filename; int clobber=FALSE; #if MINC2 int v2format=FALSE; /* Version 2.0 file format? */ #endif /* MINC2 */ char *dimname[MAX_VAR_DIMS]; long dimlength[MAX_VAR_DIMS]; int ndims; /* LB. */ int NDims=0; int type = BYTE_TYPE; int signtype = DEF_SIGN; nc_type datatype; char *sign; double valid_range[2] = {0.0, -1.0}; int vrange_set; int otype = DEF_TYPE; int osigntype = DEF_SIGN; nc_type odatatype; char *osign; double ovalid_range[2] = {0.0, -1.0}; int ovrange_set; double dimstep[3] = {DEF_STEP, DEF_STEP, DEF_STEP}; double dimstart[3] = {DEF_START, DEF_START, DEF_START}; double dimdircos[3][3] = { { DEF_DIRCOS, DEF_DIRCOS, DEF_DIRCOS }, { DEF_DIRCOS, DEF_DIRCOS, DEF_DIRCOS }, { DEF_DIRCOS, DEF_DIRCOS, DEF_DIRCOS } }; double origin[3] = {DEF_ORIGIN, DEF_ORIGIN, DEF_ORIGIN}; int vector_dimsize = -1; Modality_code modality = MODALITY_NONE; int attribute_list_size = 0; int attribute_list_alloc = 0; struct { char *variable; char *attribute; char *value; double double_value; } *attribute_list = NULL; int num_frame_times = 0; double *frame_times = NULL; int num_frame_widths = 0; double *frame_widths = NULL; char *inputfile = NULL; int do_minmax = FALSE; double real_range[2] = {DEF_RANGE, DEF_RANGE}; long skip_length; int swap_bytes = FALSE; char *axis_order[MAX_DIMS+1] = { MItime, MIzspace, MIyspace, MIxspace }; /* LB. */ static Volume_Definition volume_def; /* Argument table */ ArgvInfo argTable[] = { {NULL, ARGV_VERINFO, (char *) VERSION, (char *) NULL, NULL}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, "Options to specify input dimension order (from slowest to fastest)."}, {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, " Default = -transverse."}, {"-transverse", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Transverse images : [[time] z] y x"}, {"-sagittal", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Sagittal images : [[time] x] z y"}, {"-coronal", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Coronal images : [[time] y] z x"}, {"-time", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Time ordered images : [[z] time] y x"}, {"-xyz", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Dimension order : [[time] x] y z"}, {"-xzy", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Dimension order : [[time] x] z y"}, {"-yxz", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Dimension order : [[time] y] x z"}, {"-yzx", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Dimension order : [[time] y] z x"}, {"-zxy", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Dimension order : [[time] z] x y"}, {"-zyx", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Dimension order : [[time] z] y x"}, {"-dimorder", ARGV_FUNC, (char *) get_axis_order, (char *) axis_order, "Arbitrary dimensions: ,[,[,:=)."}, {"-dattribute", ARGV_FUNC, (char *) get_attribute, NULL, "Set a double precision attribute (:=)."}, {"-attribute", ARGV_FUNC, (char *) get_attribute, NULL, "Set an attribute, guessing the type (:=)."}, {NULL, ARGV_HELP, NULL, NULL, "Options for specifying time dimension coordinates."}, {"-frame_times", ARGV_FUNC, (char *) get_times, NULL, "Specify the frame starting times (\",,,...\")."}, {"-frame_widths", ARGV_FUNC, (char *) get_times, NULL, "Specify the frame lengths (\",,,...\")."}, {"-like", ARGV_FUNC, (char *) get_model_file, (char *) &volume_def, "Specifies a model file."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { int do_vrange; int cdfid, imgid, maxid, minid, varid; int icv; long start[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS]; long end[MAX_VAR_DIMS]; int dim[MAX_VAR_DIMS]; void *image; double imgmax, imgmin, value; long image_size, image_pix, nread, fastdim; int pix_size; int image_dims; int i, j; int index; FILE *instream; char *tm_stamp; int iatt; long time_start, time_count; int is_signed; void *ptr; int floating_type; int do_real_range; int status; double scale, offset, denom, pixel_min, pixel_max; double dircos[WORLD_NDIMS][WORLD_NDIMS]; int cflags; /* Save time stamp and args */ tm_stamp = time_stamp(argc, argv); /* Parse arguments */ parse_args(argc, argv); /* Do normalization if input type is float */ floating_type = (( datatype==NC_FLOAT) || ( datatype==NC_DOUBLE)); do_minmax = do_minmax || floating_type; /* Find max and min for vrange if output type is float */ do_vrange = do_minmax && (( odatatype==NC_FLOAT) || ( odatatype==NC_DOUBLE)); /* Did the user provide a real range */ do_real_range = (real_range[0] != DEF_RANGE) && !floating_type; /* Check that only start or origin are specified, not both */ for (i=0; i 0) { varid = micreate_std_variable(cdfid, MItime, NC_DOUBLE, 1, &dim[i]); } if (num_frame_widths > 0) { varid = micreate_std_variable(cdfid, MItime_width, NC_DOUBLE, 1, &dim[i]); } } else { varid = micreate_std_variable(cdfid, dimname[i], NC_INT, 0, NULL); /* Write out step and start and direction cosine */ if (STR_EQ(dimname[i], MIxspace)) index = X; if (STR_EQ(dimname[i], MIyspace)) index = Y; if (STR_EQ(dimname[i], MIzspace)) index = Z; if (dimstep[index] != DEF_STEP) { (void) miattputdbl(cdfid, varid, MIstep, dimstep[index]); } if (dimstart[index] != DEF_START) { (void) miattputdbl(cdfid, varid, MIstart, dimstart[index]); } if (dimdircos[index][0] != DEF_DIRCOS) { (void) ncattput(cdfid, varid, MIdirection_cosines, NC_DOUBLE, 3, dimdircos[index]); } } /* Set variables for looping through images */ start[i]=0; count[i]= ((i 0) { ndims++; image_dims++; dim[ndims-1] = ncdimdef(cdfid, MIvector_dimension, (long) vector_dimsize); start[ndims-1] = 0; count[ndims-1] = vector_dimsize; end[ndims-1] = vector_dimsize; } /* Create the modality attribute */ if (modality != MODALITY_NONE) { varid = micreate_group_variable(cdfid, MIstudy); switch (modality){ case MODALITY_PET: (void) miattputstr(cdfid, varid, MImodality, MI_PET); break; case MODALITY_MRI: (void) miattputstr(cdfid, varid, MImodality, MI_MRI); break; case MODALITY_SPECT: (void) miattputstr(cdfid, varid, MImodality, MI_SPECT); break; case MODALITY_GAMMA: (void) miattputstr(cdfid, varid, MImodality, MI_GAMMA); break; case MODALITY_MRS: (void) miattputstr(cdfid, varid, MImodality, MI_MRS); break; case MODALITY_MRA: (void) miattputstr(cdfid, varid, MImodality, MI_MRA); break; case MODALITY_CT: (void) miattputstr(cdfid, varid, MImodality, MI_CT); break; case MODALITY_DSA: (void) miattputstr(cdfid, varid, MImodality, MI_DSA); break; case MODALITY_DR: (void) miattputstr(cdfid, varid, MImodality, MI_DR); break; case MODALITY_NONE: default: (void) fprintf(stderr, "%s: Unknown Modality, this should not happen (call houston).\n", pname); exit(ERROR_STATUS); break; } } /* Create any special attributes */ ncopts = 0; for (iatt=0; iatt < attribute_list_size; iatt++) { if (strlen(attribute_list[iatt].variable) == 0) { varid = NC_GLOBAL; } else { varid = ncvarid(cdfid, attribute_list[iatt].variable); if (varid == MI_ERROR) { varid = micreate_group_variable(cdfid, attribute_list[iatt].variable); } if (varid == MI_ERROR) { varid = ncvardef(cdfid, attribute_list[iatt].variable, NC_INT, 0, NULL); } if (varid == MI_ERROR) { continue; } } if (attribute_list[iatt].value != NULL) { (void) miattputstr(cdfid, varid, attribute_list[iatt].attribute, attribute_list[iatt].value); } else { (void) miattputdbl(cdfid, varid, attribute_list[iatt].attribute, attribute_list[iatt].double_value); } } ncopts = NC_VERBOSE | NC_FATAL; /* Create the image */ if (do_minmax || do_real_range) { if (!floating_type || (otype != FLOAT_TYPE && otype != DOUBLE_TYPE)) { maxid = micreate_std_variable(cdfid, MIimagemax, NC_DOUBLE, ndims-image_dims, dim); minid = micreate_std_variable(cdfid, MIimagemin, NC_DOUBLE, ndims-image_dims, dim); } else { maxid = micreate_std_variable(cdfid, MIimagemax, NC_DOUBLE, 0, NULL); minid = micreate_std_variable(cdfid, MIimagemin, NC_DOUBLE, 0, NULL); } } imgid=micreate_std_variable(cdfid, MIimage, odatatype, ndims, dim); (void) miattputstr(cdfid, imgid, MIcomplete, MI_FALSE); (void) miattputstr(cdfid, imgid, MIsigntype, osign); if (ovrange_set) (void) miset_valid_range(cdfid, imgid, ovalid_range); /* End definition mode */ (void) ncendef(cdfid); /* Write out the frame times and widths */ time_start = 0; time_count = num_frame_times; if (num_frame_times > 0) { (void) mivarput(cdfid, ncvarid(cdfid, MItime), &time_start, &time_count, NC_DOUBLE, NULL, frame_times); } if (num_frame_widths > 0) { (void) mivarput(cdfid, ncvarid(cdfid, MItime_width), &time_start, &time_count, NC_DOUBLE, NULL, frame_widths); } /* Attach the icv */ (void) miicv_attach(icv, cdfid, imgid); /* Get a buffer for reading images */ image_pix = 1; for (i=1; i<=image_dims; i++) image_pix *= end[ndims-i]; pix_size=nctypelen(datatype); image_size=image_pix*pix_size; image=malloc(image_size); /* Loop through the images */ fastdim=ndims-image_dims-1; if (fastdim<0) fastdim=0; if (do_vrange) { ovalid_range[0]=DBL_MAX; ovalid_range[1]=(-DBL_MAX); } /* CJH - July 02 - Skip over any header bytes */ if (skip_length > 0) { /* First try seeking over the header */ if (fseek(instream, skip_length, SEEK_SET) == 0) { /* OK instream was a file and we skipped the requested bytes */ } else { char buffer[8192]; int bytes_copied = 0; while ( bytes_copied < skip_length ) { int bytes_to_read = sizeof(buffer); if ( bytes_to_read + bytes_copied > skip_length ) bytes_to_read = skip_length - bytes_copied; nread = fread(buffer, sizeof(char), bytes_to_read, instream); bytes_copied += nread; if (nread != bytes_to_read) { (void) fprintf(stderr, "%s: Premature end of file.\n", pname); perror("While skipping over small header"); exit(ERROR_STATUS); } } } } while (start[0] < end[0]) { /* Read in image */ nread=fread(image, pix_size, image_pix, instream); if (nread!=image_pix) { (void) fprintf(stderr, "%s: Premature end of file.\n", pname); exit(ERROR_STATUS); } /* If the user wants to swap bytes, do it here before any further * processing of the image. */ if (swap_bytes) { switch (datatype) { case NC_SHORT: /* Easy case - call swab() */ if ((image_size & 1) != 0) { fprintf(stderr, "%s: image size must be even for -swap_bytes\n", pname); exit(ERROR_STATUS); } else { swab(image, image, image_size); } break; case NC_INT: case NC_FLOAT: /* Harder case - have to do a more complex 4-byte swap. */ if ((image_size & 3) != 0) { fprintf(stderr, "%s: image size must be divisible by 4 for -swap_bytes!\n", pname); exit(ERROR_STATUS); } else { unsigned char *img_ptr = image; unsigned char *img_end = (unsigned char*)image + image_size; for ( ; img_ptr < img_end; img_ptr += 4) { unsigned char tmp; /* Swap the inner 2 bytes */ tmp = img_ptr[1]; img_ptr[1] = img_ptr[2]; img_ptr[2] = tmp; /* Swap the outer 2 bytes */ tmp = img_ptr[0]; img_ptr[0] = img_ptr[3]; img_ptr[3] = tmp; } } break; case NC_DOUBLE : /* Harder case - have to do a more complex 8-byte swap. */ if ((image_size & 7) != 0) { fprintf(stderr, "%s: image size must be divisible by 8 for -swap_bytes!\n", pname); exit(ERROR_STATUS); } else { unsigned char *img_ptr = image; unsigned char *img_end = (unsigned char*)image + image_size; for ( ; img_ptr < img_end; img_ptr += 8) { unsigned char tmp; /* Swap bytes [0,1,2,3,4,5,6,7] to [7,6,5,4,3,2,1,0] */ tmp = img_ptr[3]; img_ptr[3] = img_ptr[4]; img_ptr[4] = tmp; tmp = img_ptr[2]; img_ptr[2] = img_ptr[5]; img_ptr[5] = tmp; tmp = img_ptr[1]; img_ptr[1] = img_ptr[6]; img_ptr[6] = tmp; tmp = img_ptr[0]; img_ptr[0] = img_ptr[7]; img_ptr[7] = tmp; } } break; default: fprintf(stderr, "Warning: you specified -swap_bytes, but I can't swap this type of input\n"); break; } } /* Search for max and min for float and double */ if (do_minmax) { imgmax=(-DBL_MAX); imgmin=DBL_MAX; is_signed = (signtype == SIGNED); for (j=0; jimgmax) imgmax=value; } if (do_vrange) { if (imgminovalid_range[1]) ovalid_range[1]=imgmax; } } else { imgmin = pixel_min; imgmax = pixel_max; } /* Change the valid range for integer types if needed */ if (do_minmax && !floating_type) { (void) miicv_detach(icv); (void) miicv_setdbl(icv, MI_ICV_VALID_MIN, imgmin); (void) miicv_setdbl(icv, MI_ICV_VALID_MAX, imgmax); (void) miicv_attach(icv, cdfid, imgid); } /* Write the image max and min after re-scaling */ if (do_minmax || do_real_range) { imgmin = imgmin * scale + offset; imgmax = imgmax * scale + offset; if (!floating_type || (otype != FLOAT_TYPE && otype != DOUBLE_TYPE)) { (void) mivarput1(cdfid, minid, start, NC_DOUBLE, NULL, &imgmin); (void) mivarput1(cdfid, maxid, start, NC_DOUBLE, NULL, &imgmax); } } /* Write the image */ (void) miicv_put(icv, start, count, image); /* Increment the counters */ start[fastdim] += count[fastdim]; i=fastdim; while ((i>0) && (start[i]>=end[i])) { start[i] = 0; i--; start[i] += count[i]; } } /* Free the memory */ free(image); /* Write the valid max and min */ if (do_vrange) { (void) miset_valid_range(cdfid, imgid, ovalid_range); } /* Write Global scaling for float data*/ if (floating_type && (otype == FLOAT_TYPE || otype == DOUBLE_TYPE)) { (void) mivarput1(cdfid, minid, 0, NC_DOUBLE, NULL, &ovalid_range[0]); (void) mivarput1(cdfid, maxid, 0, NC_DOUBLE, NULL, &ovalid_range[1]); } /* Close the file */ (void) miattputstr(cdfid, imgid, MIcomplete, MI_TRUE); (void) miclose(cdfid); exit(NORMAL_STATUS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : parse_args @INPUT : argc - number of command line arguments argv - array of arguments @OUTPUT : @RETURNS : (nothing). @DESCRIPTION: Parses command line arguments. @METHOD : @GLOBALS : pname - program name filename - file to write clobber - overwrite? dimname - names of dimensions dimlength - lengths of dimensions ndims - number of dimensions type - type of input data signtype - sign of input data datatype - NetCDF type of input data sign - string sign of input valid_range - valid range of input data vrange_set - valid range used? otype - type of output data osigntype - sign of output data datatype - NetCDF type of output data osign - string sign of output ovalid_range - valid range of output data ovrange_set - valid range used? @CALLS : @CREATED : December 3, 1992 @MODIFIED : ---------------------------------------------------------------------------- */ static void parse_args(int argc, char *argv[]) { char *ptr; int time_size; int i; /* Parse the command line */ pname=argv[0]; if (ParseArgv(&argc, argv, argTable, 0)) { usage_error(pname); } /* Get filename */ filename = argv[1]; /* Check dimensions */ ndims = argc - 2; /* LB. Modified to take -like with no dimension length provided */ if (ndims == 0) { if (!Specified_like) { (void) fprintf(stderr, "\nEither provide dimension lengths or use -like.\n"); usage_error(pname); } else { ndims = NDims; for (i=0; iMAX_DIMS)) { (void) fprintf(stderr, "\nWrong number of arguments.\n"); usage_error(pname); } /* Get dimensions */ for (i=0; i 0)) || ((num_frame_widths != time_size) && (num_frame_widths > 0))) { (void) fprintf(stderr, "Number of frame times or widths does not match number of frames.\n"); exit(EXIT_FAILURE); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : usage_error @INPUT : progname - program name @OUTPUT : (none) @RETURNS : (nothing) @DESCRIPTION: Prints a usage error message and exits. @METHOD : @GLOBALS : @CALLS : @CREATED : September 25, 1992 (Peter Neelin) @MODIFIED : December 2, 1992 (P.N.) ---------------------------------------------------------------------------- */ static void usage_error(char *progname) { (void) fprintf(stderr, "\nUsage: %s [] ", progname); (void) fprintf(stderr, "[[] ] \n"); (void) fprintf(stderr, " %s [-help]\n\n", progname); exit(ERROR_STATUS); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_attribute @INPUT : dst - client data passed by ParseArgv key - matching key in argv nextarg - argument following key in argv @OUTPUT : (none) @RETURNS : TRUE since nextarg is used. @DESCRIPTION: Gets attributes from command line. Syntax for argument is ":=". Numeric values are converted to double precision. @METHOD : @GLOBALS : @CALLS : @CREATED : May 3, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_attribute(char *dst, char *key, char *nextarg) /* ARGSUSED */ { int need_string, need_double; char *variable; char *attribute; char *value; char *end; double dvalue; /* Check for a following argument */ if (nextarg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Figure out whether we need a string or a double */ need_string = (strcmp(key, "-sattribute") == 0); need_double = (strcmp(key, "-dattribute") == 0); /* Get the variable name */ variable = nextarg; attribute = strchr(variable, ':'); if (attribute == NULL) { (void) fprintf(stderr, "%s option requires argument :=\n", key); exit(EXIT_FAILURE); } *attribute = '\0'; attribute++; /* Get the value */ value = strchr(attribute, '='); if (value == NULL) { (void) fprintf(stderr, "%s option requires argument :=\n", key); exit(EXIT_FAILURE); } *value = '\0'; value++; /* Save the information */ attribute_list_size++; if (attribute_list_size > attribute_list_alloc) { attribute_list_alloc += 10; if (attribute_list == NULL) { attribute_list = malloc(attribute_list_alloc * sizeof(*attribute_list)); } else { attribute_list = realloc(attribute_list, attribute_list_alloc * sizeof(*attribute_list)); } } attribute_list[attribute_list_size-1].variable = variable; attribute_list[attribute_list_size-1].attribute = attribute; attribute_list[attribute_list_size-1].value = value; /* Try to get a double precision value */ if (!need_string) { dvalue = strtod(value, &end); if ((end != value) && (*end == '\0')) { attribute_list[attribute_list_size-1].value = NULL; attribute_list[attribute_list_size-1].double_value = dvalue; } else if (need_double) { (void) fprintf(stderr, "\"%s\" option requires a numeric argument\n", key); exit(EXIT_FAILURE); } } return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_times @INPUT : dst - client data passed by ParseArgv key - matching key in argv nextarg - argument following key in argv @OUTPUT : (none) @RETURNS : TRUE since nextarg is used. @DESCRIPTION: Gets frame start times or frame lengths from next argument. @METHOD : @GLOBALS : @CALLS : @CREATED : May 3, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_times(char *dst, char *key, char *nextarg) /* ARGSUSED */ { int *num_elements_ptr; double **time_list_ptr; int num_elements; int num_alloc; double *time_list; double dvalue; char *cur, *end, *prev; /* Check for a following argument */ if (nextarg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Get pointers to global variables */ if (strcmp(key, "-frame_times") == 0) { num_elements_ptr = &num_frame_times; time_list_ptr = &frame_times; } else if (strcmp(key, "-frame_widths") == 0) { num_elements_ptr = &num_frame_widths; time_list_ptr = &frame_widths; } else { (void) fprintf(stderr, "Unknown option \"%s\".\n", key); exit(EXIT_FAILURE); } /* Set up pointers to end of string and first non-space character */ end = nextarg + strlen(nextarg); cur = nextarg; while (isspace(*cur)) cur++; num_elements = 0; num_alloc = 0; time_list = NULL; /* Loop through string looking for doubles */ while (cur!=end) { /* Get double */ prev = cur; dvalue = strtod(prev, &cur); if (cur == prev) { (void) fprintf(stderr, "expected vector of doubles for \"%s\", but got \"%s\"\n", key, nextarg); exit(EXIT_FAILURE); } /* Add the value to the list */ num_elements++; if (num_elements > num_alloc) { num_alloc += 20; if (time_list == NULL) { time_list = malloc(num_alloc * sizeof(*time_list)); } else { time_list = realloc(time_list, num_alloc * sizeof(*time_list)); } } time_list[num_elements-1] = dvalue; /* Skip any spaces */ while (isspace(*cur)) cur++; /* Skip an optional comma */ if (*cur == VECTOR_SEPARATOR) cur++; } /* Update the global variables */ *num_elements_ptr = num_elements; if (*time_list_ptr != NULL) { free(*time_list_ptr); } *time_list_ptr = time_list; return TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_axis_order @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE or FALSE (so that ParseArgv will discard nextArg only when needed) @DESCRIPTION: Routine called by ParseArgv to set the axis order @METHOD : @GLOBALS : @CALLS : @CREATED : March 16, 1994 (Peter Neelin) @MODIFIED : Copied from mincreshape.c by bert, 29 Oct 2003 ---------------------------------------------------------------------------- */ /* "Standard" orientations - index the orientation_names table defined * below. */ #define TRANSVERSE_ORIENTATION 0 #define SAGITTAL_ORIENTATION 1 #define CORONAL_ORIENTATION 2 #define TIME_FAST_ORIENTATION 3 #define XYZ_ORIENTATION 4 #define YXZ_ORIENTATION 5 #define ZXY_ORIENTATION 6 #define STD_ORIENTATION_COUNT 7 static int get_axis_order(char *dst, char *key, char *nextArg) { char **dim_name_array; char *argp; int i, j; int orientation; /* Structure containing information about orientation */ static char *orientation_names[STD_ORIENTATION_COUNT][MAX_DIMS] = { {MItime, MIzspace, MIyspace, MIxspace}, /* TRANSVERSE_ORIENTATION */ {MItime, MIxspace, MIzspace, MIyspace}, /* SAGITTAL_ORIENTATION */ {MItime, MIyspace, MIzspace, MIxspace}, /* CORONAL_ORIENTATION */ {MIzspace, MItime, MIyspace, MIxspace}, /* TIME_FAST_ORIENTATION */ {MItime, MIxspace, MIyspace, MIzspace}, /* XYZ_ORIENTATION */ {MItime, MIyspace, MIxspace, MIzspace}, /* YXZ_ORIENTATION */ {MItime, MIzspace, MIxspace, MIyspace}, /* ZXY_ORIENTATION */ }; /* LB. To avoid confusion for dimension order with -like*/ if (Specified_like) { (void) fprintf(stderr, "\"%s\" can not use this option with -like\n", key); exit(EXIT_FAILURE); } /* Get pointer to client data */ dim_name_array = (char **) dst; if (!strcmp(key, "-dimorder")) { /* Check for next argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* Set up pointers to end of string and first non-space character */ argp = nextArg; while (isspace(*argp)) argp++; /* Loop through string looking for space or comma-separated names */ for (i = 0; i < MAX_DIMS && *argp != '\0'; i++) { dim_name_array[i] = argp; /* Get string */ /* Search for end of dimension name */ while (!isspace(*argp) && *argp != ARG_SEPARATOR && *argp != '\0') argp++; if (*argp != '\0') { *argp = '\0'; argp++; } /* Skip any spaces */ while (isspace(*argp)) argp++; } /* BEGIN WEIRDNESS */ /* parse_args() assumes that the axis_order[] array contains * MAX_DIMS (4) entries, with optional values at the * _beginning_ of the array. To make the array we just * constructed compatible with that assumption, I need to copy * all of the just-specified dimensions to the end of this * array, and fill the earlier entries up with some sort of * dummy value. */ if (i < MAX_DIMS) { int deficit = MAX_DIMS - i; /* How many we're missing */ for (j = i; j >= 0; j--) { dim_name_array[j + deficit] = dim_name_array[j]; } for (j = 0; j < deficit; j++) { dim_name_array[j] = "unknown"; /* Just a dummy value. */ } } /* END WEIRDNESS */ /* Return TRUE to let the argv processor know that we used an * extra argument. */ return (TRUE); } else if (!strcmp(key, "-transverse") || !strcmp(key, "-zyx")) { orientation = TRANSVERSE_ORIENTATION; } else if (!strcmp(key, "-sagittal") || !strcmp(key, "-xzy")) { orientation = SAGITTAL_ORIENTATION; } else if (!strcmp(key, "-coronal") || !strcmp(key, "-yzx")) { orientation = CORONAL_ORIENTATION; } else if (!strcmp(key, "-time")) { orientation = TIME_FAST_ORIENTATION; } else if (!strcmp(key, "-xyz")) { orientation = XYZ_ORIENTATION; } else if (!strcmp(key, "-yxz")) { orientation = YXZ_ORIENTATION; } else if (!strcmp(key, "-zxy")) { orientation = ZXY_ORIENTATION; } else { (void) fprintf(stderr, "Unrecognized option \"%s\": internal program error.\n", key); exit(EXIT_FAILURE); } /* Copy from the appropriate row of the static array into the * dimension name array. */ for (i = 0; i < MAX_DIMS; i++) { dim_name_array[i] = orientation_names[orientation][i]; } /* Return FALSE to let the argv processor know we didn't use anything * extra from the argument list. */ return (FALSE); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_file_info @INPUT : filename - name of file to read initialized_volume_def - if TRUE, then volume_def is taken as being properly initialized and arrays are freed if non-NULL. Otherwise arrays are not freed. @OUTPUT : volume_def - description of volume file_info - description of file @RETURNS : (nothing) @DESCRIPTION: Routine to get information about the volume definition of a minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : February 9, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void get_file_info(char *filename, int initialized_volume_def, Volume_Definition *volume_def, File_Info *file_info) { int dim[MAX_VAR_DIMS], dimid; int axis_counter, idim, jdim, cur_axis; int varndims, vardim[MAX_VAR_DIMS]; long varstart, varcount, dimlength1; char attstr[MI_MAX_ATTSTR_LEN]; char dimname1[MAX_NC_NAME]; enum {UNKNOWN, REGULAR, IRREGULAR} coord_spacing; /* Open the minc file */ file_info->mincid = miopen(filename, NC_NOWRITE); file_info->name = filename; /* Get variable identifiers */ file_info->imgid = ncvarid(file_info->mincid, MIimage); ncopts = 0; file_info->maxid = ncvarid(file_info->mincid, MIimagemax); file_info->minid = ncvarid(file_info->mincid, MIimagemin); ncopts = NC_VERBOSE | NC_FATAL; /* Get information about datatype dimensions of variable */ (void) miget_datatype(file_info->mincid, file_info->imgid, &file_info->datatype, &file_info->is_signed); /* Get valid max and min */ (void) miget_valid_range(file_info->mincid, file_info->imgid, file_info->vrange); /* Get information about dimensions */ (void) ncvarinq(file_info->mincid, file_info->imgid, NULL, NULL, &file_info->ndims, dim, NULL); /* Set variables for keeping track of spatial dimensions */ axis_counter = 0; /* Keeps track of values for axes */ /* Initialize volume definition variables */ for (idim=0; idim < WORLD_NDIMS; idim++) { volume_def->axes[idim] = NO_AXIS; volume_def->step[idim] = 1.0; volume_def->start[idim] = 0.0; for (jdim=0; jdim < WORLD_NDIMS; jdim++) { if (jdim==idim) volume_def->dircos[idim][jdim] = 1.0; else volume_def->dircos[idim][jdim] = 0.0; } if (initialized_volume_def && (volume_def->coords[idim] != NULL)) { free(volume_def->coords[idim]); } volume_def->coords[idim] = NULL; (void) strcpy(volume_def->units[idim], "mm"); (void) strcpy(volume_def->spacetype[idim], MI_NATIVE); } /* Loop through dimensions, getting dimension information */ for (idim=0; idim < file_info->ndims; idim++) { /* Get size of dimension */ (void) ncdiminq(file_info->mincid, dim[idim], dimname1, &file_info->nelements[idim]); /* Check variable name */ /* LB. added minor modification to change axis_order for dimension order and name */ cur_axis = NO_AXIS; if (strcmp(dimname1, MIxspace)==0) { cur_axis = XAXIS; axis_order[idim+1]= MIxspace; } else if (strcmp(dimname1, MIyspace)==0) { cur_axis = YAXIS; axis_order[idim+1]= MIyspace; } else if (strcmp(dimname1, MIzspace)==0) { cur_axis = ZAXIS; axis_order[idim+1]= MIzspace; } /* Save world axis info */ file_info->world_axes[idim] = cur_axis; /* Check for spatial dimension */ if (cur_axis == NO_AXIS) continue; /* Set axis */ if (volume_def->axes[cur_axis] != NO_AXIS) { (void) fprintf(stderr, "Repeated spatial dimension %s in file %s.\n", dimname1, filename); exit(EXIT_FAILURE); } volume_def->axes[cur_axis] = axis_counter++; /* Save spatial axis specific info */ file_info->axes[cur_axis] = volume_def->axes[cur_axis]; file_info->indices[volume_def->axes[cur_axis]] = idim; volume_def->nelements[cur_axis] = file_info->nelements[idim]; /* Check for existence of variable */ ncopts = 0; dimid = ncvarid(file_info->mincid, dimname1); ncopts = NC_VERBOSE | NC_FATAL; if (dimid == MI_ERROR) continue; /* Get attributes from variable */ ncopts = 0; (void) miattget1(file_info->mincid, dimid, MIstep, NC_DOUBLE, &volume_def->step[cur_axis]); if (volume_def->step[cur_axis] == 0.0) volume_def->step[cur_axis] = 1.0; (void) miattget1(file_info->mincid, dimid, MIstart, NC_DOUBLE, &volume_def->start[cur_axis]); (void) miattget(file_info->mincid, dimid, MIdirection_cosines, NC_DOUBLE, WORLD_NDIMS, volume_def->dircos[cur_axis], NULL); (void) miattgetstr(file_info->mincid, dimid, MIunits, MI_MAX_ATTSTR_LEN, volume_def->units[cur_axis]); (void) miattgetstr(file_info->mincid, dimid, MIspacetype, MI_MAX_ATTSTR_LEN, volume_def->spacetype[cur_axis]); ncopts = NC_VERBOSE | NC_FATAL; /* Normalize the direction cosine */ // normalize_vector(volume_def->dircos[cur_axis]); /* Look for irregular coordinates for dimension variable */ ncopts = 0; coord_spacing = UNKNOWN; dimlength1 = volume_def->nelements[cur_axis]; if (miattgetstr(file_info->mincid, dimid, MIspacing, MI_MAX_ATTSTR_LEN, attstr) != NULL) { if (strcmp(attstr, MI_IRREGULAR) == 0) coord_spacing = IRREGULAR; else if (strcmp(attstr, MI_REGULAR) == 0) coord_spacing = REGULAR; } if (ncvarinq(file_info->mincid, dimid, NULL, NULL, &varndims, vardim, NULL) == MI_ERROR) { ncopts = NC_VERBOSE | NC_FATAL; continue; } if ((coord_spacing != REGULAR) && (varndims == 1) && (vardim[0] == dim[idim])) { coord_spacing = IRREGULAR; } if ((coord_spacing == UNKNOWN) || (dimlength1 <= 1)) { coord_spacing = REGULAR; } if (coord_spacing == IRREGULAR) { volume_def->coords[cur_axis] = malloc(sizeof(double) * dimlength1); varstart = 0; varcount = dimlength1; if (mivarget(file_info->mincid, dimid, &varstart, &varcount, NC_DOUBLE, MI_SIGNED, volume_def->coords[cur_axis]) == MI_ERROR) { ncopts = NC_VERBOSE | NC_FATAL; free(volume_def->coords[cur_axis]); volume_def->coords[cur_axis] = NULL; continue; } volume_def->start[cur_axis] = volume_def->coords[cur_axis][0]; if (dimlength1 > 1) { volume_def->step[cur_axis] = (volume_def->coords[cur_axis][dimlength1-1] - volume_def->coords[cur_axis][0]) / (dimlength1 - 1); if (volume_def->step[cur_axis] == 0.0) volume_def->step[cur_axis] = 1.0; } } ncopts = NC_VERBOSE | NC_FATAL; } /* End of loop over dimensions */ /* Check that we have the correct number of spatial dimensions */ if (axis_counter != WORLD_NDIMS) { (void) fprintf(stderr, "Incorrect number of spatial dimensions in file %s.\n", filename); exit(EXIT_FAILURE); } return; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_model_file @INPUT : dst - Pointer to client data from argument table key - argument key nextArg - argument following key @OUTPUT : (nothing) @RETURNS : TRUE so that ParseArgv will discard nextArg unless there is no following argument. @DESCRIPTION: Routine called by ParseArgv to read in a model file (-like) @METHOD : @GLOBALS : @CALLS : @CREATED : February 15, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static int get_model_file(char *dst, char *key, char *nextArg) /* ARGSUSED */ { Volume_Definition *volume_def; File_Info file; /* Check for following argument */ if (nextArg == NULL) { (void) fprintf(stderr, "\"%s\" option requires an additional argument\n", key); exit(EXIT_FAILURE); } /* set this flag so we know that -like is used */ Specified_like = TRUE; /* Get pointer to volume definition structure */ volume_def = (Volume_Definition *) dst; /* Get file information */ get_file_info(nextArg, TRUE, volume_def, &file); /* LB. Set number of dimensions */ NDims = file.ndims; /* LB. Set dimension lengths and other info */ dimlength[0] = volume_def->nelements[file.world_axes[0]]; dimlength[1] = volume_def->nelements[file.world_axes[1]]; dimlength[2] = volume_def->nelements[file.world_axes[2]]; /* start */ dimstart[0]= volume_def->start[0]; dimstart[1]= volume_def->start[1]; dimstart[2]= volume_def->start[2]; /* step */ dimstep[0]= volume_def->step[0]; dimstep[1]= volume_def->step[1]; dimstep[2]= volume_def->step[2]; /* modify dircos X */ dimdircos[0][0] = volume_def->dircos[0][0]; dimdircos[0][1] = volume_def->dircos[0][1]; dimdircos[0][2] = volume_def->dircos[0][2]; /* modify dircos Y */ dimdircos[1][0] = volume_def->dircos[1][0]; dimdircos[1][1] = volume_def->dircos[1][1]; dimdircos[1][2] = volume_def->dircos[1][2]; /* modify dircos Z */ dimdircos[2][0] = volume_def->dircos[2][0]; dimdircos[2][1] = volume_def->dircos[2][1]; dimdircos[2][2] = volume_def->dircos[2][2]; /* Close the file */ (void) miclose(file.mincid); return TRUE; } minc-2.2.00/progs/xfm/0000755000265600003100000000000012030114723011434 500000000000000minc-2.2.00/progs/xfm/transformtags.man10000644000265600003100000000217612027132663015043 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH TRANSFORMTAGS 1 "$Date: 2004-05-20 21:52:09 $" "" "MINC User's Guide" .SH NAME transformtags \- apply MNI transform to a tag file .SH SYNOPSIS .B transformtags .BI [ -vol1 ] .BI [ -vol2 ] .BI [ "-transformation transform.xfm" ] .BI infile.tag .BI outfile.tag .SH DESCRIPTION \fBtransformtags\fR applies the specified transformation to one of the two sets of tags in the tag file. The default is to apply the transformation to the tags of the second volume. Use \fB\-vol1\fR to transform the first volume's tag. Only one volume at a time may be transformed. The transformation must be specified using the \fB-transformation\fR option. .SH OPTIONS .TP \fB\-vol1\fR Transform tags for volume 1. .TP \fB\-vol2\fR Transform tags for volume 2 (default). .TP \fB\-transformation\fR\ \fIfilename.xfm\fR Name of transformation file (default is internal identity transform). .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 Peter Neelin minc-2.2.00/progs/xfm/xfm2def.man10000644000265600003100000000427012027132663013501 00000000000000.TH XFM2DEF 1 "$Date: 2010-08-11 04:06:42 $" "" "MINC User's Guide" .SH NAME xfm2def \- convert a MNI transform file to a deformation volume .SH SYNOPSIS \fBxfm2def\fR\ [options] \fIinput.xfm\fR\ \fIdef_vol.mnc\fR .SH DESCRIPTION \fIxfm2def\fR takes an input transform \fIinput.xfm\fR that can consist of a series of concatenated transforms in a single xfm file and converts this into a single deformation volume that is output as \fIdef_vol.mnc\fR. Note that the output is not a tranform file itself, you can then make use of this volume in a MINC tranform by creating an .xfm file as such: MNI Transform File Transform_Type = Grid_Transform; Displacement_Volume = def_vol.mnc; The output resolution and sampling of the deformation grid must be specified or a default size will be used. (100x100x100 1mm steps centred around the origin). .SH OPTIONS .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .TP \fB\-verbose\fR Print out extra progress information while running. .TP \fB\-clobber\fR Overwrite any existing output file .TP \fB\-xnelements\fR\ \fInx\fR Number of elements along the xspace dimension. .TP \fB\-ynelements\fR\ \fIny\fR Number of elements along the yspace dimension. .TP \fB\-znelements\fR\ \fInz\fR Number of elements along the zspace dimension. .TP \fB\-xstep\fR\ \fIxstep\fR Step between voxels along the xspace dimension. .TP \fB\-ystep\fR\ \fIystep\fR Step between voxels along the yspace dimension. .TP \fB\-zstep\fR\ \fIzstep\fR Step between voxels along the zspace dimension. .TP \fB\-xstart\fR\ \fIxstart\fR Position of centre of first voxel along the xspace dimension. .TP \fB\-ystart\fR\ \fIystart\fR Position of centre of first voxel along the yspace dimension. .TP \fB\-zstart\fR\ \fIzstart\fR Position of centre of first voxel along the zspace dimension. .TP \fB\-xdircos\fR\ \fIx1\ x2\ x3\fR Direction cosines for the xspace dimension. .TP \fB\-ydircos\fR\ \fIy1\ y2\ y3\fR Direction cosines for the yspace dimension. .TP \fB\-zdircos\fR\ \fIz1\ z2\ z3\fR Direction cosines for the zspace dimension. .SH AUTHOR Andrew Janke .SH COPYRIGHTS Copyright \(co 2010 Andrew Janke - a.janke@gmail.com minc-2.2.00/progs/xfm/xfmconcat.man10000644000265600003100000000146112027132663014127 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH XFMCONCAT 1 "$Date: 2008-09-04 03:20:16 $" "" "MINC User's Guide" .SH NAME xfmconcat \- concatenate MNI transform files .SH SYNOPSIS \fBxfmconcat\fR\ \fIinput1.xfm\fR [ \fIinput2.xfm\fR... ] \fIresult.xfm\fR .SH DESCRIPTION \fIxfmconcat\fR concatenates a number of transforms together. The resulting transformation will have the effect of applying transformation \fIinput1.xfm\fR then \fIinput2.xfm\fR, etc., in that order. .SH OPTIONS .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-verbose\fR Print out progress information. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 Peter Neelin minc-2.2.00/progs/xfm/xfminvert.man10000644000265600003100000000127212027132663014167 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH XFMINVERT 1 "$Date: 2008-09-04 03:20:16 $" "" "MINC User's Guide" .SH NAME xfminvert \- invert an MNI transform file .SH SYNOPSIS \fBxfminvert\fR\ \fIinput.xfm\fR\ \fIresult.xfm\fR .SH DESCRIPTION \fIxfminvert\fR creates the file \fIresult.xfm\fR containing the inverse transformation of \fIinput.xfm\fR. .SH OPTIONS .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-clobber\fR Overwrite an existing file. .TP \fB\-verbose\fR Print out progress information. .TP \fB\-version\fR Print the program's version number and exit. .SH AUTHOR Peter Neelin .SH COPYRIGHTS Copyright \(co 1993 Peter Neelin minc-2.2.00/progs/xfm/xfmflip.man10000644000265600003100000000170012027132663013606 00000000000000.\" Hey, EMACS: -*- nroff -*- .TH XFMFLIP 1 "$Date: 2007-08-24 04:05:44 $" "" "MINC User's Guide" .SH NAME xfmflip \- flip an MNI transform file .SH SYNOPSIS \fBxfmflip\fR\ \fIin.xfm\fR\ \fIout.xfm\fR .SH DESCRIPTION \fIxfmflip\fR flips an input transform \fIinput.xfm\fR about an axis (x, y or z) and puts the result in the file \fIresult.xfm\fR. The default flip is about the X axis (Left-Right) but can be changed to the Y axis (via the -y option) or Z axis (-z) .SH OPTIONS .TP \fB\-help\fR Print summary of command-line options and exit. .TP \fB\-version\fR Print the program's version number and exit. .TP \fB\-verbose\fR Print out extra progress information while running. .TP \fB\-clobber\fR Overwrite any existing output file .TP \fB\-fake\fR Dont actually run the commands, just echo them to STDOUT .SH AUTHOR Andrew Janke Vladimir Fonov .SH COPYRIGHTS Copyright \(co 2007 Andrew Janke - a.janke@gmail.com minc-2.2.00/progs/xfm/xfmflip.in0000755000265600003100000000703612027132663013373 00000000000000#! /usr/bin/env perl # # Andrew Janke - a.janke@gmail.com # # Copyright Andrew Janke, The University of Queensland. # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies. # The author and the University make no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Flips an xfm in the given direction use strict; use warnings "all"; use Getopt::Tabular; use File::Basename; use File::Temp qw/ tempdir /; my($Help, $Usage, $me, @opt_table, $tmpdir, $history, %opt); my(@args, $inxfm, $outxfm); # Argument variables and table $me = &basename($0); $tmpdir = "/tmp/$me-$$"; %opt = ( 'verbose' => 0, 'clobber' => 0, 'fake' => 0, 'todo' => 0, ); $Help = < 1, CLEANUP => 1 ); my @flips = ( [-1, 1, 1], [ 1, -1, 1], [ 1, 1, -1] ); # generate a temporary flip xfm &do_cmd('param2xfm', '-clobber', '-center', 0, 0, 0, '-scales', @{$flips[$opt{todo}]}, "$tmpdir/flip.xfm"); # create the flip xfm &do_cmd('xfmconcat', "$tmpdir/flip.xfm", $inxfm, "$tmpdir/flip.xfm", $outxfm); # do the dogy and add a history string (this may well bite me later on) my @buf = split("\n", `cat $outxfm`); open(FH, ">$outxfm"); print FH shift(@buf) . "\n" . "%\n" . "% Created by $me\n" . "%\n" . "% $history \n" . "\n" . join("\n", @buf) . "\n"; close(FH); sub do_cmd { print STDOUT "@_\n" if $opt{verbose}; if(!$opt{fake}){ system(@_) == 0 or die; } } sub print_version_info { my($package, $version, $package_bugreport); $package = '@PACKAGE@'; $version = '@VERSION@'; $package_bugreport = '@PACKAGE_BUGREPORT@'; print STDOUT "\n$package version $version\n". "Comments to $package_bugreport\n\n"; exit; } minc-2.2.00/progs/xfm/transformtags.c0000644000265600003100000001336612027132663014434 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : transformtags.c @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to transform a tag file using a transform file @METHOD : @GLOBALS : @CALLS : @CREATED : September 13, 1993 (Peter Neelin) @MODIFIED : * $Log: transformtags.c,v $ * Revision 6.4 2008-01-17 02:33:06 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.3 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.2 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.1 1999/10/19 14:45:31 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:28 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:29 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:08 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:03 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:33:24 neelin * Release of minc version 0.2 * * Revision 1.5 94/09/28 10:33:21 neelin * Pre-release * * Revision 1.4 93/10/12 12:52:16 neelin * Replaced def_mni.h with volume_io.h * * Revision 1.3 93/09/16 09:39:00 neelin * Use dave's open_file_with_default_suffix and input_transform_file and * output_transform_file to add suffixes to file names. * * Revision 1.2 93/09/14 09:50:20 neelin * changed name to from tagtransform to transformtags * * Revision 1.1 93/09/13 16:16:55 neelin * Initial revision * ---------------------------------------------------------------------------- */ #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Variables for argument parsing */ int volume_to_transform = 2; char *xfmfile = NULL; /* Argument table */ ArgvInfo argTable[] = { {"-vol1", ARGV_CONSTANT, (char *) 1, (char *) &volume_to_transform, "Transform tags for volume 1."}, {"-vol2", ARGV_CONSTANT, (char *) 2, (char *) &volume_to_transform, "Transform tags for volume 2 (default)."}, {"-transformation", ARGV_STRING, (char *) NULL, (char *) &xfmfile, "Name of transformation file (default = identity)."}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]) { char *pname, *intagfile, *outtagfile; int n_volumes, n_tag_points, ipoint; Real **tags_volume1, **tags_volume2, **tag_list; General_transform transform; FILE *fp; char comment_string[512]; char *comment = comment_string; Real *weights; int *structure_ids; int *patient_ids; char **labels; /* Parse arguments */ pname = argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || (argc != 3)) { (void) fprintf(stderr, "\nUsage: %s [] infile.tag outfile.tag\n\n", argv[0]); exit(EXIT_FAILURE); } intagfile = argv[1]; outtagfile = argv[2]; /* Read in tag file */ if ((open_file_with_default_suffix(intagfile, get_default_tag_file_suffix(), READ_FILE, ASCII_FORMAT, &fp) != OK) || (input_tag_points(fp, &n_volumes, &n_tag_points, &tags_volume1, &tags_volume2, &weights, &structure_ids, &patient_ids, &labels) != OK)) { (void) fprintf(stderr, "%s: Error reading tag file %s\n", pname, intagfile); exit(EXIT_FAILURE); } (void) close_file(fp); /* Check number of volumes */ if (n_volumes > 2) { (void) fprintf(stderr, "%s: Wrong number of volumes in %s\n", pname, intagfile); exit(EXIT_FAILURE); } /* Get the list of tags to transform */ if (n_volumes == 1) volume_to_transform = 1; if (volume_to_transform == 1) { tag_list = tags_volume1; } else { tag_list = tags_volume2; } /* Get the transform */ if (xfmfile == NULL) { create_linear_transform(&transform, NULL); } else { if (input_transform_file(xfmfile, &transform) != OK) { (void) fprintf(stderr, "%s: Error reading transform file %s\n", pname, xfmfile); exit(EXIT_FAILURE); } } /* Transform the points */ for (ipoint=0; ipoint < n_tag_points; ipoint++) { general_transform_point(&transform, tag_list[ipoint][0], tag_list[ipoint][1], tag_list[ipoint][2], &tag_list[ipoint][0], &tag_list[ipoint][1], &tag_list[ipoint][2]); } /* Create a comment for the new file */ if (xfmfile != NULL) { (void) sprintf(comment, " Volume %d points transformed using xfm file %s", volume_to_transform, xfmfile); } else { comment = NULL; } /* Write out the new tag file */ if ((open_file_with_default_suffix(outtagfile, get_default_tag_file_suffix(), WRITE_FILE, ASCII_FORMAT, &fp) != OK) || (output_tag_points(fp, comment, n_volumes, n_tag_points, tags_volume1, tags_volume2, weights, structure_ids, patient_ids, labels) != OK)) { (void) fprintf(stderr, "%s: Error writing new tag file %s\n", pname, outtagfile); exit(EXIT_FAILURE); } (void) close_file(fp); exit(EXIT_SUCCESS); } minc-2.2.00/progs/xfm/xfm2def.c0000644000265600003100000001546512027132663013077 00000000000000/* * xfm2def.c * * Approximates a deformation grid from an input transformation * * Copyright Andrew Janke - a.janke@gmail.com * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies. The * author makes no representations about the suitability of this software for * any purpose. It is provided "as is" without express or implied warranty. */ #include #include #include #include #include #include #include #define WORLD_NDIMS 3 #define DEF_BOOL -1 static char *std_dimorder_v[] = { MIxspace, MIyspace, MIzspace, MIvector_dimension }; /* argument variables and table */ static int verbose = FALSE; static int clobber = FALSE; static nc_type dtype = NC_SHORT; static int is_signed = FALSE; static int nelem[WORLD_NDIMS + 1] = { 100, 100, 100, 3 }; static double start[WORLD_NDIMS] = { -50.0, -50.0, -50.0 }; static double step[WORLD_NDIMS] = { 1.0, 1.0, 1.0 }; static double dircos[WORLD_NDIMS][WORLD_NDIMS] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} }; static ArgvInfo argTable[] = { {"-verbose", ARGV_CONSTANT, (char *)TRUE, (char *)&verbose, "Print out extra information."}, {"-clobber", ARGV_CONSTANT, (char *)TRUE, (char *)&clobber, "Overwrite existing files."}, {NULL, ARGV_HELP, NULL, NULL, "\nOuput grid Options"}, {"-byte", ARGV_CONSTANT, (char *)NC_BYTE, (char *)&dtype, "Create a byte data."}, {"-short", ARGV_CONSTANT, (char *)NC_SHORT, (char *)&dtype, "Create a short integer data.(Default)"}, {"-int", ARGV_CONSTANT, (char *)NC_INT, (char *)&dtype, "Create a 32-bit integer"}, {"-float", ARGV_CONSTANT, (char *)NC_FLOAT, (char *)&dtype, "Create a single-precision data."}, {"-double", ARGV_CONSTANT, (char *)NC_DOUBLE, (char *)&dtype, "Create a double-precision data."}, {"-signed", ARGV_CONSTANT, (char *)TRUE, (char *)&is_signed, "Create a signed integer data."}, {"-unsigned", ARGV_CONSTANT, (char *)FALSE, (char *)&is_signed, "Create a unsigned integer data. (Default)"}, {"-xnelements", ARGV_INT, (char *)1, (char *)&nelem[0], "Number of samples in x dimension."}, {"-ynelements", ARGV_INT, (char *)1, (char *)&nelem[1], "Number of samples in y dimension."}, {"-znelements", ARGV_INT, (char *)1, (char *)&nelem[2], "Number of samples in z dimension."}, {"-xstart", ARGV_FLOAT, (char *)1, (char *)&start[0], "Starting coordinate for x dimension."}, {"-ystart", ARGV_FLOAT, (char *)1, (char *)&start[1], "Starting coordinate for y dimension."}, {"-zstart", ARGV_FLOAT, (char *)1, (char *)&start[2], "Starting coordinate for z dimension."}, {"-xstep", ARGV_FLOAT, (char *)1, (char *)&step[0], "Step size for x dimension."}, {"-ystep", ARGV_FLOAT, (char *)1, (char *)&step[1], "Step size for y dimension."}, {"-zstep", ARGV_FLOAT, (char *)1, (char *)&step[2], "Step size for z dimension."}, {"-xdircos", ARGV_FLOAT, (char *)3, (char *)dircos[0], "Direction cosines along the x dimension"}, {"-ydircos", ARGV_FLOAT, (char *)3, (char *)dircos[1], "Direction cosines along the y dimension"}, {"-zdircos", ARGV_FLOAT, (char *)3, (char *)dircos[2], "Direction cosines along the z dimension"}, {NULL, ARGV_HELP, NULL, NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main(int argc, char *argv[]) { char *xfm_fn; char *out_fn; char *history; progress_struct progress; Volume def_grid; General_transform xfm; int x, y, z, v; double vcoord[4], wcoord[3], wcoord_t[3]; double min, max; double value; int i; /* get the history string */ history = time_stamp(argc, argv); /* get args and file names */ if(ParseArgv(&argc, argv, argTable, 0) || (argc != 3)){ fprintf(stderr, "\nUsage: %s [options] \n", argv[0]); fprintf(stderr, " %s [-help] %d\n\n", argv[0], argc); exit(EXIT_FAILURE); } xfm_fn = argv[1]; out_fn = argv[2]; /* check for infile and outfile */ if(access(xfm_fn, F_OK) != 0){ fprintf(stderr, "%s: Couldn't find input xfm %s.\n\n", argv[0], xfm_fn); exit(EXIT_FAILURE); } if(access(out_fn, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists, -clobber to overwrite.\n\n", argv[0], out_fn); exit(EXIT_FAILURE); } /* read in the input transformation */ if(input_transform_file(xfm_fn, &xfm) != OK){ fprintf(stderr, "%s: Error reading in xfm %s\n\n", argv[0], xfm_fn); } /* create the def_grid volume */ def_grid = create_volume(4, std_dimorder_v, dtype, is_signed, 0.0, 0.0); set_volume_sizes(def_grid, nelem); set_volume_starts(def_grid, start); set_volume_separations(def_grid, step); for(i = 0; i < WORLD_NDIMS; i++){ set_volume_direction_cosine(def_grid, i, dircos[i]); } alloc_volume_data(def_grid); /* generate the grid itself */ min = DBL_MAX; max = -DBL_MAX; vcoord[3] = 0; initialize_progress_report(&progress, FALSE, nelem[0], "Creating grid"); for(x = nelem[0]; x--;){ for(y = nelem[1]; y--;){ for(z = nelem[2]; z--;){ /* figure out where we are in world space */ vcoord[0] = x; vcoord[1] = y; vcoord[2] = z; convert_voxel_to_world(def_grid, vcoord, &wcoord[0], &wcoord[1], &wcoord[2]); /* transform that */ general_transform_point(&xfm, wcoord[0], wcoord[1], wcoord[2], &wcoord_t[0], &wcoord_t[1], &wcoord_t[2]); /* write out dx, dy and dz */ for(v = nelem[3]; v--;){ value = wcoord_t[v] - wcoord[v]; if(value < min){ min = value; } if(value > max){ max = value; } set_volume_real_value(def_grid, x, y, z, v, 0, value); } } } update_progress_report(&progress, x + 1); } terminate_progress_report(&progress); /* set the range */ if(verbose){ fprintf(stdout, " + data range: [%g:%g]\n", min, max); } set_volume_real_range(def_grid, min, max); /* output the result */ if(verbose){ fprintf(stdout, "Outputting %s...\n", out_fn); } if(output_volume(out_fn, dtype, is_signed, 0.0, 0.0, def_grid, history, NULL) != OK){ fprintf(stderr, "Problems outputing: %s\n\n", out_fn); exit(EXIT_FAILURE); } /* tidy up */ delete_volume(def_grid); delete_general_transform(&xfm); return (EXIT_SUCCESS); } minc-2.2.00/progs/xfm/xfmconcat.c0000644000265600003100000001311212027132663013511 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : xfmconcat @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to concatenate MNI transform files @METHOD : @GLOBALS : @CALLS : @CREATED : August 13, 1993 (Peter Neelin) @MODIFIED : * $Log: xfmconcat.c,v $ * Revision 6.7 2008-09-04 03:20:16 rotor * * added -clobber option to xfmconcat and readied for 2.0.16 release * * Revision 6.6 2008/01/23 22:54:35 rotor * * added Claude to AUTHORS * * added a patch for history to xfmconcat from Mishkin Derakhshan * * Revision 6.5 2008/01/17 02:33:06 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.4 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.3 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.2 2004/02/02 18:24:11 bert * Call ParseArgv() so that version information will be available * * Revision 6.1 1999/10/19 14:45:32 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:28 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:29 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:08 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:03 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:33:25 neelin * Release of minc version 0.2 * * Revision 1.5 94/09/28 10:33:20 neelin * Pre-release * * Revision 1.4 93/10/12 12:52:35 neelin * Replaced def_mni.h with volume_io.h * * Revision 1.3 93/09/16 09:40:21 neelin * Use dave's open_file_with_default_suffix and input_transform_file and * output_transform_file to add suffixes to file names. * * Revision 1.2 93/09/01 15:58:49 neelin * Cast return of fclose to (void). * * Revision 1.1 93/08/13 15:27:18 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Argument variables */ int clobber = FALSE; int verbose = FALSE; /* Argument table */ ArgvInfo argTable[] = { {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out extra information."}, {NULL, ARGV_HELP, NULL, NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]){ General_transform trans1, trans2, trans3; General_transform *new_result, *old_result, *input, *temp_result; int iarg, first_arg, last_arg; char *outfile; char *arg_string; char *pname; /* collect the command line for history */ arg_string = time_stamp(argc, argv); /* Check arguments */ pname = argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || argc < 3) { (void) fprintf(stderr, "Usage: %s [ ...] \n", pname); (void) fprintf(stderr, " %s -help\n\n", pname); exit(EXIT_FAILURE); } /* Set up pointers and indices of first and last files to concat */ new_result = &trans1; old_result = &trans2; input = &trans3; first_arg = 1; last_arg = argc-2; outfile = argv[argc-1]; /* check for the outfile */ if(access(outfile, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists! (use -clobber to overwrite)\n\n", pname, outfile); exit(EXIT_FAILURE); } /* Loop through arguments */ for (iarg=first_arg; iarg <= last_arg; iarg++) { /* Read in file to concatenate */ if (input_transform_file(argv[iarg], input) != OK) { (void) fprintf(stderr, "%s: Error reading transform file %s\n", pname, argv[iarg]); exit(EXIT_FAILURE); } /* Concatenate the transform */ temp_result = new_result; new_result = old_result; old_result = temp_result; if (iarg == first_arg) { copy_general_transform(input, new_result); } else { concat_general_transforms(old_result, input, new_result); delete_general_transform(old_result); } delete_general_transform(input); } /* End of loop through arguments */ /* Write out the transform */ if (output_transform_file(outfile, arg_string, new_result) != OK) { (void) fprintf(stderr, "%s: Error writing transform file %s\n", pname, outfile); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } minc-2.2.00/progs/xfm/xfminvert.c0000644000265600003100000001213012027132663013550 00000000000000/* ----------------------------- MNI Header ----------------------------------- @NAME : xfminvert @INPUT : argc, argv - command line arguments @OUTPUT : (none) @RETURNS : status @DESCRIPTION: Program to invert an MNI transform file @METHOD : @GLOBALS : @CALLS : @CREATED : August 13, 1993 (Peter Neelin) @MODIFIED : * $Log: xfminvert.c,v $ * Revision 6.6 2008-01-17 02:33:06 rotor * * removed all rcsids * * removed a bunch of ^L's that somehow crept in * * removed old (and outdated) BUGS file * * Revision 6.5 2008/01/12 19:08:15 stever * Add __attribute__ ((unused)) to all rcsid variables. * * Revision 6.4 2007/08/10 11:55:35 rotor * * added -clobber and -verbose to xfminvert to get it up to scratch * * a bit of code cleanup (not there there is much in there!) * * Revision 6.3 2004/11/01 22:38:39 bert * Eliminate all references to minc_def.h * * Revision 6.2 2004/02/02 18:24:11 bert * Call ParseArgv() so that version information will be available * * Revision 6.1 1999/10/19 14:45:32 neelin * Fixed Log subsitutions for CVS * * Revision 6.0 1997/09/12 13:23:28 neelin * Release of minc version 0.6 * * Revision 5.0 1997/08/21 13:24:29 neelin * Release of minc version 0.5 * * Revision 4.0 1997/05/07 20:00:08 neelin * Release of minc version 0.4 * * Revision 3.0 1995/05/15 19:31:03 neelin * Release of minc version 0.3 * * Revision 2.0 1994/09/28 10:33:26 neelin * Release of minc version 0.2 * * Revision 1.5 94/09/28 10:33:20 neelin * Pre-release * * Revision 1.4 93/10/12 12:52:37 neelin * Replaced def_mni.h with volume_io.h * * Revision 1.3 93/09/16 09:40:24 neelin * Use dave's open_file_with_default_suffix and input_transform_file and * output_transform_file to add suffixes to file names. * * Revision 1.2 93/09/01 15:59:05 neelin * Cast return of fclose to (void). * * Revision 1.1 93/08/13 15:26:53 neelin * Initial revision * @COPYRIGHT : Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include /* Constants */ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif /* Argument variables */ int clobber = FALSE; int verbose = FALSE; /* Argument table */ ArgvInfo argTable[] = { {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, "Overwrite existing file."}, {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, "Don't overwrite existing file (default)."}, {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, "Print out extra information."}, {NULL, ARGV_HELP, NULL, NULL, ""}, {NULL, ARGV_END, NULL, NULL, NULL} }; /* Main program */ int main(int argc, char *argv[]){ General_transform transform, inverse; char *arg_string; char *pname; char *infile; char *outfile; /* Save time stamp and args */ arg_string = time_stamp(argc, argv); /* Check arguments */ pname = argv[0]; if (ParseArgv(&argc, argv, argTable, 0) || argc != 3) { (void) fprintf(stderr, "\nUsage: %s [options] \n", pname); (void) fprintf(stderr, " %s -help\n\n", pname); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /* check for the infile */ if(access(infile, F_OK) != 0){ fprintf(stderr, "%s: Couldn't find %s\n\n", pname, infile); exit(EXIT_FAILURE); } /* check for the outfile */ if(access(outfile, F_OK) == 0 && !clobber){ fprintf(stderr, "%s: %s exists! (use -clobber to overwrite)\n\n", pname, outfile); exit(EXIT_FAILURE); } /* Read in file to invert */ if (input_transform_file(infile, &transform) != OK) { (void) fprintf(stderr, "%s: Error reading transform file %s\n", pname, infile); exit(EXIT_FAILURE); } /* Invert the transform */ create_inverse_general_transform(&transform, &inverse); if(verbose){ (void) fprintf(stdout, "[%s]: Inverted %s\n", pname, infile); } /* Write out the transform */ if (output_transform_file(outfile, arg_string, &inverse) != OK) { (void) fprintf(stderr, "%s: Error writing transform file %s\n", pname, outfile); exit(EXIT_FAILURE); } if(verbose){ (void) fprintf(stdout, "[%s]: Wrote out %s\n", pname, outfile); } exit(EXIT_SUCCESS); } minc-2.2.00/progs/CMakeLists.txt0000644000265600003100000001507012030075003013322 00000000000000# CMakeFiles.txt for the MINC2 progs # # Andrew Janke - a.janke@gmail.com INCLUDE_DIRECTORIES(Proglib) LINK_LIBRARIES( ${MINC2_LIBRARIES} ) ADD_DEFINITIONS(-DHAVE_CONFIG_H) IF(NOT MINC2_EXTERNALLY_CONFIGURED) FIND_PACKAGE(BISON) FIND_PACKAGE(FLEX) ENDIF(NOT MINC2_EXTERNALLY_CONFIGURED) # all the progs ADD_EXECUTABLE(invert_raw_image mincview/invert_raw_image.c) ADD_EXECUTABLE(mincaverage mincaverage/mincaverage.c) TARGET_LINK_LIBRARIES(mincaverage m) IF(BISON_FOUND AND FLEX_FOUND) include_directories(${CMAKE_CURRENT_BINARY_DIR} minccalc) BISON_TARGET(gram ${CMAKE_CURRENT_SOURCE_DIR}/minccalc/gram.y ${CMAKE_CURRENT_BINARY_DIR}/gram.c COMPILE_FLAGS "--debug") FLEX_TARGET(lex ${CMAKE_CURRENT_SOURCE_DIR}/minccalc/lex.l ${CMAKE_CURRENT_BINARY_DIR}/lex.c ) #ADD_FLEX_BISON_DEPENDENCY(gram lex) ADD_EXECUTABLE(minccalc minccalc/minccalc.c minccalc/eval.c minccalc/ident.c minccalc/node.c minccalc/optim.c minccalc/scalar.c minccalc/sym.c minccalc/vector.c ${FLEX_lex_OUTPUTS} ${BISON_gram_OUTPUTS} ) TARGET_LINK_LIBRARIES(minccalc ${FLEX_LIBRARIES} m) INSTALL( TARGETS minccalc DESTINATION bin) include_directories(${CMAKE_CURRENT_BINARY_DIR} mincgen) BISON_TARGET(ncgentab ${CMAKE_CURRENT_SOURCE_DIR}/mincgen/ncgentab.y ${CMAKE_CURRENT_BINARY_DIR}/ncgentab.c) FLEX_TARGET(ncgenyy ${CMAKE_CURRENT_SOURCE_DIR}/mincgen/ncgenyy.l ${CMAKE_CURRENT_BINARY_DIR}/ncgenyy.c) ADD_EXECUTABLE(mincgen mincgen/main.c ${BISON_ncgentab_OUTPUTS} ${FLEX_ncgenyy_OUTPUTS} mincgen/escapes.c mincgen/genlib.c mincgen/getfill.c mincgen/init.c mincgen/load.c) INSTALL( TARGETS mincgen DESTINATION bin) TARGET_LINK_LIBRARIES(mincgen ${FLEX_LIBRARIES}) ENDIF(BISON_FOUND AND FLEX_FOUND) ADD_EXECUTABLE(mincconcat mincconcat/mincconcat.c) ADD_EXECUTABLE(mincconvert mincconvert/mincconvert.c) ADD_EXECUTABLE(minccopy minccopy/minccopy.c) ADD_EXECUTABLE(mincdump mincdump/mincdump.c mincdump/vardata.c mincdump/dumplib.c) ADD_EXECUTABLE(mincexample1 mincexample/mincexample1.c) ADD_EXECUTABLE(mincexample2 mincexample/mincexample2.c) ADD_EXECUTABLE(mincexpand mincexpand/mincexpand.c) ADD_EXECUTABLE(mincextract mincextract/mincextract.c) ADD_EXECUTABLE(mincinfo mincinfo/mincinfo.c) ADD_EXECUTABLE(minclookup minclookup/minclookup.c) TARGET_LINK_LIBRARIES(minclookup m) ADD_EXECUTABLE(mincmakescalar mincmakescalar/mincmakescalar.c) TARGET_LINK_LIBRARIES(mincmakescalar m) ADD_EXECUTABLE(mincmakevector mincmakevector/mincmakevector.c) ADD_EXECUTABLE(mincmath mincmath/mincmath.c) TARGET_LINK_LIBRARIES(mincmath m) ADD_EXECUTABLE(minc_modify_header minc_modify_header/minc_modify_header.c) ADD_EXECUTABLE(mincresample mincresample/mincresample.c mincresample/resample_volumes.c Proglib/convert_origin_to_start.c) TARGET_LINK_LIBRARIES(mincresample ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(mincreshape mincreshape/mincreshape.c mincreshape/copy_data.c) ADD_EXECUTABLE(mincstats mincstats/mincstats.c) TARGET_LINK_LIBRARIES(mincstats m) ADD_EXECUTABLE(minctoraw minctoraw/minctoraw.c) ADD_EXECUTABLE(mincwindow mincwindow/mincwindow.c) ADD_EXECUTABLE(mincmorph mincmorph/mincmorph.c mincmorph/kernel_io.c mincmorph/kernel_ops.c mincmorph/kernel_io.h mincmorph/kernel_ops.h ) TARGET_LINK_LIBRARIES(mincmorph ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(mincsample mincsample/mincsample.c mincsample/mt19937ar.c mincsample/mt19937ar.h ) TARGET_LINK_LIBRARIES(mincsample ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(rawtominc rawtominc/rawtominc.c Proglib/convert_origin_to_start.c) TARGET_LINK_LIBRARIES(rawtominc m) ADD_EXECUTABLE(voxeltoworld coordinates/voxeltoworld.c) TARGET_LINK_LIBRARIES(voxeltoworld ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(worldtovoxel coordinates/worldtovoxel.c) TARGET_LINK_LIBRARIES(worldtovoxel ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(transformtags xfm/transformtags.c) TARGET_LINK_LIBRARIES(transformtags ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(xfmconcat xfm/xfmconcat.c) TARGET_LINK_LIBRARIES(xfmconcat ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(xfminvert xfm/xfminvert.c) TARGET_LINK_LIBRARIES(xfminvert ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) ADD_EXECUTABLE(mincblob mincblob/mincblob.c) TARGET_LINK_LIBRARIES(mincblob ${VOLUME_IO_LIBRARY} ${MINC2_LIBRARIES} m) # install progs INSTALL(TARGETS invert_raw_image mincaverage mincconcat mincconvert minccopy mincdump # mincexample1 # mincexample2 mincblob mincexpand mincextract mincinfo minclookup mincmakescalar mincmakevector mincmath minc_modify_header mincresample mincreshape mincstats minctoraw mincwindow mincmorph mincsample rawtominc voxeltoworld worldtovoxel transformtags xfmconcat xfminvert DESTINATION bin) # perl and shell scripts INSTALL(PROGRAMS mincdiff/mincdiff mincedit/mincedit mincheader/mincheader mincview/mincview PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION bin ) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/minchistory/minchistory.in ${CMAKE_CURRENT_BINARY_DIR}/minchistory @ONLY) add_custom_target(minchistory chmod +x ${CMAKE_CURRENT_BINARY_DIR}/minchistory DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/minchistory/minchistory.in) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mincpik/mincpik.in ${CMAKE_CURRENT_BINARY_DIR}/mincpik @ONLY) add_custom_target(mincpik chmod +x ${CMAKE_CURRENT_BINARY_DIR}/mincpik DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/mincpik/mincpik.in) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/minchistory PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION bin ) INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/mincpik PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION bin ) minc-2.2.00/volume_io/0000755000265600003100000000000012030114724011507 500000000000000minc-2.2.00/volume_io/Geometry/0000755000265600003100000000000012030114722013300 500000000000000minc-2.2.00/volume_io/Geometry/colour.c0000644000265600003100000001234212027132663014703 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : make_Colour @INPUT : r g b @OUTPUT : @RETURNS : Colour @DESCRIPTION: Packs the three components, which are in the range 0 to 255, into a Colour type, unsigned long. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Colour make_Colour( int r, int g, int b ) { return( make_rgba_Colour( r, g, b, 255 ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_r_0_1 @INPUT : colour @OUTPUT : @RETURNS : red component @DESCRIPTION: Returns the red component of the colour in the range of 0.0 to 1.0 @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_Colour_r_0_1( Colour colour ) { return( (Real) get_Colour_r(colour) / 255.0 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_g_0_1 @INPUT : colour @OUTPUT : @RETURNS : green component @DESCRIPTION: Returns the green component of the colour in the range of 0.0 to 1.0 @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_Colour_g_0_1( Colour colour ) { return( (Real) get_Colour_g(colour) / 255.0 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_b_0_1 @INPUT : colour @OUTPUT : @RETURNS : blue component @DESCRIPTION: Returns the blue component of the colour in the range of 0.0 to 1.0 @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_Colour_b_0_1( Colour colour ) { return( (Real) get_Colour_b(colour) / 255.0 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_a_0_1 @INPUT : colour @OUTPUT : @RETURNS : alpha component @DESCRIPTION: Returns the alpha (opacity) component of the colour in the range of 0.0 to 1.0 @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_Colour_a_0_1( Colour colour ) { return( (Real) get_Colour_a(colour) / 255.0 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : make_Colour_0_1 @INPUT : r g b @OUTPUT : @RETURNS : Colour @DESCRIPTION: Takes the three components, each in the range of 0 to 1, and packs them into a colour. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Colour make_Colour_0_1( Real r, Real g, Real b ) { return( make_Colour( (int) (r * 255.0 + 0.5), (int) (g * 255.0 + 0.5), (int) (b * 255.0 + 0.5) ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : make_rgba_Colour_0_1 @INPUT : r g b a - alpha (opacity) @OUTPUT : @RETURNS : Colour @DESCRIPTION: Takes the four components, each in the range of 0 to 1, and packs them into a colour. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Colour make_rgba_Colour_0_1( Real r, Real g, Real b, Real a ) { return( make_rgba_Colour( (int) (r * 255.0 + 0.5), (int) (g * 255.0 + 0.5), (int) (b * 255.0 + 0.5), (int) (a * 255.0 + 0.5) ) ); } minc-2.2.00/volume_io/Geometry/colour_def.c0000644000265600003100000001063112027132663015520 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : make_rgba_Colour @INPUT : r g b a @OUTPUT : @RETURNS : Colour @DESCRIPTION: Packs the four components into a colour. Each component must be in the range 0 to 255. Depending on what graphics library is being linked with, if any, for instance, GL or OpenGL, this library function may be overridden by another to define the correct method of packing bytes into a colour. If no graphics are involved, then the byte order does not matter and the code here can be used. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Colour make_rgba_Colour( int r, int g, int b, int a ) { Colour c; unsigned char *byte_ptr; c = 0; /* to avoid used-before-set compiler messages */ ASSIGN_PTR(byte_ptr) = (void *) &c; byte_ptr[0] = (unsigned char) a; byte_ptr[1] = (unsigned char) b; byte_ptr[2] = (unsigned char) g; byte_ptr[3] = (unsigned char) r; return( c ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_r @INPUT : colour @OUTPUT : @RETURNS : red component @DESCRIPTION: Returns the red component of the colour in the range 0 to 255. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_Colour_r( Colour colour ) { unsigned char *b; ASSIGN_PTR(b) = (void *) &colour; return( (int) b[3] ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_g @INPUT : colour @OUTPUT : @RETURNS : green component @DESCRIPTION: Returns the green component of the colour in the range 0 to 255. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_Colour_g( Colour colour ) { unsigned char *b; ASSIGN_PTR(b) = (void *) &colour; return( (int) b[2] ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_b @INPUT : colour @OUTPUT : @RETURNS : blue component @DESCRIPTION: Returns the blue component of the colour in the range 0 to 255. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_Colour_b( Colour colour ) { unsigned char *b; ASSIGN_PTR(b) = (void *) &colour; return( (int) b[1] ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_Colour_a @INPUT : colour @OUTPUT : @RETURNS : alpha component @DESCRIPTION: Returns the alpha (opacity) component of the colour in the range 0 to 255. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_Colour_a( Colour colour ) { unsigned char *b; ASSIGN_PTR(b) = (void *) &colour; return( (int) b[0] ); } minc-2.2.00/volume_io/Geometry/gaussian.c0000644000265600003100000001710212027132663015211 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : scaled_maximal_pivoting_gaussian_elimination @INPUT : n size of matrix, n by n a matrix n_values number of values to solve for @OUTPUT : row permutation array filled in by this function solution on input, the values, on output the solution, size n by n_values @RETURNS : TRUE if successful @DESCRIPTION: Performs scaled maximal pivoting gaussian elimination as a numerically robust method to solve systems of linear equations. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN scaled_maximal_pivoting_gaussian_elimination( int n, int row[], Real **a, int n_values, Real **solution ) { int i, j, k, p, v, tmp; Real *s, val, best_val, m, scale_factor; BOOLEAN success; ALLOC( s, n ); for_less( i, 0, n ) row[i] = i; for_less( i, 0, n ) { s[i] = FABS( a[i][0] ); for_less( j, 1, n ) { if( FABS(a[i][j]) > s[i] ) s[i] = FABS(a[i][j]); } if( s[i] == 0.0 ) { FREE( s ); return( FALSE ); } } success = TRUE; for_less( i, 0, n-1 ) { p = i; best_val = a[row[i]][i] / s[row[i]]; best_val = FABS( best_val ); for_less( j, i+1, n ) { val = a[row[j]][i] / s[row[j]]; val = FABS( val ); if( val > best_val ) { best_val = val; p = j; } } if( a[row[p]][i] == 0.0 ) { success = FALSE; break; } if( i != p ) { tmp = row[i]; row[i] = row[p]; row[p] = tmp; } for_less( j, i+1, n ) { if( a[row[i]][i] == 0.0 ) { success = FALSE; break; } m = a[row[j]][i] / a[row[i]][i]; for_less( k, i+1, n ) a[row[j]][k] -= m * a[row[i]][k]; for_less( v, 0, n_values ) solution[row[j]][v] -= m * solution[row[i]][v]; } if( !success ) break; } if( success && a[row[n-1]][n-1] == 0.0 ) success = FALSE; if( success ) { for( i = n-1; i >= 0; --i ) { for_less( j, i+1, n ) { scale_factor = a[row[i]][j]; for_less( v, 0, n_values ) solution[row[i]][v] -= scale_factor * solution[row[j]][v]; } for_less( v, 0, n_values ) solution[row[i]][v] /= a[row[i]][i]; } } FREE( s ); return( success ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : scaled_maximal_pivoting_gaussian_elimination_real @INPUT : n coefs n_values values @OUTPUT : values has the solution on output @RETURNS : TRUE if successful @DESCRIPTION: Performs gaussian elimination on a type-Real matrix, first copying it into temporary storage, which is modified as the gaussian elimination is performed. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN scaled_maximal_pivoting_gaussian_elimination_real( int n, Real **coefs, int n_values, Real **values ) { int i, j, v, *row; Real **a, **solution; BOOLEAN success; ALLOC( row, n ); ALLOC2D( a, n, n ); ALLOC2D( solution, n, n_values ); for_less( i, 0, n ) { for_less( j, 0, n ) a[i][j] = coefs[i][j]; for_less( v, 0, n_values ) solution[i][v] = values[v][i]; } success = scaled_maximal_pivoting_gaussian_elimination( n, row, a, n_values, solution ); if( success ) { for_less( i, 0, n ) { for_less( v, 0, n_values ) values[v][i] = solution[row[i]][v]; } } FREE2D( a ); FREE2D( solution ); FREE( row ); return( success ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : solve_linear_system @INPUT : n coefs - n by n matrix values - size n list @OUTPUT : solution - size n list @RETURNS : TRUE if successful @DESCRIPTION: Solves a linear system of equations, finding the solution t t vector that satisfies [coefs] * [solution] = [values] @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN solve_linear_system( int n, Real **coefs, Real values[], Real solution[] ) { int i; for_less( i, 0, n ) solution[i] = values[i]; return( scaled_maximal_pivoting_gaussian_elimination_real( n, coefs, 1, &solution ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : invert_square_matrix @INPUT : n matrix - n by n matrix @OUTPUT : inverse @RETURNS : TRUE if successful @DESCRIPTION: Computes the inverse of a square matrix. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN invert_square_matrix( int n, Real **matrix, Real **inverse ) { Real tmp; BOOLEAN success; int i, j; for_less( i, 0, n ) { for_less( j, 0, n ) inverse[i][j] = 0.0; inverse[i][i] = 1.0; } success = scaled_maximal_pivoting_gaussian_elimination_real( n, matrix, n, inverse ); if( success ) { for_less( i, 0, n-1 ) { for_less( j, i+1, n ) { tmp = inverse[i][j]; inverse[i][j] = inverse[j][i]; inverse[j][i] = tmp; } } } return( success ); } minc-2.2.00/volume_io/Geometry/inverse.c0000644000265600003100000000474112027132663015057 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : compute_transform_inverse @INPUT : transform @OUTPUT : inverse @RETURNS : TRUE if successful @DESCRIPTION: Computes the inverse of the given transformation matrix. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN compute_transform_inverse( Transform *transform, Transform *inverse ) { int i, j; Real **t, **inv; BOOLEAN success; /* --- copy the transform to a numerical recipes type matrix */ ALLOC2D( t, 4, 4 ); ALLOC2D( inv, 4, 4 ); for_less( i, 0, 4 ) { for_less( j, 0, 4 ) t[i][j] = Transform_elem(*transform,i,j); } success = invert_square_matrix( 4, t, inv ); if( success ) { /* --- copy the resulting numerical recipes matrix to the output argument */ for_less( i, 0, 4 ) { for_less( j, 0, 4 ) { Transform_elem(*inverse,i,j) = inv[i][j]; } } #ifdef DEBUG /* --- check if this really is an inverse, by multiplying */ { Transform ident; concat_transforms( &ident, transform, inverse ); if( !close_to_identity(&ident) ) { print_error( "Error in compute_transform_inverse\n" ); } } #endif } else make_identity_transform( inverse ); FREE2D( t ); FREE2D( inv ); return( success ); } minc-2.2.00/volume_io/Geometry/newton.c0000644000265600003100000001100512027132663014705 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #define STEP_RATIO 1.0 /* ----------------------------- MNI Header ----------------------------------- @NAME : newton_root_find @INPUT : n_dimensions - dimensionality of domain and range function - function to find the solution to - takes as arguments the function_data pointer, the position to evaluate, and passes back the values[n_dim] and derivatives[n_dim][n_dim] function_data initial_guess[n_dimensions] desired_values[n_dimensions] function_tolerance delta_tolerance max_iterations @OUTPUT : solution[n_dimensions] @RETURNS : TRUE if successful @DESCRIPTION: Performs a newton root find of a function by taking steps of x' = (desired - f(x)) / grad(f(x)), where x starts at initial_guess and is updated until the f(x) is close to zero. x is passed back in solution. @METHOD : @GLOBALS : @CALLS : @CREATED : May 10, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN newton_root_find( int n_dimensions, void (*function) ( void *, Real [], Real [], Real ** ), void *function_data, Real initial_guess[], Real desired_values[], Real solution[], Real function_tolerance, Real delta_tolerance, int max_iterations ) { int iter, dim; Real *values, **derivatives, *delta, error, best_error, *position; Real step_size; BOOLEAN success; ALLOC( position, n_dimensions ); ALLOC( values, n_dimensions ); ALLOC( delta, n_dimensions ); ALLOC2D( derivatives, n_dimensions, n_dimensions ); /*--- initialize function position to the initial guess */ for_less( dim, 0, n_dimensions ) position[dim] = initial_guess[dim]; iter = 0; success = FALSE; best_error = 0.0; while( max_iterations < 0 || iter < max_iterations ) { ++iter; /*--- evaluate the function and derivatives */ (*function) ( function_data, position, values, derivatives ); /*--- compute the error between the desired values and the current */ error = 0.0; for_less( dim, 0, n_dimensions ) { values[dim] = desired_values[dim] - values[dim]; error += FABS( values[dim] ); } /*--- if this is best so far, record it */ if( iter == 1 || error < best_error ) { best_error = error; for_less( dim, 0, n_dimensions ) solution[dim] = position[dim]; if( error < function_tolerance ) { success = TRUE; break; } } /*--- find the step (delta) to solve the linear system of function value and derivatives */ if( !solve_linear_system( n_dimensions, derivatives, values, delta ) ) break; /*--- compute the size of the step to see if it is small */ step_size = 0.0; for_less( dim, 0, n_dimensions ) { position[dim] += STEP_RATIO * delta[dim]; step_size += FABS( delta[dim] ); } if( step_size < delta_tolerance ) { success = TRUE; break; } } /*--- free memory */ FREE( values ); FREE( delta ); FREE2D( derivatives ); FREE( position ); return( success ); } minc-2.2.00/volume_io/Geometry/points.c0000644000265600003100000000446312027132663014721 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : create_orthogonal_vector @INPUT : v @OUTPUT : ortho @RETURNS : @DESCRIPTION: Creates a vector which is orthogonal to v. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Jul. 11, 1995 D. MacDonald - made more numerically robust @MODIFIED : Feb. 8, 1996 D. MacDonald - changed from noncolinear to orthogonal ---------------------------------------------------------------------------- */ VIOAPI void create_orthogonal_vector( Vector *v, Vector *ortho ) { Real x, y, z; x = (Real) Vector_x(*v); y = (Real) Vector_y(*v); z = (Real) Vector_z(*v); fill_Vector( *ortho, y+z, -x-z, y-x ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_two_orthogonal_vectors @INPUT : v @OUTPUT : v1 v2 @RETURNS : @DESCRIPTION: Creates two vectors which are perpendicular to each other and to the given vector. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_two_orthogonal_vectors( Vector *v, Vector *v1, Vector *v2 ) { create_orthogonal_vector( v, v1 ); CROSS_VECTORS( *v2, *v, *v1 ); } minc-2.2.00/volume_io/Geometry/splines.c0000644000265600003100000002665512027132663015071 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /*--- Weighting functions which define the splines, all of which are interpolation splines, with the exception of the quadratic spline */ static Real constant_coefs[1][1] = { { 1.0 } }; static Real linear_coefs[2][2] = { { 1.0, 0.0 }, { -1.0, 1.0 } }; static Real quadratic_coefs[3][3] = { { 0.5, 0.5, 0.0 }, { -1.0, 1.0, 0.0 }, { 0.5, -1.0, 0.5 } }; static Real cubic_coefs[4][4] = { { 0.0, 1.0, 0.0, 0.0 }, { -0.5, 0.0, 0.5, 0.0 }, { 1.0, -2.5, 2.0, -0.5 }, { -0.5, 1.5, -1.5, 0.5 } }; /* ----------------------------- MNI Header ----------------------------------- @NAME : get_linear_spline_coefs @INPUT : @OUTPUT : coefs 2 by 2 array of coefficients @RETURNS : @DESCRIPTION: Passes back the basis matrix of the linear spline. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_linear_spline_coefs( Real **coefs ) { int i, j; for_less( i, 0, 2 ) for_less( j, 0, 2 ) coefs[i][j] = linear_coefs[i][j]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_quadratic_spline_coefs @INPUT : @OUTPUT : coefs 3 by 3 array of coefficients @RETURNS : @DESCRIPTION: Passes back the basis matrix of the quadratic spline. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_quadratic_spline_coefs( Real **coefs ) { int i, j; for_less( i, 0, 3 ) for_less( j, 0, 3 ) coefs[i][j] = quadratic_coefs[i][j]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_cubic_spline_coefs @INPUT : @OUTPUT : coefs 4 by 4 array of coefficients @RETURNS : @DESCRIPTION: Passes back the basis matrix of the cubic interpolating (Catmull-Romm) spline. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_cubic_spline_coefs( Real **coefs ) { int i, j; for_less( i, 0, 4 ) for_less( j, 0, 4 ) coefs[i][j] = cubic_coefs[i][j]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : cubic_interpolate @INPUT : u - position to evaluate, between 0 and 1 v0 - four control vertices v1 v2 v3 @OUTPUT : @RETURNS : interpolated value @DESCRIPTION: Performs cubic interpolation, where a value of u = 0 returns v1, a value of u = 1 returns v2, and intermediate values smoothly interpolate. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real cubic_interpolate( Real u, Real v0, Real v1, Real v2, Real v3 ) { Real coefs[4], value; coefs[0] = v0; coefs[1] = v1; coefs[2] = v2; coefs[3] = v3; evaluate_univariate_interpolating_spline( u, 4, coefs, 0, &value ); return( value ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_univariate_interpolating_spline @INPUT : u degree - 2,3,4 for linear, quadratic, or cubic coefs[degree] - control vertices n_derivs - number of derivatives to compute @OUTPUT : derivs - 1 + n_derivs values and derivatives @RETURNS : @DESCRIPTION: Passes back the interpolated value and n_derivs derivatives in the derivs array. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void evaluate_univariate_interpolating_spline( Real u, int degree, Real coefs[], int n_derivs, Real derivs[] ) { evaluate_interpolating_spline( 1, &u, degree, 1, coefs, n_derivs, derivs ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_bivariate_interpolating_spline @INPUT : u - position to evaluate v degree - 2,3,4 for linear, quadratic, or cubic coefs - control vertices, size degree * degree n_derivs - number of derivatives to compute @OUTPUT : derivs - (1 + n_derivs) * (1 + n_derivs) values and derivatives @RETURNS : @DESCRIPTION: Passes back the interpolated value and derivatives in the derivs array. derivs is a 1D array that is conceptually 2 dimensional, indexed by dx and dy, where dx and dy range from 0 to n_derivs, indicating which value or derivative. For example 0,0 refers to the interpolated value whereas 1,0 refers to the derivative of the function wrt u. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void evaluate_bivariate_interpolating_spline( Real u, Real v, int degree, Real coefs[], int n_derivs, Real derivs[] ) { Real positions[2]; positions[0] = u; positions[1] = v; evaluate_interpolating_spline( 2, positions, degree, 1, coefs, n_derivs, derivs ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_trivariate_interpolating_spline @INPUT : u - position to evaluate v w degree - 2,3,4 for linear, quadratic, or cubic coefs - control vertices, size degree * degree * degree n_derivs - number of derivatives to compute @OUTPUT : derivs - (1 + n_derivs) * (1 + n_derivs) * (1 + n_derivs) values and derivatives @RETURNS : @DESCRIPTION: Passes back the interpolated value and derivatives in the derivs array. derivs is a 1D array that is conceptually 3 dimensional, indexed by dx, dy, and dz, where dx, dy, and dz each range from 0 to n_derivs, indicating which value or derivative. For example 0,0,0 refers to the interpolated value whereas 1,0,1 refers to the derivative of the function wrt u and w. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void evaluate_trivariate_interpolating_spline( Real u, Real v, Real w, int degree, Real coefs[], int n_derivs, Real derivs[] ) { Real positions[3]; positions[0] = u; positions[1] = v; positions[2] = w; evaluate_interpolating_spline( 3, positions, degree, 1, coefs, n_derivs, derivs ); } #define MAX_DIMS 100 /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_interpolating_spline @INPUT : n_dims - dimensionality of the spline, >= 1 parameters - u, v, w,... position of spline degree - 2,3,4 for linear, quadratic, or cubic n_values - number of values to interpolate at the point coefs - [n_values]*[degree]*[degree]... control vertices n_derivs - number of derivatives to compute @OUTPUT : derivs - (n_values) * (1 + n_derivs) * (1 + n_derivs) * ... values and derivatives @RETURNS : @DESCRIPTION: Passes back the interpolated value and derivatives in the derivs array. derivs is a 1D array that is conceptually multi-dimensional, indexed by v, dx, dy, dz, etc., where dx, dy, dz, etc. each range from 0 to n_derivs, and v ranges from 0 to n_values-1. For example, if n_dims is 3 and n_values is 4, then the 4D index of derivs[2,0,0,0] refers to the interpolated value of the 3rd component of the 4 valued function. derivs[1,0,1,1] refers to the derivative of the 2nd component of the 4 valued function with respect to v and w. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void evaluate_interpolating_spline( int n_dims, Real parameters[], int degree, int n_values, Real coefs[], int n_derivs, Real derivs[] ) { int d, degrees[MAX_DIMS], n_derivs_list[MAX_DIMS]; Real *bases[MAX_DIMS]; if( degree < 1 || degree > 4 ) { print_error( "evaluate_interpolating_spline: invalid degree: %d\n", degree ); return; } if( n_dims < 1 || n_dims > MAX_DIMS ) { print_error( "evaluate_interpolating_spline: invalid n dims: %d\n", n_dims ); return; } switch( degree ) { case 1: bases[0] = &constant_coefs[0][0]; break; case 2: bases[0] = &linear_coefs[0][0]; break; case 3: bases[0] = &quadratic_coefs[0][0]; break; case 4: bases[0] = &cubic_coefs[0][0]; break; } for_less( d, 1, n_dims ) bases[d] = bases[0]; for_less( d, 0, n_dims ) { degrees[d] = degree; n_derivs_list[d] = n_derivs; } spline_tensor_product( n_dims, parameters, degrees, bases, n_values, coefs, n_derivs_list, derivs ); } minc-2.2.00/volume_io/Geometry/tensors.c0000755000265600003100000002235212027132663015102 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : multiply_basis_matrices @INPUT : n_derivs n_degs m1 m2 @OUTPUT : prod @RETURNS : @DESCRIPTION: Performs a matrix multiply of the basis matrix with the powers of the u's positions. Steps through the matrices in the appropriate strides. Could use the more general multiply_matrices below, but is done this way for speed. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void multiply_basis_matrices( int n_derivs, int n_degs, Real m1[], Real m2[], Real prod[] ) { int i, j, k, m2_inc; Real *m1_ptr, *m1_ptr1; Real *m2_ptr; Real sum, *prod_ptr; m1_ptr = m1; prod_ptr = prod; m2_inc = 1 - n_degs * n_degs; for_less( i, 0, n_derivs ) { m2_ptr = m2; for_less( j, 0, n_degs ) { sum = 0.0; m1_ptr1 = m1_ptr; for_less( k, 0, n_degs ) { sum += (*m1_ptr1) * (*m2_ptr); ++m1_ptr1; m2_ptr += n_degs; } m2_ptr += m2_inc; *prod_ptr = sum; ++prod_ptr; } m1_ptr += n_degs; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : multiply_matrices @INPUT : x1 - x size of first matrix y1 - y size of first matrix m1 - first matrix sa1 - x stride of first matrix sb1 - y stride of first matrix : y2 - y size of second matrix (x size must be y1) m2 - second matrix sa2 - x stride of second matrix sb2 - y stride of second matrix sap - x stride of product matrix sbp - y stride of product matrix @OUTPUT : prod - product of m1 * m2 @RETURNS : @DESCRIPTION: Multiplies the two matrices m1 and m2, placing the results in prod. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan. 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void multiply_matrices( int x1, int y1, Real m1[], int sa1, int sb1, int y2, Real m2[], int sa2, int sb2, Real prod[], int sap, int sbp ) { int i, j, k; Real *m1_ptr, *m1_ptr1, *m2_ptr; Real sum, *prod_ptr; m1_ptr = m1; prod_ptr = prod; sb2 -= y1 * sa2; sap -= y2 * sbp; for_less( i, 0, x1 ) { m2_ptr = m2; for_less( j, 0, y2 ) { sum = 0.0; m1_ptr1 = m1_ptr; for_less( k, 0, y1 ) { sum += (*m1_ptr1) * (*m2_ptr); m1_ptr1 += sb1; m2_ptr += sa2; } *prod_ptr = sum; prod_ptr += sbp; m2_ptr += sb2; } m1_ptr += sa1; prod_ptr += sap; } } #define MAX_DEGREE 4 #define MAX_DIMS 10 #define MAX_TOTAL_VALUES 4000 /* ----------------------------- MNI Header ----------------------------------- @NAME : spline_tensor_product @INPUT : n_dims positions[n_dims] degrees[n_dims] bases[n_dims][degrees[dim]*degrees[dim]] n_values coefs [n_values*degrees[0]*degrees[1]*...] n_derivs[n_dims] @OUTPUT : results[n_values*n_derivs[0]*n_derivs[1]*...] @RETURNS : @DESCRIPTION: Performs the spline tensor product necessary to evaluate. Takes as input the number of dimensions, the position to evaluate, the basis matrices defining the interpolation method, and the control vertices (coefs). The resulting values and derivatives are placed in the 1D array results, conceptually as a (1+n_dims)-D array. @METHOD : @GLOBALS : @CALLS : @CREATED : Jan 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void spline_tensor_product( int n_dims, Real positions[], int degrees[], Real *bases[], int n_values, Real coefs[], int n_derivs[], Real results[] ) { int deriv, d, k, total_values, src; int ind, prev_ind, max_degree, n_derivs_plus_1, deg; int static_indices[MAX_DIMS]; int *indices, total_derivs; Real *input_coefs, u_power, u; Real static_us[MAX_DEGREE*MAX_DEGREE]; Real static_weights[MAX_DEGREE*MAX_DEGREE]; Real *us, *weights; Real *tmp_results[2], *r; Real static_tmp_results[2][MAX_TOTAL_VALUES]; BOOLEAN results_alloced; /*--- check arguments */ max_degree = 2; total_values = n_values; total_derivs = 0; for_less( d, 0, n_dims ) { if( degrees[d] < 2 ) { print_error( "spline_tensor_product: Degree %d must be greater than 1.\n", degrees[d] ); return; } if( degrees[d] > max_degree ) max_degree = degrees[d]; if( n_derivs[d] > total_derivs ) total_derivs = n_derivs[d]; total_values *= degrees[d]; } /*--- determine if fixed size storage is large enough, if not allocate memory */ if( n_dims > MAX_DIMS ) { ALLOC( indices, n_dims ); } else { indices = static_indices; } if( max_degree > MAX_DEGREE ) { ALLOC( us, max_degree * max_degree ); ALLOC( weights, max_degree * max_degree ); } else { us = static_us; weights = static_weights; } if( total_values > MAX_TOTAL_VALUES ) { ALLOC( tmp_results[0], total_values ); ALLOC( tmp_results[1], total_values ); results_alloced = TRUE; } else { tmp_results[0] = static_tmp_results[0]; tmp_results[1] = static_tmp_results[1]; results_alloced = FALSE; } input_coefs = coefs; src = 0; /*--- do each dimension */ for_less( d, 0, n_dims ) { deg = degrees[d]; n_derivs_plus_1 = 1 + n_derivs[d]; /*--- fill in the top row of matrix of powers of u = [1 u u^2 u^3 ...] for evaluating values */ u = positions[d]; u_power = 1.0; us[0] = 1.0; for_less( k, 1, deg ) { u_power *= u; us[k] = u_power; } /*--- fill in the rest of the n_derivs_plus_1 by degrees[d] matrix: 1 u u^2 u^3 ... 0 1 2u 3u^2 ... 0 0 2 6u ... ... */ ind = deg; for_less( deriv, 1, n_derivs_plus_1 ) { for_less( k, 0, deriv ) { us[ind] = 0.0; ++ind; } prev_ind = IJ( deriv-1, deriv-1, deg ); for_less( k, deriv, deg ) { us[ind] = us[prev_ind] * (Real) k; ++ind; ++prev_ind; } } /*--- multiply the u's matrix by the spline basis to create weights */ multiply_basis_matrices( n_derivs_plus_1, deg, us, bases[d], weights ); total_values /= deg; if( d == n_dims-1 ) r = results; else r = tmp_results[1-src]; /*--- multiply coefficient weights by the coefficients */ multiply_matrices( n_derivs_plus_1, deg, weights, deg, 1, total_values, input_coefs, total_values, 1, r, 1, n_derivs_plus_1 ); src = 1 - src; input_coefs = tmp_results[src]; total_values *= n_derivs_plus_1; } /*--- check to free memory */ if( n_dims > MAX_DIMS ) { FREE( indices ); } if( max_degree > MAX_DEGREE ) { FREE( us ); FREE( weights ); } if( results_alloced ) { FREE( tmp_results[0] ); FREE( tmp_results[1] ); } } minc-2.2.00/volume_io/Geometry/transforms.c0000644000265600003100000005716112027132664015607 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : make_identity_transform @INPUT : @OUTPUT : transform @RETURNS : @DESCRIPTION: Fills in the transform with the identity matrix. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void make_identity_transform( Transform *transform ) { Transform_elem( *transform, 0, 0 ) = 1.0; Transform_elem( *transform, 0, 1 ) = 0.0; Transform_elem( *transform, 0, 2 ) = 0.0; Transform_elem( *transform, 0, 3 ) = 0.0; Transform_elem( *transform, 1, 0 ) = 0.0; Transform_elem( *transform, 1, 1 ) = 1.0; Transform_elem( *transform, 1, 2 ) = 0.0; Transform_elem( *transform, 1, 3 ) = 0.0; Transform_elem( *transform, 2, 0 ) = 0.0; Transform_elem( *transform, 2, 1 ) = 0.0; Transform_elem( *transform, 2, 2 ) = 1.0; Transform_elem( *transform, 2, 3 ) = 0.0; Transform_elem( *transform, 3, 0 ) = 0.0; Transform_elem( *transform, 3, 1 ) = 0.0; Transform_elem( *transform, 3, 2 ) = 0.0; Transform_elem( *transform, 3, 3 ) = 1.0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : close_to_identity @INPUT : transform @OUTPUT : @RETURNS : TRUE if transform is close to identity @DESCRIPTION: @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN close_to_identity( Transform *transform ) { #define TOLERANCE 0.001 BOOLEAN close; Real expected_val; int i, j; close = TRUE; for_less( i, 0, 4 ) { for_less( j, 0, 4 ) { if( i == j ) expected_val = 1.0; else expected_val = 0.0; if( Transform_elem(*transform,i,j) < expected_val - TOLERANCE || Transform_elem(*transform,i,j) > expected_val + TOLERANCE ) { close = FALSE; } } } return( close ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_origin @INPUT : transform @OUTPUT : origin @RETURNS : @DESCRIPTION: Passes back the origin of the transform, i.e., where the point (0,0,0) would be transformed to. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_origin( Transform *transform, Point *origin ) { fill_Point( *origin, Transform_elem(*transform,0,3), Transform_elem(*transform,1,3), Transform_elem(*transform,2,3) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_transform_origin @INPUT : origin @OUTPUT : transform @RETURNS : @DESCRIPTION: Sets the origin of the transform, i.e., where the point (0,0,0) would be transformed to. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_transform_origin( Transform *transform, Point *origin ) { Transform_elem(*transform,0,3) = (Transform_elem_type) Point_x(*origin); Transform_elem(*transform,1,3) = (Transform_elem_type) Point_y(*origin); Transform_elem(*transform,2,3) = (Transform_elem_type) Point_z(*origin); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_origin_real @INPUT : transform @OUTPUT : origin @RETURNS : @DESCRIPTION: Passes back the origin of the transform, i.e., where the point (0,0,0) would be transformed to. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_origin_real( Transform *transform, Real origin[] ) { origin[X] = Transform_elem(*transform,0,3); origin[Y] = Transform_elem(*transform,1,3); origin[Z] = Transform_elem(*transform,2,3); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_x_axis @INPUT : transform @OUTPUT : x_axis @RETURNS : @DESCRIPTION: Passes back the x axis of the transform, i.e., the vector to which the vector (1,0,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_x_axis( Transform *transform, Vector *x_axis ) { fill_Vector( *x_axis, Transform_elem(*transform,0,0), Transform_elem(*transform,1,0), Transform_elem(*transform,2,0) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_x_axis_real @INPUT : transform @OUTPUT : x_axis @RETURNS : @DESCRIPTION: Passes back the x axis of the transform, i.e., the vector to which the vector (1,0,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_x_axis_real( Transform *transform, Real x_axis[] ) { x_axis[X] = Transform_elem(*transform,0,0); x_axis[Y] = Transform_elem(*transform,1,0); x_axis[Z] = Transform_elem(*transform,2,0); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_transform_x_axis @INPUT : x_axis @OUTPUT : transform @RETURNS : @DESCRIPTION: Sets the x axis of the transform, i.e., the vector to which the vector (1,0,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_transform_x_axis( Transform *transform, Vector *x_axis ) { Transform_elem(*transform,0,0) = (Transform_elem_type) Vector_x(*x_axis); Transform_elem(*transform,1,0) = (Transform_elem_type) Vector_y(*x_axis); Transform_elem(*transform,2,0) = (Transform_elem_type) Vector_z(*x_axis); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_transform_x_axis_real @INPUT : x_axis @OUTPUT : transform @RETURNS : @DESCRIPTION: Sets the x axis of the transform, i.e., the vector to which the vector (1,0,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_transform_x_axis_real( Transform *transform, Real x_axis[] ) { Transform_elem(*transform,0,0) = (Transform_elem_type) x_axis[X]; Transform_elem(*transform,1,0) = (Transform_elem_type) x_axis[Y]; Transform_elem(*transform,2,0) = (Transform_elem_type) x_axis[Z]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_y_axis @INPUT : transform @OUTPUT : y_axis @RETURNS : @DESCRIPTION: Passes back the y axis of the transform, i.e., the vector to which the vector (0,1,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_y_axis( Transform *transform, Vector *y_axis ) { fill_Vector( *y_axis, Transform_elem(*transform,0,1), Transform_elem(*transform,1,1), Transform_elem(*transform,2,1) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_y_axis_real @INPUT : transform @OUTPUT : y_axis @RETURNS : @DESCRIPTION: Passes back the y axis of the transform, i.e., the vector to which the vector (0,1,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_y_axis_real( Transform *transform, Real y_axis[] ) { y_axis[X] = Transform_elem(*transform,0,1); y_axis[Y] = Transform_elem(*transform,1,1); y_axis[Z] = Transform_elem(*transform,2,1); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_transform_y_axis @INPUT : y_axis @OUTPUT : transform @RETURNS : @DESCRIPTION: Sets the y axis of the transform, i.e., the vector to which the vector (0,1,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_transform_y_axis( Transform *transform, Vector *y_axis ) { Transform_elem(*transform,0,1) = (Transform_elem_type) Vector_x(*y_axis); Transform_elem(*transform,1,1) = (Transform_elem_type) Vector_y(*y_axis); Transform_elem(*transform,2,1) = (Transform_elem_type) Vector_z(*y_axis); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_transform_y_axis_real @INPUT : y_axis @OUTPUT : transform @RETURNS : @DESCRIPTION: Sets the y axis of the transform, i.e., the vector to which the vector (0,1,0) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_transform_y_axis_real( Transform *transform, Real y_axis[] ) { Transform_elem(*transform,0,1) = (Transform_elem_type) y_axis[X]; Transform_elem(*transform,1,1) = (Transform_elem_type) y_axis[Y]; Transform_elem(*transform,2,1) = (Transform_elem_type) y_axis[Z]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_z_axis @INPUT : transform @OUTPUT : z_axis @RETURNS : @DESCRIPTION: Passes back the z axis of the transform, i.e., the vector to which the vector (0,0,1) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_z_axis( Transform *transform, Vector *z_axis ) { fill_Vector( *z_axis, Transform_elem(*transform,0,2), Transform_elem(*transform,1,2), Transform_elem(*transform,2,2) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_z_axis_real @INPUT : transform @OUTPUT : z_axis @RETURNS : @DESCRIPTION: Passes back the z axis of the transform, i.e., the vector to which the vector (0,0,1) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_transform_z_axis_real( Transform *transform, Real z_axis[] ) { z_axis[X] = Transform_elem(*transform,0,2); z_axis[Y] = Transform_elem(*transform,1,2); z_axis[Z] = Transform_elem(*transform,2,2); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_transform_z_axis @INPUT : z_axis @OUTPUT : transform @RETURNS : @DESCRIPTION: Sets the z axis of the transform, i.e., the vector to which the vector (0,0,1) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_transform_z_axis( Transform *transform, Vector *z_axis ) { Transform_elem(*transform,0,2) = (Transform_elem_type) Vector_x(*z_axis); Transform_elem(*transform,1,2) = (Transform_elem_type) Vector_y(*z_axis); Transform_elem(*transform,2,2) = (Transform_elem_type) Vector_z(*z_axis); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_transform_z_axis_real @INPUT : z_axis @OUTPUT : transform @RETURNS : @DESCRIPTION: Sets the z axis of the transform, i.e., the vector to which the vector (0,0,1) would be transformed. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_transform_z_axis_real( Transform *transform, Real z_axis[] ) { Transform_elem(*transform,0,2) = (Transform_elem_type) z_axis[X]; Transform_elem(*transform,1,2) = (Transform_elem_type) z_axis[Y]; Transform_elem(*transform,2,2) = (Transform_elem_type) z_axis[Z]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : make_change_to_bases_transform @INPUT : origin x_axis y_axis z_axis @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a transform that translates the point (0,0,0) to the specified origin. The point (1,0,0) is transformed to the specified origin plus the specified x_axis. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void make_change_to_bases_transform( Point *origin, Vector *x_axis, Vector *y_axis, Vector *z_axis, Transform *transform ) { Transform_elem( *transform,0,0 ) = (Transform_elem_type)Vector_x( *x_axis ); Transform_elem( *transform,0,1 ) = (Transform_elem_type)Vector_x( *y_axis ); Transform_elem( *transform,0,2 ) = (Transform_elem_type)Vector_x( *z_axis ); Transform_elem( *transform,0,3 ) = (Transform_elem_type)Point_x( *origin ); Transform_elem( *transform,1,0 ) = (Transform_elem_type)Vector_y( *x_axis ); Transform_elem( *transform,1,1 ) = (Transform_elem_type)Vector_y( *y_axis ); Transform_elem( *transform,1,2 ) = (Transform_elem_type)Vector_y( *z_axis ); Transform_elem( *transform,1,3 ) = (Transform_elem_type)Point_y( *origin ); Transform_elem( *transform,2,0 ) = (Transform_elem_type)Vector_z( *x_axis ); Transform_elem( *transform,2,1 ) = (Transform_elem_type)Vector_z( *y_axis ); Transform_elem( *transform,2,2 ) = (Transform_elem_type)Vector_z( *z_axis ); Transform_elem( *transform,2,3 ) = (Transform_elem_type)Point_z( *origin ); Transform_elem( *transform,3,0 ) = 0.0; Transform_elem( *transform,3,1 ) = 0.0; Transform_elem( *transform,3,2 ) = 0.0; Transform_elem( *transform,3,3 ) = 1.0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : make_change_from_bases_transform @INPUT : origin x_axis y_axis z_axis @OUTPUT : @RETURNS : @DESCRIPTION: Makes a change of bases transform, so that points are transformed to be relative to the given axes. For instance the origin is transformed by the change of bases transform to be point (0,0,0). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void make_change_from_bases_transform( Point *origin, Vector *x_axis, Vector *y_axis, Vector *z_axis, Transform *transform ) { Transform_elem(*transform,0,0) = (Transform_elem_type)Vector_x( *x_axis ); Transform_elem(*transform,0,1) = (Transform_elem_type)Vector_y( *x_axis ); Transform_elem(*transform,0,2) = (Transform_elem_type)Vector_z( *x_axis ); Transform_elem(*transform,0,3) = (Transform_elem_type) - DOT_POINT_VECTOR( *origin, *x_axis ); Transform_elem(*transform,1,0) = (Transform_elem_type)Vector_x( *y_axis ); Transform_elem(*transform,1,1) = (Transform_elem_type)Vector_y( *y_axis ); Transform_elem(*transform,1,2) = (Transform_elem_type)Vector_z( *y_axis ); Transform_elem(*transform,1,3) = (Transform_elem_type) - DOT_POINT_VECTOR( *origin, *y_axis ); Transform_elem(*transform,2,0) = (Transform_elem_type)Vector_x( *z_axis ); Transform_elem(*transform,2,1) = (Transform_elem_type)Vector_y( *z_axis ); Transform_elem(*transform,2,2) = (Transform_elem_type)Vector_z( *z_axis ); Transform_elem(*transform,2,3) = (Transform_elem_type) - DOT_POINT_VECTOR( *origin, *z_axis ); Transform_elem(*transform,3,0) = 0.0; Transform_elem(*transform,3,1) = 0.0; Transform_elem(*transform,3,2) = 0.0; Transform_elem(*transform,3,3) = 1.0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : concat_transforms @INPUT : t1 t2 @OUTPUT : result @RETURNS : @DESCRIPTION: Concatenates the two transforms returning the result in the argument, 'result'. Correctly handles the case where the result transform is also one of the operands. Transforming a point by the 'result' transform will give the same point as first transforming the point by 't1', then by 't2'. @METHOD : Multiplies result = t2 * t1 @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void concat_transforms( Transform *result, Transform *t1, Transform *t2 ) { int i, j, k; Real sum; BOOLEAN result_is_also_an_arg; Transform tmp, *t; /*--- check if the result transform is same as one of the arguments */ if( result == t1 || result == t2 ) { result_is_also_an_arg = TRUE; t = &tmp; } else { result_is_also_an_arg = FALSE; t = result; } /*--- perform multiplication */ for_less( i, 0, 4 ) { for_less( j, 0, 4 ) { sum = 0.0; for_less( k, 0, 4 ) { sum += Transform_elem( *t2, i, k ) * Transform_elem( *t1, k, j ); } Transform_elem( *t, i, j ) = sum; } } if( result_is_also_an_arg ) *result = tmp; } /* ----------------------------- MNI Header ----------------------------------- @NAME : homogenous_transform_point @INPUT : transform x y z w @OUTPUT : x_trans y_trans z_trans @RETURNS : @DESCRIPTION: Transforms the point (x,y,z,w) by the homogenous transform matrix, resulting in (x_trans,y_trans,z_trans). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void homogenous_transform_point( Transform *transform, Real x, Real y, Real z, Real w, Real *x_trans, Real *y_trans, Real *z_trans ) { Real w_trans; *x_trans = Transform_elem(*transform,0,0) * x + Transform_elem(*transform,0,1) * y + Transform_elem(*transform,0,2) * z + Transform_elem(*transform,0,3) * w; *y_trans = Transform_elem(*transform,1,0) * x + Transform_elem(*transform,1,1) * y + Transform_elem(*transform,1,2) * z + Transform_elem(*transform,1,3) * w; *z_trans = Transform_elem(*transform,2,0) * x + Transform_elem(*transform,2,1) * y + Transform_elem(*transform,2,2) * z + Transform_elem(*transform,2,3) * w; w_trans = Transform_elem(*transform,3,0) * x + Transform_elem(*transform,3,1) * y + Transform_elem(*transform,3,2) * z + Transform_elem(*transform,3,3) * w; if( w_trans != 0.0 && w_trans != 1.0 ) { *x_trans /= w_trans; *y_trans /= w_trans; *z_trans /= w_trans; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : transform_point @INPUT : transform x y z @OUTPUT : x_trans y_trans z_trans @RETURNS : @DESCRIPTION: Transforms the point (x,y,z) by the transform matrix, resulting in (x_trans,y_trans,z_trans). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void transform_point( Transform *transform, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans ) { homogenous_transform_point( transform, x, y, z, 1.0, x_trans, y_trans, z_trans ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : transform_vector @INPUT : transform x y z @OUTPUT : x_trans y_trans z_trans @RETURNS : @DESCRIPTION: Transforms the vector by the specified transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void transform_vector( Transform *transform, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans ) { homogenous_transform_point( transform, x, y, z, 0.0, x_trans, y_trans, z_trans ); } minc-2.2.00/volume_io/Include/0000755000265600003100000000000012030114721013067 500000000000000minc-2.2.00/volume_io/Include/volume_io/0000755000265600003100000000000012030114721015065 500000000000000minc-2.2.00/volume_io/Include/volume_io/alloc.h0000644000265600003100000002533212027132664016271 00000000000000#ifndef DEF_ALLOC #define DEF_ALLOC /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/alloc.h,v 1.19 2005-05-19 21:19:27 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A set of macros for allocating 1, 2, and 3 dimensional arrays. @METHOD : Requires the file alloc.c linked in. @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include #include #ifdef NO_DEBUG_ALLOC #define _ALLOC_SOURCE_LINE #define _ALLOC_SOURCE_LINE_ARG_DEF #define _ALLOC_SOURCE_LINE_ARGUMENTS #define PRINT_ALLOC_SOURCE_LINE #else #define _ALLOC_SOURCE_LINE , __FILE__, __LINE__ #define _ALLOC_SOURCE_LINE_ARG_DEF , char filename[], int line_number #define _ALLOC_SOURCE_LINE_ARGUMENTS , filename, line_number #define PRINT_ALLOC_SOURCE_LINE \ print_alloc_source_line( filename, line_number ); #endif #if !VIO_PREFIX_NAMES /* ----------------------------- MNI Header ----------------------------------- @NAME : ALLOC @INPUT : n_items @OUTPUT : ptr @RETURNS : @DESCRIPTION: Macro to allocate n_items of the type ptr points to, assigning : ptr. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ALLOC( ptr, n_items ) \ ASSIGN_PTR(ptr) = \ alloc_memory_1d( (size_t) (n_items), \ sizeof(*(ptr)) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : FREE @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Macro to FREE the ptr. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define FREE( ptr ) \ free_memory_1d( (void **) &(ptr) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : REALLOC @INPUT : ptr : n_items @OUTPUT : @RETURNS : @DESCRIPTION: Macro to change the number of items that ptr points to, assigning : ptr. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define REALLOC( ptr, n_items ) \ realloc_memory( (void **) &(ptr), (size_t) (n_items), \ sizeof(*(ptr)) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : ALLOC_VAR_SIZED_STRUCT @INPUT : element_type : n_elements @OUTPUT : : ptr @RETURNS : @DESCRIPTION: Macro to allocate a structure with a variable size, assigning : ptr. : To use this, the variable length array must be the last element : of the structure. : : Use: : typedef struct : { : int n_items; : double variable_length_list[1]; : } var_struct; : : var_struct *s_ptr; : : ALLOC_VAR_SIZED_STRUCT( s_ptr, double, 15 ); : : s->n_items = 15; : s->variable_length_list[0] = 1.0; : s->variable_length_list[1] = -2.0; : ... : ... : s->variable_length_list[13] = 1456.0; : s->variable_length_list[14] = 1234.0; @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ALLOC_VAR_SIZED_STRUCT( ptr, element_type, n_elements ) \ ASSIGN_PTR(ptr) = alloc_memory_in_bytes( \ (size_t) (sizeof(*(ptr))+((size_t)(n_elements)-1) * sizeof(element_type)) \ _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : ALLOC2D @INPUT : n1 : n2 @OUTPUT : : ptr @RETURNS : @DESCRIPTION: Macro to allocate an n1 by n2 array, assigning : ptr. @METHOD : Allocates a single chunk size n1 by n2, and a list of size n1 : pointers, which are each assigned to point into the single : chunk. Therefore, only 2 malloc's are required. @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ALLOC2D( ptr, n1, n2 ) \ ASSIGN_PTR(ptr) = alloc_memory_2d( (size_t) (n1), (size_t) (n2), \ sizeof(**(ptr)) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : FREE2D @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Macro to free the 2 dimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define FREE2D( ptr ) \ free_memory_2d( (void ***) &(ptr) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : ALLOC3D @INPUT : n1 : n2 : n3 @OUTPUT : : ptr @RETURNS : @DESCRIPTION: Macro to allocate an n1 by n2 by n3 array, assigning : ptr. @METHOD : Similar to ALLOC2D, this requires only 3 mallocs. @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ALLOC3D( ptr, n1, n2, n3 ) \ ASSIGN_PTR(ptr) = alloc_memory_3d( (size_t) (n1), (size_t) (n2), \ (size_t) (n3), sizeof(***(ptr)) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : FREE3D @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees a 3 dimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define FREE3D( ptr ) \ free_memory_3d( (void ****) &(ptr) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : ALLOC4D @INPUT : n1 : n2 : n3 : n4 @OUTPUT : : ptr @RETURNS : @DESCRIPTION: Macro to allocate an n1 by n2 by n3 by n4 array, assigning : ptr. @METHOD : Similar to ALLOC2D, this requires only 4 mallocs. @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ALLOC4D( ptr, n1, n2, n3, n4 ) \ ASSIGN_PTR(ptr) = alloc_memory_4d( (size_t) (n1), (size_t) (n2), \ (size_t) (n3), (size_t) (n4), \ sizeof(****(ptr)) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : FREE4D @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees a 4 dimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define FREE4D( ptr ) \ free_memory_4d( (void *****) &(ptr) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : ALLOC5D @INPUT : n1 : n2 : n3 : n4 : n5 @OUTPUT : : ptr @RETURNS : @DESCRIPTION: Macro to allocate an n1 by n2 by n3 by n4 by n5 array, assigning : ptr. @METHOD : Similar to ALLOC2D, this requires only 5 mallocs. @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ALLOC5D( ptr, n1, n2, n3, n4, n5 ) \ ASSIGN_PTR(ptr) = alloc_memory_5d( (size_t) (n1), (size_t) (n2), \ (size_t) (n3), (size_t) (n4), (size_t) (n5), \ sizeof(*****(ptr)) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : FREE5D @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees a 5 dimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define FREE5D( ptr ) \ free_memory_5d( (void ******) &(ptr) _ALLOC_SOURCE_LINE ) #endif /* !VIO_PREFIX_NAMES */ #endif minc-2.2.00/volume_io/Include/volume_io/arrays.h0000644000265600003100000001513512027132664016500 00000000000000#ifndef DEF_ARRAYS #define DEF_ARRAYS /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/arrays.h,v 1.13 2004-10-04 20:23:51 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : arrays.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Macros for adding to and deleting from arrays. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include #define DEFAULT_CHUNK_SIZE 100 /* ----------------------------- MNI Header ----------------------------------- @NAME : SET_ARRAY_SIZE @INPUT : array previous_n_elems new_n_elems - desired new array size chunk_size @OUTPUT : @RETURNS : @DESCRIPTION: Sets the number of items allocated in the array to a multiple of : chunk_size larger than new_n_elems @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define SET_ARRAY_SIZE( array, previous_n_elems, new_n_elems, chunk_size ) \ set_array_size( (void **) (&(array)), sizeof(*(array)), \ (size_t) (previous_n_elems), \ (size_t) (new_n_elems), \ (size_t) (chunk_size) _ALLOC_SOURCE_LINE ) /* ----------------------------- MNI Header ----------------------------------- @NAME : ADD_ELEMENT_TO_ARRAY @INPUT : array : the array to add to : n_elems : current number of items in the array : elem_to_add : the item to add : chunk_size : the chunk_size for allocation @OUTPUT : @RETURNS : @DESCRIPTION: Adds an element to the end of an array, and increments the n_elems @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ADD_ELEMENT_TO_ARRAY( array, n_elems, elem_to_add, chunk_size) \ { \ SET_ARRAY_SIZE( array, n_elems, (n_elems)+1, chunk_size ); \ (array) [(n_elems)] = (elem_to_add); \ ++(n_elems); \ } /* ----------------------------- MNI Header ----------------------------------- @NAME : DELETE_ELEMENT_FROM_ARRAY @INPUT : array : the array to add to : n_elems : current number of items in the array : index_to_remove : the index of the element to delete : chunk_size : the chunk_size for allocation @OUTPUT : @RETURNS : @DESCRIPTION: Deletes an element from an array, sliding down subsequent : elements, and decrements the n_elems @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define DELETE_ELEMENT_FROM_ARRAY( array, n_elems, index_to_remove, chunk_size ) \ { \ (void) memmove( (void *) ((unsigned long) (array) + \ (unsigned long) (index_to_remove) * (unsigned long) sizeof(*(array))), \ (void *) ((unsigned long) (array) + \ ((unsigned long) (index_to_remove)+1)* (unsigned long) sizeof(*(array))),\ ((size_t) (n_elems) - (size_t) (index_to_remove) - 1) * sizeof(*(array)) );\ \ --(n_elems); \ \ SET_ARRAY_SIZE( array, (n_elems)+1, n_elems, chunk_size); \ } /* ----------------------------- MNI Header ----------------------------------- @NAME : ADD_ELEMENT_TO_ARRAY_WITH_SIZE @INPUT : array : n_alloced : n_elems : elem_to_add : chunk_size @OUTPUT : @RETURNS : @DESCRIPTION: Adds an element to an array where a separate n_allocated and : n_elems is maintained. n_allocated will always be greater than : or equal to n_elems. This routine is useful so that you don't : have to call SET_ARRAY_SIZE everytime you remove an element, : as in done in DELETE_ELEMENT_FROM_ARRAY @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define ADD_ELEMENT_TO_ARRAY_WITH_SIZE( array, n_alloced, n_elems, elem_to_add, chunk_size ) \ { \ if( (n_elems) >= (n_alloced) ) \ { \ SET_ARRAY_SIZE( array, n_alloced, (n_elems) + 1, chunk_size );\ (n_alloced) = (n_elems)+1; \ } \ (array) [(n_elems)] = (elem_to_add); \ ++(n_elems); \ } #endif /* DEF_ARRAYS */ minc-2.2.00/volume_io/Include/volume_io/basic.h0000644000265600003100000001347112027132664016261 00000000000000#ifndef DEF_BASIC #define DEF_BASIC /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/basic.h,v 1.35 2005-05-19 21:19:27 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : basic.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A set of macros and definitions useful for all MNI programs. @METHOD : @GLOBALS : @CALLS : @CREATED : July 15, 1991 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include #include #include #ifdef __sgi #include /* --- for memcpy, etc. */ #else #include /* --- for memcpy, etc. */ #endif #include #include /* --------- define TRUE and FALSE ------------------------ */ #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* These are the internal typedefs, which are aliased to their "classic" * volume_io names below, if the new VIO_PREFIX_NAMES macro is set to * zero. */ typedef char *VIO_STR; typedef int VIO_BOOL; typedef double VIO_Real; typedef signed char VIO_SCHAR; typedef unsigned char VIO_UCHAR; typedef enum { OK, ERROR, INTERNAL_ERROR, END_OF_FILE, QUIT } VIO_Status; #if !VIO_PREFIX_NAMES /* Play nice with others */ #ifndef __cplusplus #ifndef private #define private static #endif /* private */ #ifndef public #define public #endif /* public */ #ifndef semiprivate #define semiprivate #endif /* semiprivate */ #endif /* __cplusplus */ #define OFF FALSE #define ON TRUE /* --------- macro to determine the size of a static array, e.g., int array[] = { 1, 3, 9, 5 }; ------------ */ #define SIZEOF_STATIC_ARRAY( array ) \ (int) ( sizeof(array) / sizeof((array)[0])) /* --------- interpolate between a and b ------------------- */ #define INTERPOLATE( alpha, a, b ) ((a) + (alpha) * ((b) - (a))) /* --------- PI, and angles -------------------------------- */ #define PI M_PI /* from math.h */ #define DEG_TO_RAD (PI / 180.0) #define RAD_TO_DEG (180.0 / PI) /* --------- Absolute value, min, and max. Bear in mind that these may evaluate an expression multiple times, i.e., ABS( x - y ), and therefore may be inefficient, or incorrect, i.e, ABS( ++x ); ------------------ */ #define ABS( x ) ( ((x) > 0) ? (x) : (-(x)) ) #define FABS( x ) fabs( (double) x ) #define SIGN( x ) ( ((x) > 0) ? 1 : (((x) < 0) ? -1 : 0) ) #define FSIGN( x ) ( ((x) > 0.0) ? 1.0 : (((x) < 0.0) ? -1.0 : 0.0) ) #ifdef MAX #undef MAX #endif #define MAX( x, y ) ( ((x) >= (y)) ? (x) : (y) ) #define MAX3( x, y, z ) ( ((x) >= (y)) ? MAX( x, z ) : MAX( y, z ) ) #ifdef MIN #undef MIN #endif #define MIN( x, y ) ( ((x) <= (y)) ? (x) : (y) ) #define MIN3( x, y, z ) ( ((x) <= (y)) ? MIN( x, z ) : MIN( y, z ) ) /* --------- gets the address of a 2-d array element in a 1-d array ----- */ #define IJ( i, j, nj ) ( (i) * (nj) + (j) ) /* --------- gets the address of a 3-d array element in a 1-d array ----- */ #define IJK( i, j, k, nj, nk ) ( (k) + (nk) * ((j) + (nj) * (i)) ) /* --------- environment variables -------------------------- */ #define ENV_EXISTS( env ) ( getenv(env) != (char *) 0 ) /* --------- C and LINT stuff -------------------------- */ #ifdef __STDC__ #define GLUE(x,y) x##y #define GLUE3(x,y,z) x##y##z #define CREATE_STRING(x) #x #else #define GLUE(x,y) x/**/y #define GLUE3(x,y,z) x/**/y/**/z #define CREATE_STRING(x) "x" #endif /* Basic types */ typedef VIO_SCHAR Smallest_int; typedef VIO_UCHAR unsigned_byte; typedef VIO_BOOL BOOLEAN; typedef VIO_Real Real; typedef VIO_STR STRING; typedef VIO_Status Status; #define REAL_MAX DBL_MAX /* --------------- */ #define IS_INT( x ) ((double) (x) == (double) ((int) (x))) #define FLOOR( x ) ((int) floor(x)) #define ROUND( x ) FLOOR( (double) (x) + 0.5 ) #define CEILING( x ) ((int) ceil(x)) #define FRACTION( x ) ((double) (x) - (double) FLOOR(x)) /* for loops */ #define for_less( i, start, end ) for( (i) = (start); (i) < (end); ++(i) ) #define for_down( i, start, end ) for( (i) = (start); (i) >= (end); --(i)) #define for_inclusive( i, start, end ) \ for( (i) = (start); (i) <= (end); ++(i) ) #define for_enum( e, max, type ) \ for( (e) = (type) 0; (e) < (max); (e) = (type) ((int) (e)+1) ) #define CONVERT_INTEGER_RANGE( x1, min1, max1, min2, max2 ) \ ((min2) + (2 * (x1) + 1 - 2 * (min1)) * ((max2) - (min2) + 1) / \ ((max1) - (min1) + 1) / 2) #define HANDLE_INTERNAL_ERROR( X ) \ handle_internal_error( X ) #endif /* !VIO_PREFIX_NAMES */ #endif /* DEF_BASIC */ minc-2.2.00/volume_io/Include/volume_io/def_math.h0000644000265600003100000000174712027132664016752 00000000000000#ifndef DEF_MATH #define DEF_MATH /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/def_math.h,v 1.9 2004-10-04 20:23:51 bert Exp $ ---------------------------------------------------------------------------- */ #include #endif minc-2.2.00/volume_io/Include/volume_io/files.h0000644000265600003100000000330012027132664016270 00000000000000#ifndef DEF_FILES #define DEF_FILES /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/files.h,v 1.10 2005-05-19 21:19:27 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : files.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Types for use with the general file io routines of the library. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include #include typedef enum { ASCII_FORMAT, BINARY_FORMAT } VIO_File_formats; typedef enum { READ_FILE, WRITE_FILE, APPEND_FILE } VIO_IO_types; #if !VIO_PREFIX_NAMES typedef VIO_File_formats File_formats; typedef VIO_IO_types IO_types; #endif /* !VIO_PREFIX_NAMES */ #endif /* DEF_FILES */ minc-2.2.00/volume_io/Include/volume_io/geom_structs.h0000644000265600003100000002202412027132664017710 00000000000000#ifndef DEF_GEOM_STRUCTS #define DEF_GEOM_STRUCTS /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/geom_structs.h,v 1.24 2007-12-03 14:19:35 rotor Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : geom_structs.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Types and macros for accessing points, vectors, colours, etc. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ /* Define the structure of a point in world coordinates */ #define VIO_N_DIMENSIONS 3 #define VIO_X 0 #define VIO_Y 1 #define VIO_Z 2 #if !VIO_PREFIX_NAMES /* Don't define commonly used symbols */ #define N_DIMENSIONS VIO_N_DIMENSIONS #define X VIO_X #define Y VIO_Y #define Z VIO_Z #endif /* !VIO_PREFIX_NAMES */ /* ----------------------------- MNI Header ----------------------------------- @NAME : Point type @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A 3D point type and macros for manipulation. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ typedef float VIO_Point_coord_type; typedef struct { VIO_Point_coord_type coords[VIO_N_DIMENSIONS]; } VIO_Point; /* --- access the given coordinate of the point */ #define Point_coord( point, coord ) ((point).coords[coord]) /* --- access x, y, or z coordinate of the point */ #define Point_x( point ) Point_coord( point, VIO_X ) #define Point_y( point ) Point_coord( point, VIO_Y ) #define Point_z( point ) Point_coord( point, VIO_Z ) /* --- assign all 3 coordinates of the point */ #define fill_Point( point, x, y, z ) \ { \ Point_x(point) = (VIO_Point_coord_type) (x); \ Point_y(point) = (VIO_Point_coord_type) (y); \ Point_z(point) = (VIO_Point_coord_type) (z); \ } /* ----------------------------- MNI Header ----------------------------------- @NAME : Vector type @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A 3D vector type and macros for manipulation. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ typedef struct { VIO_Point_coord_type coords[VIO_N_DIMENSIONS]; } VIO_Vector; /* --- access the given coordinate of the vector */ #define Vector_coord( vector, coord ) ((vector).coords[coord]) /* --- access x, y, or z coordinate of the vector */ #define Vector_x( vector ) Vector_coord( vector, VIO_X ) #define Vector_y( vector ) Vector_coord( vector, VIO_Y ) #define Vector_z( vector ) Vector_coord( vector, VIO_Z ) /* --- assign all 3 coordinates of the vector */ #define fill_Vector( vector, x, y, z ) \ { \ Vector_x(vector) = (VIO_Point_coord_type) (x); \ Vector_y(vector) = (VIO_Point_coord_type) (y); \ Vector_z(vector) = (VIO_Point_coord_type) (z); \ } /* ----------------------------- MNI Header ----------------------------------- @NAME : Colour type @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A 4 by 8-bit component colour type and macros for manipulation. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ /* bert - redefined 'Colour' to be an 'int' instead of a 'long'. Jason * Lerch found that MNI-Display was displaying garbled images when built * for 64 bits on the SGI. * * Apparently the graphics functions in volume_io rely on Colour being * exactly 4 bytes, so you get weird results on 64-bit architectures * if Colour is a 'long'. */ typedef unsigned int VIO_Colour; #define MULT_COLOURS( prod, c1, c2 ) \ { \ VIO_Real r, g, b, r1, g1, b1, r2, g2, b2; \ r1 = get_Colour_r_0_1(c1); \ g1 = get_Colour_g_0_1(c1); \ b1 = get_Colour_b_0_1(c1); \ r2 = get_Colour_r_0_1(c2); \ g2 = get_Colour_g_0_1(c2); \ b2 = get_Colour_b_0_1(c2); \ r = r1 * r2; \ g = g1 * g2; \ b = b1 * b2; \ (prod) = make_rgba_Colour_0_1( r, g, b, get_Colour_a_0_1(c1) ); \ } /* --- component-wise sum of two colours, returned in sum */ #define ADD_COLOURS( sum, c1, c2 ) \ { \ int _r, _g, _b, _r1, _g1, _b1, _r2, _g2, _b2; \ _r1 = get_Colour_r(c1); \ _g1 = get_Colour_g(c1); \ _b1 = get_Colour_b(c1); \ _r2 = get_Colour_r(c2); \ _g2 = get_Colour_g(c2); \ _b2 = get_Colour_b(c2); \ _r = _r1 + _r2; \ _g = _g1 + _g2; \ _b = _b1 + _b2; \ if( _r > 255 ) _r = 255; \ if( _g > 255 ) _g = 255; \ if( _b > 255 ) _b = 255; \ (sum) = make_rgba_Colour( _r, _g, _b, get_Colour_a(c1) ); \ } /* ----------------------------- MNI Header ----------------------------------- @NAME : Surfprop type @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A Surface property type and macros for manipulation. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ typedef float VIO_Spr_type; typedef struct { VIO_Spr_type a, d, s; VIO_Spr_type se; VIO_Spr_type t; } VIO_Surfprop; /* --- access the given element of the surface property */ #define Surfprop_a( surfprop ) ((surfprop).a) #define Surfprop_d( surfprop ) ((surfprop).d) #define Surfprop_s( surfprop ) ((surfprop).s) #define Surfprop_se( surfprop ) ((surfprop).se) #define Surfprop_t( surfprop ) ((surfprop).t) /* --- assign all elements of the structure, s */ #define fill_Surfprop( s, amb, diff, spec, spec_exp, trans ) \ { \ Surfprop_a(s) = (Spr_type) (amb); \ Surfprop_d(s) = (Spr_type) (diff); \ Surfprop_s(s) = (Spr_type) (spec); \ Surfprop_se(s) = (Spr_type) (spec_exp); \ Surfprop_t(s) = (Spr_type) (trans); \ } /* ----------------------------- MNI Header ----------------------------------- @NAME : Transform_2d type @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A 2D transform type and macros for element access. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ typedef double VIO_Transform_elem_type; typedef struct { VIO_Transform_elem_type m2d[2][3]; } VIO_Transform_2d; #define Transform_2d_elem( t, i, j ) ((t).m2d[i][j]) /* ----------------------------- MNI Header ----------------------------------- @NAME : Transform type @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A 3D transform type and macros for element access. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ typedef struct { VIO_Transform_elem_type m[4][4]; } VIO_Transform; #define Transform_elem( t, i, j ) ((t).m[j][i]) #if !VIO_PREFIX_NAMES typedef VIO_Transform Transform; typedef VIO_Vector Vector; typedef VIO_Colour Colour; typedef VIO_Transform_2d Transform_2d; typedef VIO_Transform_elem_type Transform_elem_type; typedef VIO_Spr_type Spr_type; typedef VIO_Surfprop Surfprop; /* Th 'Point' typedef is annoying to Mac OS users, since Point has been * a basic type on Macs since the beginning. Testing __MACTYPES__ should * work at least with the OS X codebase, I don't know if it existed in * earlier versions of the MacTypes.h header. */ #ifndef __MACTYPES__ typedef VIO_Point Point; #endif /* __MACTYPES__ not defined */ typedef VIO_Point_coord_type Point_coord_type; #endif /* !VIO_PREFIX_NAMES */ #endif /* DEF_GEOM_STRUCTS */ minc-2.2.00/volume_io/Include/volume_io/geometry.h0000644000265600003100000002140512027132664017027 00000000000000#ifndef DEF_GEOMETRY #define DEF_GEOMETRY /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/geometry.h,v 1.12 2004-10-04 20:23:51 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : geometry.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Macros for performing geometric operations on points and vectors. For most macros, the return value is the first argument. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include #include #define Point_coord_cast(x) ((VIO_Point_coord_type) (x)) #define Real_cast(x) ((VIO_Real) (x)) #define RPoint_x( p ) Real_cast(Point_x(p)) #define RPoint_y( p ) Real_cast(Point_y(p)) #define RPoint_z( p ) Real_cast(Point_z(p)) #define RPoint_coord( p, c ) Real_cast(Point_coord(p,c)) #define RVector_x( p ) Real_cast(Vector_x(p)) #define RVector_y( p ) Real_cast(Vector_y(p)) #define RVector_z( p ) Real_cast(Point_z(p)) #define RVector_coord( p, c ) Real_cast(Vector_coord(p,c)) /* --- private point and vector operations for use by public routines */ #define POINT_SCALAR_EXP( result, v, op, scalar ) \ { \ Point_x(result) = Point_coord_cast( RPoint_x(v) op Real_cast((scalar)) ); \ Point_y(result) = Point_coord_cast( RPoint_y(v) op Real_cast((scalar)) ); \ Point_z(result) = Point_coord_cast( RPoint_z(v) op Real_cast((scalar)) ); \ } #define POINT_EXP2( result, v1, op, v2 ) \ { \ Point_x(result) = Point_coord_cast( RPoint_x(v1) op RPoint_x(v2) ); \ Point_y(result) = Point_coord_cast( RPoint_y(v1) op RPoint_y(v2) ); \ Point_z(result) = Point_coord_cast( RPoint_z(v1) op RPoint_z(v2) ); \ } #define POINT_VECTOR_EXP2( result, p, op, v ) \ { \ Point_x(result) = Point_coord_cast( RPoint_x(p) op RVector_x(v) ); \ Point_y(result) = Point_coord_cast( RPoint_y(p) op RVector_y(v) ); \ Point_z(result) = Point_coord_cast( RPoint_z(p) op RVector_z(v) ); \ } #define VECTOR_SCALAR_EXP( result, v, op, scalar ) \ { \ Vector_x(result) = Point_coord_cast( RVector_x(v) op Real_cast(scalar) ); \ Vector_y(result) = Point_coord_cast( RVector_y(v) op Real_cast(scalar) ); \ Vector_z(result) = Point_coord_cast( RVector_z(v) op Real_cast(scalar) ); \ } #define VECTOR_EXP2( result, v1, op, v2 ) \ { \ Vector_x(result) = Point_coord_cast( RVector_x(v1) op RVector_x(v2) ); \ Vector_y(result) = Point_coord_cast( RVector_y(v1) op RVector_y(v2) ); \ Vector_z(result) = Point_coord_cast( RVector_z(v1) op RVector_z(v2) ); \ } /* --- interpolate between two points, 0 results in p1, 1 results in p2 */ #define INTERPOLATE_POINTS( interp, p1, p2, alpha ) \ { \ Point_x(interp) = Point_coord_cast( (1.0-Real_cast(alpha))*RPoint_x(p1) + \ Real_cast(alpha)*RPoint_x(p2) );\ Point_y(interp) = Point_coord_cast( (1.0-Real_cast(alpha))*RPoint_y(p1) + \ Real_cast(alpha)*RPoint_y(p2) );\ Point_z(interp) = Point_coord_cast( (1.0-Real_cast(alpha))*RPoint_z(p1) + \ Real_cast(alpha)*RPoint_z(p2) );\ } /* --- interpolate between two vectors, 0 results in v1, 1 results in v2 */ #define INTERPOLATE_VECTORS( interp, v1, v2, alpha ) \ { \ Vector_x(interp)= Point_coord_cast( (1.0-Real_cast(alpha))*RVector_x(v1) + \ Real_cast(alpha)*RVector_x(v2) );\ Vector_y(interp)= Point_coord_cast( (1.0-Real_cast(alpha))*RVector_y(v1) + \ Real_cast(alpha)*RVector_y(v2) );\ Vector_z(interp)= Point_coord_cast( (1.0-Real_cast(alpha))*RVector_z(v1) + \ Real_cast(alpha)*RVector_z(v2) );\ } /* --- get a point on a ray, returning it as 'point' */ #define GET_POINT_ON_RAY( point, origin, direction, distance ) \ { \ Vector_x(point)= Point_coord_cast( RPoint_x(origin) + \ Real_cast(distance)*RVector_x(direction) );\ Vector_y(point)= Point_coord_cast( RPoint_y(origin) + \ Real_cast(distance)*RVector_y(direction) );\ Vector_z(point)= Point_coord_cast( RPoint_z(origin) + \ Real_cast(distance)*RVector_z(direction) );\ } /* --- add and subtract points and vectors, returning correct type */ #define ADD_POINTS( sum, p1, p2 ) POINT_EXP2( sum, p1, +, p2 ) #define ADD_VECTORS( sum, v1, v2 ) VECTOR_EXP2( sum, v1, +, v2 ) #define ADD_POINT_VECTOR( sum, p, v ) POINT_VECTOR_EXP2( sum, p, +, v ) #define SUB_POINTS( diff, p1, p2 ) POINT_EXP2( diff, p1, -, p2 ) #define SUB_VECTORS( diff, v1, v2 ) VECTOR_EXP2( diff, v1, -, v2 ) #define SUB_POINT_VECTOR( diff, p, v ) POINT_VECTOR_EXP2( diff, p, -, v ) /* --- return the dot product of two points, two vectors, or one of each */ #define DOT_POINTS( p1, p2 ) \ ( RPoint_x(p1)*RPoint_x(p2) + \ RPoint_y(p1)*RPoint_y(p2) + \ RPoint_z(p1)*RPoint_z(p2) ) #define DOT_VECTORS( v1, v2 ) \ ( RVector_x(v1)*RVector_x(v2) + \ RVector_y(v1)*RVector_y(v2) + \ RVector_z(v1)*RVector_z(v2) ) #define DOT_POINT_VECTOR( p, v ) \ ( RPoint_x(p)*RVector_x(v) + \ RPoint_y(p)*RVector_y(v) + \ RPoint_z(p)*RVector_z(v) ) /* --- component-wise scaling of points and vectors, result is in ps/vs */ #define SCALE_POINT( ps, p, scale ) POINT_SCALAR_EXP( ps, p, *, scale ) #define SCALE_VECTOR( vs, v, scale ) VECTOR_SCALAR_EXP( vs, v, *, scale ) /* --- return the magnitude of a vector */ #define MAGNITUDE( v ) Real_cast(sqrt( DOT_VECTORS(v,v) )) /* --- set vn to the value of the vector v, normalized to length 1 */ #define NORMALIZE_VECTOR( vn, v ) \ { \ VIO_Real _mag_; \ \ _mag_ = MAGNITUDE( v ); \ if( _mag_ != 0.0 ) \ SCALE_VECTOR( vn, v, 1.0 / _mag_ ); \ } /* --- set c to the cross product of vectors v1 and v2 */ #define CROSS_VECTORS( c, v1, v2 ) \ { \ Vector_x(c) = Point_coord_cast( RVector_y(v1) * RVector_z(v2) - \ RVector_y(v2) * RVector_z(v1) ); \ Vector_y(c) = Point_coord_cast( RVector_z(v1) * RVector_x(v2) - \ RVector_z(v2) * RVector_x(v1) ); \ Vector_z(c) = Point_coord_cast( RVector_x(v1) * RVector_y(v2) - \ RVector_x(v2) * RVector_y(v1) ); \ } /* --- returns TRUE if the points/vectors are equal */ #define EQUAL_POINTS( p1, p2 ) \ ( Point_x(p1) == Point_x(p2) && \ Point_y(p1) == Point_y(p2) && \ Point_z(p1) == Point_z(p2) ) #define EQUAL_VECTORS( v1, v2 ) \ ( Vector_x(v1) == Vector_x(v2) && \ Vector_y(v1) == Vector_y(v2) && \ Vector_z(v1) == Vector_z(v2) ) /* --- given a plane normal, plane distance, and a point, returns the distance of the point from the plane, in fractions of the normal length */ #define DIST_FROM_PLANE( normal, d, point ) \ ( DOT_POINT_VECTOR(point,normal) - Real_cast(d) ) /* --- converts the 'point' to a 'vector' */ #define CONVERT_POINT_TO_VECTOR( vector, point ) \ fill_Vector( vector, \ Point_x(point), Point_y(point), Point_z(point) ) /* --- converts the 'vector' to a 'point' */ #define CONVERT_VECTOR_TO_POINT( point, vector ) \ fill_Point( point, \ Vector_x(vector), Vector_y(vector), Vector_z(vector) ) #endif /* DEF_GEOMETRY */ minc-2.2.00/volume_io/Include/volume_io/multidim.h0000644000265600003100000002653412027132664017030 00000000000000#ifndef DEF_MULTI_DIM #define DEF_MULTI_DIM /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/multidim.h,v 1.7 2005-05-19 21:19:27 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : multidim.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Multidimensional variable type arrays. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 14, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define VIO_MAX_DIMENSIONS 5 /* -------------------------- Data_types ------------------------- */ typedef enum { NO_DATA_TYPE, UNSIGNED_BYTE, SIGNED_BYTE, UNSIGNED_SHORT, SIGNED_SHORT, UNSIGNED_INT, SIGNED_INT, FLOAT, DOUBLE, MAX_DATA_TYPE } VIO_Data_types; typedef struct { int n_dimensions; int sizes[VIO_MAX_DIMENSIONS]; VIO_Data_types data_type; void *data; } VIO_multidim_array; /* ------------------------- set value ---------------------------- */ /* --- private macros */ #define SET_ONE( array, type, asterisks, subscripts, value ) \ (((type asterisks) ((array).data)) subscripts = (type) (value)) #define SET_GIVEN_DIM( array, asterisks, subscripts, value ) \ switch( (array).data_type ) \ { \ case UNSIGNED_BYTE: \ SET_ONE( array, unsigned char, asterisks, subscripts, value);\ break; \ case SIGNED_BYTE: \ SET_ONE( array, signed char, asterisks, subscripts, value);\ break; \ case UNSIGNED_SHORT: \ SET_ONE( array, unsigned short, asterisks, subscripts, value);\ break; \ case SIGNED_SHORT: \ SET_ONE( array, signed short, asterisks, subscripts, value);\ break; \ case UNSIGNED_INT: \ SET_ONE( array, unsigned int, asterisks, subscripts, value);\ break; \ case SIGNED_INT: \ SET_ONE( array, signed int, asterisks, subscripts, value);\ break; \ case FLOAT: \ SET_ONE( array, float, asterisks, subscripts, value);\ break; \ case DOUBLE: \ SET_ONE( array, double, asterisks, subscripts, value);\ break; \ } #define GET_MULTIDIM_TYPE_1D( array, type, v0 ) \ (((type *) ((array).data)) [v0]) #define GET_MULTIDIM_TYPE_2D( array, type, v0, v1 ) \ (((type **) ((array).data)) [v0][v1]) #define GET_MULTIDIM_TYPE_3D( array, type, v0, v1, v2 ) \ (((type ***) ((array).data)) [v0][v1][v2]) #define GET_MULTIDIM_TYPE_4D( array, type, v0, v1, v2, v3 ) \ (((type ****) ((array).data)) [v0][v1][v2][v3]) #define GET_MULTIDIM_TYPE_5D( array, type, v0, v1, v2, v3, v4 ) \ (((type *****) ((array).data)) [v0][v1][v2][v3][v4]) #define SET_MULTIDIM_TYPE_1D( array, type, v0, value ) \ (GET_MULTIDIM_TYPE_1D( array, type, v0 ) = (type) (value)) #define SET_MULTIDIM_TYPE_2D( array, type, v0, v1, value ) \ (GET_MULTIDIM_TYPE_2D( array, type, v0, v1 ) = (type) (value)) #define SET_MULTIDIM_TYPE_3D( array, type, v0, v1, v2, value ) \ (GET_MULTIDIM_TYPE_3D( array, type, v0, v1, v2 ) = (type) (value)) #define SET_MULTIDIM_TYPE_4D( array, type, v0, v1, v2, v3, value ) \ (GET_MULTIDIM_TYPE_4D( array, type, v0, v1, v2, v3 ) = (type) (value)) #define SET_MULTIDIM_TYPE_5D( array, type, v0, v1, v2, v3, v4, value ) \ (GET_MULTIDIM_TYPE_5D( array, type, v0, v1, v2, v3, v4 ) = (type) (value)) /* --- public macros to set the [x][y]... voxel of 'array' to 'value' */ #define SET_MULTIDIM_1D( array, x, value ) \ SET_GIVEN_DIM( array, *, [x], value ) #define SET_MULTIDIM_2D( array, x, y, value ) \ SET_GIVEN_DIM( array, **, [x][y], value ) #define SET_MULTIDIM_3D( array, x, y, z, value ) \ SET_GIVEN_DIM( array, ***, [x][y][z], value ) #define SET_MULTIDIM_4D( array, x, y, z, t, value ) \ SET_GIVEN_DIM( array, ****, [x][y][z][t], value ) #define SET_MULTIDIM_5D( array, x, y, z, t, v, value ) \ SET_GIVEN_DIM( array, *****, [x][y][z][t][v], value ) /* --- same as previous, but don't have to know dimensions of volume */ #define SET_MULTIDIM( array, x, y, z, t, v, value ) \ switch( (array).n_dimensions ) \ { \ case 1: SET_MULTIDIM_1D( array, x, value ); break; \ case 2: SET_MULTIDIM_2D( array, x, y, value ); break; \ case 3: SET_MULTIDIM_3D( array, x, y, z, value ); break; \ case 4: SET_MULTIDIM_4D( array, x, y, z, t, value ); break; \ case 5: SET_MULTIDIM_5D( array, x, y, z, t, v, value ); break; \ } /* ------------------------- get multidim value ------------------------ */ /* --- private macros */ #define GET_ONE( value, vtype, array, type, asterisks, subscripts ) \ (value) = vtype (((type asterisks) ((array).data)) subscripts) #define GET_GIVEN_DIM( value, vtype, array, asterisks, subscripts ) \ switch( (array).data_type ) \ { \ case UNSIGNED_BYTE: \ GET_ONE( value, vtype, array, unsigned char, asterisks, subscripts );\ break; \ case SIGNED_BYTE: \ GET_ONE( value, vtype, array, signed char, asterisks, subscripts );\ break; \ case UNSIGNED_SHORT: \ GET_ONE( value, vtype, array, unsigned short, asterisks, subscripts );\ break; \ case SIGNED_SHORT: \ GET_ONE( value, vtype, array, signed short, asterisks, subscripts );\ break; \ case UNSIGNED_INT: \ GET_ONE( value, vtype, array, unsigned int, asterisks, subscripts );\ break; \ case SIGNED_INT: \ GET_ONE( value, vtype, array, signed int, asterisks, subscripts );\ break; \ case FLOAT: \ GET_ONE( value, vtype, array, float, asterisks, subscripts );\ break; \ case DOUBLE: \ GET_ONE( value, vtype, array, double, asterisks, subscripts );\ break; \ } /* --- public macros to place the [x][y]...'th voxel of 'array' in 'value' */ #define GET_MULTIDIM_1D( value, vtype, array, x ) \ GET_GIVEN_DIM( value, vtype, array, *, [x] ) #define GET_MULTIDIM_2D( value, vtype, array, x, y ) \ GET_GIVEN_DIM( value, vtype, array, **, [x][y] ) #define GET_MULTIDIM_3D( value, vtype, array, x, y, z ) \ GET_GIVEN_DIM( value, vtype, array, ***, [x][y][z] ) #define GET_MULTIDIM_4D( value, vtype, array, x, y, z, t ) \ GET_GIVEN_DIM( value, vtype, array, ****, [x][y][z][t] ) #define GET_MULTIDIM_5D( value, vtype, array, x, y, z, t, v ) \ GET_GIVEN_DIM( value, vtype, array, *****, [x][y][z][t][v] ) /* --- same as previous, but no need to know array dimensions */ #define GET_MULTIDIM( value, vtype, array, x, y, z, t, v ) \ switch( (array).n_dimensions ) \ { \ case 1: GET_MULTIDIM_1D( value, vtype, array, x ); break; \ case 2: GET_MULTIDIM_2D( value, vtype, array, x, y ); break; \ case 3: GET_MULTIDIM_3D( value, vtype, array, x, y, z ); break; \ case 4: GET_MULTIDIM_4D( value, vtype, array, x, y, z, t ); break; \ case 5: GET_MULTIDIM_5D( value, vtype, array, x, y, z, t, v ); break; \ } /* ------------------------- get multidim ptr ------------------------ */ /* --- private macros */ #define GET_ONE_PTR( ptr, array, type, asterisks, subscripts ) \ (ptr) = (void *) (&(((type asterisks) ((array).data)) subscripts)) #define GET_GIVEN_DIM_PTR( ptr, array, asterisks, subscripts ) \ switch( (array).data_type ) \ { \ case UNSIGNED_BYTE: \ GET_ONE_PTR( ptr, array, unsigned char, asterisks, subscripts );\ break; \ case SIGNED_BYTE: \ GET_ONE_PTR( ptr, array, signed char, asterisks, subscripts );\ break; \ case UNSIGNED_SHORT: \ GET_ONE_PTR( ptr, array, unsigned short, asterisks, subscripts );\ break; \ case SIGNED_SHORT: \ GET_ONE_PTR( ptr, array, signed short, asterisks, subscripts );\ break; \ case UNSIGNED_INT: \ GET_ONE_PTR( ptr, array, unsigned int, asterisks, subscripts );\ break; \ case SIGNED_INT: \ GET_ONE_PTR( ptr, array, signed int, asterisks, subscripts );\ break; \ case FLOAT: \ GET_ONE_PTR( ptr, array, float, asterisks, subscripts );\ break; \ case DOUBLE: \ GET_ONE_PTR( ptr, array, double, asterisks, subscripts );\ break; \ } /* --- public macros to return a pointer to the [x][y]'th voxel of the 'array', and place it in 'ptr' */ #define GET_MULTIDIM_PTR_1D( ptr, array, x ) \ GET_GIVEN_DIM_PTR( ptr, array, *, [x] ) #define GET_MULTIDIM_PTR_2D( ptr, array, x, y ) \ GET_GIVEN_DIM_PTR( ptr, array, **, [x][y] ) #define GET_MULTIDIM_PTR_3D( ptr, array, x, y, z ) \ GET_GIVEN_DIM_PTR( ptr, array, ***, [x][y][z] ) #define GET_MULTIDIM_PTR_4D( ptr, array, x, y, z, t ) \ GET_GIVEN_DIM_PTR( ptr, array, ****, [x][y][z][t] ) #define GET_MULTIDIM_PTR_5D( ptr, array, x, y, z, t, v ) \ GET_GIVEN_DIM_PTR( ptr, array, *****, [x][y][z][t][v] ) /* --- same as previous, but no need to know array dimensions */ #define GET_MULTIDIM_PTR( ptr, array, x, y, z, t, v ) \ switch( (array).n_dimensions ) \ { \ case 1: GET_MULTIDIM_PTR_1D( ptr, array, x ); break; \ case 2: GET_MULTIDIM_PTR_2D( ptr, array, x, y ); break; \ case 3: GET_MULTIDIM_PTR_3D( ptr, array, x, y, z ); break; \ case 4: GET_MULTIDIM_PTR_4D( ptr, array, x, y, z, t ); break; \ case 5: GET_MULTIDIM_PTR_5D( ptr, array, x, y, z, t, v ); break; \ } #if !VIO_PREFIX_NAMES typedef VIO_multidim_array multidim_array; typedef VIO_Data_types Data_types; #define MAX_DIMENSIONS VIO_MAX_DIMENSIONS #endif /* !VIO_PREFIX_NAMES */ #endif minc-2.2.00/volume_io/Include/volume_io/progress.h0000644000265600003100000000375512027132664017050 00000000000000#ifndef DEF_PROGRESS #define DEF_PROGRESS /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/progress.h,v 1.10 2005-05-19 21:19:28 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : progress.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Defines type used for progress reporting. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include typedef struct { VIO_BOOL force_one_line; VIO_BOOL first_msg_displayed; VIO_BOOL one_line_flag; int n_steps; int n_dots_so_far; int total_n_dots; VIO_Real start_time; VIO_Real previous_time; VIO_Real update_rate; VIO_Real sum_xy; VIO_Real sum_xx; VIO_STR title; VIO_Real last_check_time; int check_every; int next_check_step; int last_check_step; } VIO_progress_struct; #if !VIO_PREFIX_NAMES typedef VIO_progress_struct progress_struct; #endif /* VIO_PREFIX_NAMES */ #endif /* DEF_PROGRESS */ minc-2.2.00/volume_io/Include/volume_io/string_funcs.h0000644000265600003100000000337512027132664017706 00000000000000#ifndef DEF_STRING #define DEF_STRING /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/string_funcs.h,v 1.9 2005-05-19 21:19:28 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : string_funcs.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Macros for string manipulations @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include #if !VIO_PREFIX_NAMES #define EXTREMELY_LARGE_STRING_SIZE 10000 #define END_OF_STRING ((char) 0) #define COPY_MEMORY( dest, src, n_items ) \ (void) memcpy( (void *) (dest), (void *) (src), \ (size_t) (n_items) * sizeof((src)[0]) ) #endif /* !VIO_PREFIX_NAMES */ #endif /* DEF_STRING */ minc-2.2.00/volume_io/Include/volume_io/system_dependent.h0000644000265600003100000000244612027132664020552 00000000000000#ifndef _DEF_SYSTEM_DEPENDENT_H /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #if HAVE_FLOAT_H #include #else #if HAVE_VALUES_H #include #ifndef DBL_MAX #define DBL_MAX MAXDOUBLE #endif /* DBL_MAX not defined */ #endif /* HAVE_VALUES_H */ #endif /* HAVE_FLOAT_H */ #include #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifdef __cplusplus #define ASSIGN_PTR( ptr ) (*((void **) &(ptr))) #else #define ASSIGN_PTR( ptr ) (ptr) #endif #endif minc-2.2.00/volume_io/Include/volume_io/transforms.h0000644000265600003100000000646312027132664017401 00000000000000#ifndef DEF_TAG_IO #define DEF_TAG_IO /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/transforms.h,v 1.14 2005-05-19 21:19:28 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : transforms.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Types for defining general transforms. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ /* --- the list of supported transform types */ typedef enum { LINEAR, THIN_PLATE_SPLINE, USER_TRANSFORM, CONCATENATED_TRANSFORM, GRID_TRANSFORM } VIO_Transform_types; /* --- the user transformation function */ typedef void (*VIO_User_transform_function)( void *user_data, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_trans, VIO_Real *y_trans, VIO_Real *z_trans ); /* --- the general transformation type */ typedef struct VIO_General_transform { VIO_Transform_types type; VIO_BOOL inverse_flag; /* --- linear transform */ VIO_Transform *linear_transform; VIO_Transform *inverse_linear_transform; /* --- non-linear transform */ int n_points; int n_dimensions; VIO_Real **points; VIO_Real **displacements; /* n_points + n_dim + 1 by */ /* n_dim */ /* --- grid transform */ void *displacement_volume; /* --- user_defined */ void *user_data; size_t size_user_data; VIO_User_transform_function user_transform_function; VIO_User_transform_function user_inverse_transform_function; /* --- concatenated transform */ int n_transforms; struct VIO_General_transform *transforms; } VIO_General_transform; #if !VIO_PREFIX_NAMES typedef VIO_Transform_types Transform_types; typedef VIO_General_transform General_transform; typedef VIO_User_transform_function User_transform_function; #endif /* !VIO_PREFIX_NAMES */ #endif minc-2.2.00/volume_io/Include/volume_io/vol_io_prototypes.h0000644000265600003100000014713612027132664021005 00000000000000#ifndef DEF_vol_io_prototypes #define DEF_vol_io_prototypes VIOAPI VIO_Real convert_voxel_to_value( VIO_Volume volume, VIO_Real voxel ); VIOAPI VIO_Real convert_value_to_voxel( VIO_Volume volume, VIO_Real value ); VIOAPI VIO_Real get_volume_voxel_value( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4 ); VIOAPI VIO_Real get_volume_real_value( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4 ); VIOAPI void set_volume_voxel_value( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, VIO_Real voxel ); VIOAPI void set_volume_real_value( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, VIO_Real value ); VIOAPI void set_volume_interpolation_tolerance( VIO_Real tolerance ); VIOAPI int evaluate_volume( VIO_Volume volume, VIO_Real voxel[], VIO_BOOL interpolating_dimensions[], int degrees_continuity, VIO_BOOL use_linear_at_edge, VIO_Real outside_value, VIO_Real values[], VIO_Real **first_deriv, VIO_Real ***second_deriv ); VIOAPI void evaluate_volume_in_world( VIO_Volume volume, VIO_Real x, VIO_Real y, VIO_Real z, int degrees_continuity, VIO_BOOL use_linear_at_edge, VIO_Real outside_value, VIO_Real values[], VIO_Real deriv_x[], VIO_Real deriv_y[], VIO_Real deriv_z[], VIO_Real deriv_xx[], VIO_Real deriv_xy[], VIO_Real deriv_xz[], VIO_Real deriv_yy[], VIO_Real deriv_yz[], VIO_Real deriv_zz[] ); VIOAPI void convert_voxels_to_values( VIO_Volume volume, int n_voxels, VIO_Real voxels[], VIO_Real values[] ); VIOAPI void get_volume_value_hyperslab( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real values[] ); VIOAPI void get_volume_value_hyperslab_5d( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real values[] ); VIOAPI void get_volume_value_hyperslab_4d( VIO_Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, VIO_Real values[] ); VIOAPI void get_volume_value_hyperslab_3d( VIO_Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, VIO_Real values[] ); VIOAPI void get_volume_value_hyperslab_2d( VIO_Volume volume, int v0, int v1, int n0, int n1, VIO_Real values[] ); VIOAPI void get_volume_value_hyperslab_1d( VIO_Volume volume, int v0, int n0, VIO_Real values[] ); VIOAPI void get_voxel_values_5d( VIO_Data_types data_type, void *void_ptr, int steps[], int counts[], VIO_Real values[] ); VIOAPI void get_voxel_values_4d( VIO_Data_types data_type, void *void_ptr, int steps[], int counts[], VIO_Real values[] ); VIOAPI void get_voxel_values_3d( VIO_Data_types data_type, void *void_ptr, int steps[], int counts[], VIO_Real values[] ); VIOAPI void get_voxel_values_2d( VIO_Data_types data_type, void *void_ptr, int steps[], int counts[], VIO_Real values[] ); VIOAPI void get_voxel_values_1d( VIO_Data_types data_type, void *void_ptr, int step0, int n0, VIO_Real values[] ); VIOAPI void get_volume_voxel_hyperslab_5d( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real values[] ); VIOAPI void get_volume_voxel_hyperslab_4d( VIO_Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, VIO_Real values[] ); VIOAPI void get_volume_voxel_hyperslab_3d( VIO_Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, VIO_Real values[] ); VIOAPI void get_volume_voxel_hyperslab_2d( VIO_Volume volume, int v0, int v1, int n0, int n1, VIO_Real values[] ); VIOAPI void get_volume_voxel_hyperslab_1d( VIO_Volume volume, int v0, int n0, VIO_Real values[] ); VIOAPI void get_volume_voxel_hyperslab( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real voxels[] ); VIOAPI VIO_Status initialize_free_format_input( VIO_STR filename, VIO_Volume volume, volume_input_struct *volume_input ); VIOAPI void delete_free_format_input( volume_input_struct *volume_input ); VIOAPI VIO_BOOL input_more_free_format_file( VIO_Volume volume, volume_input_struct *volume_input, VIO_Real *fraction_done ); VIOAPI int get_minc_file_n_dimensions( VIO_STR filename ); VIOAPI Minc_file initialize_minc_input_from_minc_id( int minc_id, VIO_Volume volume, minc_input_options *options ); VIOAPI Minc_file initialize_minc_input( VIO_STR filename, VIO_Volume volume, minc_input_options *options ); VIOAPI int get_n_input_volumes( Minc_file file ); VIOAPI VIO_Status close_minc_input( Minc_file file ); VIOAPI VIO_Status input_minc_hyperslab( Minc_file file, VIO_Data_types data_type, int n_array_dims, int array_sizes[], void *array_data_ptr, int to_array[], int start[], int count[] ); VIOAPI VIO_BOOL input_more_minc_file( Minc_file file, VIO_Real *fraction_done ); VIOAPI VIO_BOOL advance_input_volume( Minc_file file ); VIOAPI void reset_input_volume( Minc_file file ); VIOAPI int get_minc_file_id( Minc_file file ); VIOAPI void set_default_minc_input_options( minc_input_options *options ); VIOAPI void set_minc_input_promote_invalid_to_zero_flag( minc_input_options *options, VIO_BOOL flag ); VIOAPI void set_minc_input_promote_invalid_to_min_flag( minc_input_options *options, VIO_BOOL flag ); VIOAPI void set_minc_input_vector_to_scalar_flag( minc_input_options *options, VIO_BOOL flag ); VIOAPI void set_minc_input_vector_to_colour_flag( minc_input_options *options, VIO_BOOL flag ); VIOAPI void set_minc_input_colour_dimension_size( minc_input_options *options, int size ); VIOAPI void set_minc_input_colour_max_dimension_size( minc_input_options *options, int size ); VIOAPI void set_minc_input_colour_indices( minc_input_options *options, int indices[4] ); VIOAPI void set_minc_input_user_real_range( minc_input_options *options, double minimum, double maximum ); VIOAPI VIO_Status start_volume_input( VIO_STR filename, int n_dimensions, VIO_STR dim_names[], nc_type volume_nc_data_type, VIO_BOOL volume_signed_flag, VIO_Real volume_voxel_min, VIO_Real volume_voxel_max, VIO_BOOL create_volume_flag, VIO_Volume *volume, minc_input_options *options, volume_input_struct *input_info ); VIOAPI void delete_volume_input( volume_input_struct *input_info ); VIOAPI VIO_BOOL input_more_of_volume( VIO_Volume volume, volume_input_struct *input_info, VIO_Real *fraction_done ); VIOAPI void cancel_volume_input( VIO_Volume volume, volume_input_struct *input_info ); VIOAPI VIO_Status input_volume( VIO_STR filename, int n_dimensions, VIO_STR dim_names[], nc_type volume_nc_data_type, VIO_BOOL volume_signed_flag, VIO_Real volume_voxel_min, VIO_Real volume_voxel_max, VIO_BOOL create_volume_flag, VIO_Volume *volume, minc_input_options *options ); VIOAPI Minc_file get_volume_input_minc_file( volume_input_struct *volume_input ); VIOAPI void create_empty_multidim_array( VIO_multidim_array *array, int n_dimensions, VIO_Data_types data_type ); VIOAPI VIO_Data_types get_multidim_data_type( VIO_multidim_array *array ); VIOAPI void set_multidim_data_type( VIO_multidim_array *array, VIO_Data_types data_type ); VIOAPI int get_type_size( VIO_Data_types type ); VIOAPI void get_type_range( VIO_Data_types type, VIO_Real *min_value, VIO_Real *max_value ); VIOAPI void set_multidim_sizes( VIO_multidim_array *array, int sizes[] ); VIOAPI void get_multidim_sizes( VIO_multidim_array *array, int sizes[] ); VIOAPI VIO_BOOL multidim_array_is_alloced( VIO_multidim_array *array ); VIOAPI void alloc_multidim_array( VIO_multidim_array *array ); VIOAPI void create_multidim_array( VIO_multidim_array *array, int n_dimensions, int sizes[], VIO_Data_types data_type ); VIOAPI void delete_multidim_array( VIO_multidim_array *array ); VIOAPI int get_multidim_n_dimensions( VIO_multidim_array *array ); VIOAPI void copy_multidim_data_reordered( int type_size, void *void_dest_ptr, int n_dest_dims, int dest_sizes[], void *void_src_ptr, int n_src_dims, int src_sizes[], int counts[], int to_dest_index[], VIO_BOOL use_src_order ); VIOAPI void copy_multidim_reordered( VIO_multidim_array *dest, int dest_ind[], VIO_multidim_array *src, int src_ind[], int counts[], int to_dest_index[] ); VIOAPI Minc_file initialize_minc_output( VIO_STR filename, int n_dimensions, VIO_STR dim_names[], int sizes[], nc_type file_nc_data_type, VIO_BOOL file_signed_flag, VIO_Real file_voxel_min, VIO_Real file_voxel_max, VIO_General_transform *voxel_to_world_transform, VIO_Volume volume_to_attach, minc_output_options *options ); VIOAPI VIO_Status copy_auxiliary_data_from_minc_file( Minc_file file, VIO_STR filename, VIO_STR history_string ); VIOAPI VIO_Status copy_auxiliary_data_from_open_minc_file( Minc_file file, int src_cdfid, VIO_STR history_string ); VIOAPI VIO_Status add_minc_history( Minc_file file, VIO_STR history_string ); VIOAPI VIO_Status set_minc_output_random_order( Minc_file file ); VIOAPI VIO_Status output_minc_hyperslab( Minc_file file, VIO_Data_types data_type, int n_array_dims, int array_sizes[], void *array_data_ptr, int to_array[], int file_start[], int file_count[] ); VIOAPI VIO_Status output_volume_to_minc_file_position( Minc_file file, VIO_Volume volume, int volume_count[], long file_start[] ); VIOAPI VIO_Status output_minc_volume( Minc_file file ); VIOAPI VIO_Status close_minc_output( Minc_file file ); VIOAPI void set_default_minc_output_options( minc_output_options *options ); VIOAPI void copy_minc_output_options( minc_output_options *src, minc_output_options *dest ); VIOAPI void delete_minc_output_options( minc_output_options *options ); VIOAPI void set_minc_output_dimensions_order( minc_output_options *options, int n_dimensions, VIO_STR dimension_names[] ); VIOAPI void set_minc_output_real_range( minc_output_options *options, VIO_Real real_min, VIO_Real real_max ); VIOAPI void set_minc_output_use_volume_starts_and_steps_flag( minc_output_options *options, VIO_BOOL flag ); VIOAPI VIO_Status get_file_dimension_names( VIO_STR filename, int *n_dims, VIO_STR *dim_names[] ); VIOAPI VIO_STR *create_output_dim_names( VIO_Volume volume, VIO_STR original_filename, minc_output_options *options, int file_sizes[] ); VIOAPI VIO_Status copy_volume_auxiliary_and_history( Minc_file minc_file, VIO_STR filename, VIO_STR original_filename, VIO_STR history ); VIOAPI VIO_Status output_modified_volume( VIO_STR filename, nc_type file_nc_data_type, VIO_BOOL file_signed_flag, VIO_Real file_voxel_min, VIO_Real file_voxel_max, VIO_Volume volume, VIO_STR original_filename, VIO_STR history, minc_output_options *options ); VIOAPI VIO_Status output_volume( VIO_STR filename, nc_type file_nc_data_type, VIO_BOOL file_signed_flag, VIO_Real file_voxel_min, VIO_Real file_voxel_max, VIO_Volume volume, VIO_STR history, minc_output_options *options ); VIOAPI void convert_values_to_voxels( VIO_Volume volume, int n_voxels, VIO_Real values[], VIO_Real voxels[] ); VIOAPI void set_volume_value_hyperslab( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real values[] ); VIOAPI void set_volume_value_hyperslab_5d( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real values[] ); VIOAPI void set_volume_value_hyperslab_4d( VIO_Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, VIO_Real values[] ); VIOAPI void set_volume_value_hyperslab_3d( VIO_Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, VIO_Real values[] ); VIOAPI void set_volume_value_hyperslab_2d( VIO_Volume volume, int v0, int v1, int n0, int n1, VIO_Real values[] ); VIOAPI void set_volume_value_hyperslab_1d( VIO_Volume volume, int v0, int n0, VIO_Real values[] ); VIOAPI void set_volume_voxel_hyperslab_5d( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real values[] ); VIOAPI void set_volume_voxel_hyperslab_4d( VIO_Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, VIO_Real values[] ); VIOAPI void set_volume_voxel_hyperslab_3d( VIO_Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, VIO_Real values[] ); VIOAPI void set_volume_voxel_hyperslab_2d( VIO_Volume volume, int v0, int v1, int n0, int n1, VIO_Real values[] ); VIOAPI void set_volume_voxel_hyperslab_1d( VIO_Volume volume, int v0, int n0, VIO_Real values[] ); VIOAPI void set_volume_voxel_hyperslab( VIO_Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, VIO_Real voxels[] ); VIOAPI void set_n_bytes_cache_threshold( int threshold ); VIOAPI int get_n_bytes_cache_threshold( void ); VIOAPI void set_default_max_bytes_in_cache( int max_bytes ); VIOAPI int get_default_max_bytes_in_cache( void ); VIOAPI void set_default_cache_block_sizes( int block_sizes[] ); VIOAPI void set_cache_block_sizes_hint( VIO_Cache_block_size_hints hint ); VIOAPI void initialize_volume_cache( VIO_volume_cache_struct *cache, VIO_Volume volume ); VIOAPI VIO_BOOL volume_cache_is_alloced( VIO_volume_cache_struct *cache ); VIOAPI void flush_volume_cache( VIO_Volume volume ); VIOAPI void delete_volume_cache( VIO_volume_cache_struct *cache, VIO_Volume volume ); VIOAPI void set_volume_cache_block_sizes( VIO_Volume volume, int block_sizes[] ); VIOAPI void set_volume_cache_size( VIO_Volume volume, int max_memory_bytes ); VIOAPI void set_cache_output_volume_parameters( VIO_Volume volume, VIO_STR filename, nc_type file_nc_data_type, VIO_BOOL file_signed_flag, VIO_Real file_voxel_min, VIO_Real file_voxel_max, VIO_STR original_filename, VIO_STR history, minc_output_options *options ) ; VIOAPI void open_cache_volume_input_file( VIO_volume_cache_struct *cache, VIO_Volume volume, VIO_STR filename, minc_input_options *options ); VIOAPI void cache_volume_range_has_changed( VIO_Volume volume ); VIOAPI void set_cache_volume_file_offset( VIO_volume_cache_struct *cache, VIO_Volume volume, long file_offset[] ); VIOAPI VIO_Real get_cached_volume_voxel( VIO_Volume volume, int x, int y, int z, int t, int v ); VIOAPI void set_cached_volume_voxel( VIO_Volume volume, int x, int y, int z, int t, int v, VIO_Real value ); VIOAPI VIO_BOOL cached_volume_has_been_modified( VIO_volume_cache_struct *cache ); VIOAPI VIO_BOOL volume_is_cached( VIO_Volume volume ); VIOAPI void set_volume_cache_debugging( VIO_Volume volume, int output_every ); VIOAPI VIO_STR *get_default_dim_names( int n_dimensions ); VIOAPI VIO_BOOL convert_dim_name_to_spatial_axis( VIO_STR name, int *axis ); VIOAPI VIO_Volume create_volume( int n_dimensions, VIO_STR dimension_names[], nc_type nc_data_type, VIO_BOOL signed_flag, VIO_Real voxel_min, VIO_Real voxel_max ); VIOAPI void set_volume_type( VIO_Volume volume, nc_type nc_data_type, VIO_BOOL signed_flag, VIO_Real voxel_min, VIO_Real voxel_max ); VIOAPI nc_type get_volume_nc_data_type( VIO_Volume volume, VIO_BOOL *signed_flag ); VIOAPI VIO_Data_types get_volume_data_type( VIO_Volume volume ); VIOAPI void set_rgb_volume_flag( VIO_Volume volume, VIO_BOOL flag ); VIOAPI VIO_BOOL is_an_rgb_volume( VIO_Volume volume ); VIOAPI void alloc_volume_data( VIO_Volume volume ); VIOAPI VIO_BOOL volume_is_alloced( VIO_Volume volume ); VIOAPI void free_volume_data( VIO_Volume volume ); VIOAPI void delete_volume( VIO_Volume volume ); VIOAPI int get_volume_n_dimensions( VIO_Volume volume ); VIOAPI void get_volume_sizes( VIO_Volume volume, int sizes[] ); VIOAPI void set_volume_sizes( VIO_Volume volume, int sizes[] ); VIOAPI unsigned int get_volume_total_n_voxels( VIO_Volume volume ); VIOAPI void compute_world_transform( int spatial_axes[VIO_N_DIMENSIONS], VIO_Real separations[], VIO_Real direction_cosines[][VIO_N_DIMENSIONS], VIO_Real starts[], VIO_General_transform *world_transform ); VIOAPI void convert_transform_to_starts_and_steps( VIO_General_transform *transform, int n_volume_dimensions, VIO_Real step_signs[], int spatial_axes[], VIO_Real starts[], VIO_Real steps[], VIO_Real dir_cosines[][VIO_N_DIMENSIONS] ); VIOAPI void set_voxel_to_world_transform( VIO_Volume volume, VIO_General_transform *transform ); VIOAPI VIO_General_transform *get_voxel_to_world_transform( VIO_Volume volume ); VIOAPI VIO_STR *get_volume_dimension_names( VIO_Volume volume ); VIOAPI void delete_dimension_names( VIO_Volume volume, VIO_STR dimension_names[] ); VIOAPI VIO_STR get_volume_space_type( VIO_Volume volume ); VIOAPI void set_volume_space_type( VIO_Volume volume, VIO_STR name ); VIOAPI void get_volume_separations( VIO_Volume volume, VIO_Real separations[] ); VIOAPI void set_volume_separations( VIO_Volume volume, VIO_Real separations[] ); VIOAPI void set_volume_starts( VIO_Volume volume, VIO_Real starts[] ); VIOAPI void get_volume_starts( VIO_Volume volume, VIO_Real starts[] ); VIOAPI void set_volume_direction_unit_cosine( VIO_Volume volume, int axis, VIO_Real dir[] ); VIOAPI void set_volume_direction_cosine( VIO_Volume volume, int axis, VIO_Real dir[] ); VIOAPI void get_volume_direction_cosine( VIO_Volume volume, int axis, VIO_Real dir[] ); /* These next 5 functions may be called by other modules in the library, * but they are not truly public. That is why they are not declared VIOAPI. */ VIO_BOOL is_volume_dimension_irregular(VIO_Volume, int); int get_volume_irregular_starts(VIO_Volume, int, int, VIO_Real *); int get_volume_irregular_widths(VIO_Volume, int, int, VIO_Real *); int set_volume_irregular_starts(VIO_Volume, int, int, VIO_Real *); int set_volume_irregular_widths(VIO_Volume, int, int, VIO_Real *); VIOAPI VIO_Real nonspatial_voxel_to_world(VIO_Volume, int, int); VIOAPI int nonspatial_world_to_voxel(VIO_Volume, int, VIO_Real); VIOAPI void set_volume_translation( VIO_Volume volume, VIO_Real voxel[], VIO_Real world_space_voxel_maps_to[] ); VIOAPI void get_volume_translation( VIO_Volume volume, VIO_Real voxel[], VIO_Real world_space_voxel_maps_to[] ); VIOAPI void reorder_voxel_to_xyz( VIO_Volume volume, VIO_Real voxel[], VIO_Real xyz[] ); VIOAPI void reorder_xyz_to_voxel( VIO_Volume volume, VIO_Real xyz[], VIO_Real voxel[] ); VIOAPI void convert_voxel_to_world( VIO_Volume volume, VIO_Real voxel[], VIO_Real *x_world, VIO_Real *y_world, VIO_Real *z_world ); VIOAPI void convert_3D_voxel_to_world( VIO_Volume volume, VIO_Real voxel1, VIO_Real voxel2, VIO_Real voxel3, VIO_Real *x_world, VIO_Real *y_world, VIO_Real *z_world ); VIOAPI void convert_voxel_normal_vector_to_world( VIO_Volume volume, VIO_Real voxel_vector[], VIO_Real *x_world, VIO_Real *y_world, VIO_Real *z_world ); VIOAPI void convert_voxel_vector_to_world( VIO_Volume volume, VIO_Real voxel_vector[], VIO_Real *x_world, VIO_Real *y_world, VIO_Real *z_world ); VIOAPI void convert_world_vector_to_voxel( VIO_Volume volume, VIO_Real x_world, VIO_Real y_world, VIO_Real z_world, VIO_Real voxel_vector[] ); VIOAPI void convert_world_to_voxel( VIO_Volume volume, VIO_Real x_world, VIO_Real y_world, VIO_Real z_world, VIO_Real voxel[] ); VIOAPI void convert_3D_world_to_voxel( VIO_Volume volume, VIO_Real x_world, VIO_Real y_world, VIO_Real z_world, VIO_Real *voxel1, VIO_Real *voxel2, VIO_Real *voxel3 ); VIOAPI VIO_Real get_volume_voxel_min( VIO_Volume volume ); VIOAPI VIO_Real get_volume_voxel_max( VIO_Volume volume ); VIOAPI void get_volume_voxel_range( VIO_Volume volume, VIO_Real *voxel_min, VIO_Real *voxel_max ); VIOAPI void set_volume_voxel_range( VIO_Volume volume, VIO_Real voxel_min, VIO_Real voxel_max ); VIOAPI void get_volume_real_range( VIO_Volume volume, VIO_Real *min_value, VIO_Real *max_value ); VIOAPI VIO_Real get_volume_real_min( VIO_Volume volume ); VIOAPI VIO_Real get_volume_real_max( VIO_Volume volume ); VIOAPI void set_volume_real_range( VIO_Volume volume, VIO_Real real_min, VIO_Real real_max ); VIOAPI VIO_Volume copy_volume_definition_no_alloc( VIO_Volume volume, nc_type nc_data_type, VIO_BOOL signed_flag, VIO_Real voxel_min, VIO_Real voxel_max ); VIOAPI VIO_Volume copy_volume_definition( VIO_Volume volume, nc_type nc_data_type, VIO_BOOL signed_flag, VIO_Real voxel_min, VIO_Real voxel_max ); VIOAPI VIO_Volume copy_volume( VIO_Volume volume ); VIOAPI void grid_transform_point( VIO_General_transform *transform, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_transformed, VIO_Real *y_transformed, VIO_Real *z_transformed ); VIOAPI void grid_inverse_transform_point( VIO_General_transform *transform, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_transformed, VIO_Real *y_transformed, VIO_Real *z_transformed ); VIOAPI VIO_Status mni_get_nonwhite_character( FILE *file, char *ch ); VIOAPI VIO_Status mni_skip_expected_character( FILE *file, char expected_ch ); VIOAPI VIO_Status mni_input_line( FILE *file, VIO_STR *string ); VIOAPI VIO_Status mni_input_string( FILE *file, VIO_STR *string, char termination_char1, char termination_char2 ); VIOAPI VIO_Status mni_input_keyword_and_equal_sign( FILE *file, const char keyword[], VIO_BOOL print_error_message ); VIOAPI VIO_Status mni_input_real( FILE *file, VIO_Real *d ); VIOAPI VIO_Status mni_input_reals( FILE *file, int *n, VIO_Real *reals[] ); VIOAPI VIO_Status mni_input_int( FILE *file, int *i ); VIOAPI void output_comments( FILE *file, VIO_STR comments ); VIOAPI VIO_STR get_default_tag_file_suffix( void ); VIOAPI VIO_Status initialize_tag_file_output( FILE *file, VIO_STR comments, int n_volumes ); VIOAPI VIO_Status output_one_tag( FILE *file, int n_volumes, VIO_Real tag_volume1[], VIO_Real tag_volume2[], VIO_Real *weight, int *structure_id, int *patient_id, VIO_STR label ); VIOAPI void terminate_tag_file_output( FILE *file ); VIOAPI VIO_Status output_tag_points( FILE *file, VIO_STR comments, int n_volumes, int n_tag_points, VIO_Real **tags_volume1, VIO_Real **tags_volume2, VIO_Real weights[], int structure_ids[], int patient_ids[], VIO_STR *labels ); VIOAPI void free_tag_points( int n_volumes, int n_tag_points, VIO_Real **tags_volume1, VIO_Real **tags_volume2, VIO_Real weights[], int structure_ids[], int patient_ids[], char **labels ); VIOAPI VIO_Status initialize_tag_file_input( FILE *file, int *n_volumes_ptr ); VIOAPI VIO_Status output_tag_file( VIO_STR filename, VIO_STR comments, int n_volumes, int n_tag_points, VIO_Real **tags_volume1, VIO_Real **tags_volume2, VIO_Real weights[], int structure_ids[], int patient_ids[], VIO_STR labels[] ); VIOAPI VIO_Status input_tag_file( VIO_STR filename, int *n_volumes, int *n_tag_points, VIO_Real ***tags_volume1, VIO_Real ***tags_volume2, VIO_Real **weights, int **structure_ids, int **patient_ids, VIO_STR *labels[] ); VIOAPI VIO_BOOL input_one_tag( FILE *file, int n_volumes, VIO_Real tag_volume1[], VIO_Real tag_volume2[], VIO_Real *weight, int *structure_id, int *patient_id, VIO_STR *label, VIO_Status *status ); VIOAPI VIO_Status input_tag_points( FILE *file, int *n_volumes_ptr, int *n_tag_points, VIO_Real ***tags_volume1, VIO_Real ***tags_volume2, VIO_Real **weights, int **structure_ids, int **patient_ids, VIO_STR *labels[] ); VIOAPI void evaluate_thin_plate_spline( int n_dims, int n_values, int n_points, VIO_Real **points, VIO_Real **weights, VIO_Real pos[], VIO_Real values[], VIO_Real **derivs ); VIOAPI void thin_plate_spline_transform( int n_dims, int n_points, VIO_Real **points, VIO_Real **weights, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_transformed, VIO_Real *y_transformed, VIO_Real *z_transformed ); VIOAPI void thin_plate_spline_inverse_transform( int n_dims, int n_points, VIO_Real **points, VIO_Real **weights, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_transformed, VIO_Real *y_transformed, VIO_Real *z_transformed ); VIOAPI VIO_Real thin_plate_spline_U( VIO_Real pos[], VIO_Real landmark[], int n_dims ); VIOAPI VIO_STR get_default_transform_file_suffix( void ); VIOAPI VIO_Status output_transform( FILE *file, VIO_STR filename, int *volume_count_ptr, VIO_STR comments, VIO_General_transform *transform ); VIOAPI VIO_Status input_transform( FILE *file, VIO_STR filename, VIO_General_transform *transform ); VIOAPI VIO_Status output_transform_file( VIO_STR filename, VIO_STR comments, VIO_General_transform *transform ); VIOAPI VIO_Status input_transform_file( VIO_STR filename, VIO_General_transform *transform ); VIOAPI void create_linear_transform( VIO_General_transform *transform, VIO_Transform *linear_transform ); VIOAPI void create_thin_plate_transform_real( VIO_General_transform *transform, int n_dimensions, int n_points, VIO_Real **points, VIO_Real **displacements ); VIOAPI void create_thin_plate_transform( VIO_General_transform *transform, int n_dimensions, int n_points, float **points, float **displacements ); VIOAPI void create_grid_transform( VIO_General_transform *transform, VIO_Volume displacement_volume ); VIOAPI void create_grid_transform_no_copy( VIO_General_transform *transform, VIO_Volume displacement_volume ); VIOAPI void create_user_transform( VIO_General_transform *transform, void *user_data, size_t size_user_data, VIO_User_transform_function transform_function, VIO_User_transform_function inverse_transform_function ); VIOAPI VIO_Transform_types get_transform_type( VIO_General_transform *transform ); VIOAPI int get_n_concated_transforms( VIO_General_transform *transform ); VIOAPI VIO_General_transform *get_nth_general_transform( VIO_General_transform *transform, int n ); VIOAPI VIO_Transform *get_linear_transform_ptr( VIO_General_transform *transform ); VIOAPI VIO_Transform *get_inverse_linear_transform_ptr( VIO_General_transform *transform ); VIOAPI void general_transform_point( VIO_General_transform *transform, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_transformed, VIO_Real *y_transformed, VIO_Real *z_transformed ); VIOAPI void general_inverse_transform_point( VIO_General_transform *transform, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_transformed, VIO_Real *y_transformed, VIO_Real *z_transformed ); VIOAPI void copy_general_transform( VIO_General_transform *transform, VIO_General_transform *copy ); VIOAPI void invert_general_transform( VIO_General_transform *transform ); VIOAPI void create_inverse_general_transform( VIO_General_transform *transform, VIO_General_transform *inverse ); VIOAPI void concat_general_transforms( VIO_General_transform *first, VIO_General_transform *second, VIO_General_transform *result ); VIOAPI void delete_general_transform( VIO_General_transform *transform ); VIOAPI VIO_Colour make_rgba_Colour( int r, int g, int b, int a ); VIOAPI int get_Colour_r( VIO_Colour colour ); VIOAPI int get_Colour_g( VIO_Colour colour ); VIOAPI int get_Colour_b( VIO_Colour colour ); VIOAPI int get_Colour_a( VIO_Colour colour ); VIOAPI VIO_Colour make_Colour( int r, int g, int b ); VIOAPI VIO_Real get_Colour_r_0_1( VIO_Colour colour ); VIOAPI VIO_Real get_Colour_g_0_1( VIO_Colour colour ); VIOAPI VIO_Real get_Colour_b_0_1( VIO_Colour colour ); VIOAPI VIO_Real get_Colour_a_0_1( VIO_Colour colour ); VIOAPI VIO_Colour make_Colour_0_1( VIO_Real r, VIO_Real g, VIO_Real b ); VIOAPI VIO_Colour make_rgba_Colour_0_1( VIO_Real r, VIO_Real g, VIO_Real b, VIO_Real a ); VIOAPI VIO_BOOL solve_linear_system( int n, VIO_Real **coefs, VIO_Real values[], VIO_Real solution[] ); VIOAPI VIO_BOOL invert_square_matrix( int n, VIO_Real **matrix, VIO_Real **inverse ); VIOAPI VIO_BOOL newton_root_find( int n_dimensions, void (*function) ( void *, VIO_Real [], VIO_Real [], VIO_Real ** ), void *function_data, VIO_Real initial_guess[], VIO_Real desired_values[], VIO_Real solution[], VIO_Real function_tolerance, VIO_Real delta_tolerance, int max_iterations ); VIOAPI void create_orthogonal_vector( VIO_Vector *v, VIO_Vector *ortho ); VIOAPI void create_two_orthogonal_vectors( VIO_Vector *v, VIO_Vector *v1, VIO_Vector *v2 ); VIOAPI VIO_BOOL compute_transform_inverse( VIO_Transform *transform, VIO_Transform *inverse ); VIOAPI void get_linear_spline_coefs( VIO_Real **coefs ); VIOAPI void get_quadratic_spline_coefs( VIO_Real **coefs ); VIOAPI void get_cubic_spline_coefs( VIO_Real **coefs ); VIOAPI VIO_Real cubic_interpolate( VIO_Real u, VIO_Real v0, VIO_Real v1, VIO_Real v2, VIO_Real v3 ); VIOAPI void evaluate_univariate_interpolating_spline( VIO_Real u, int degree, VIO_Real coefs[], int n_derivs, VIO_Real derivs[] ); VIOAPI void evaluate_bivariate_interpolating_spline( VIO_Real u, VIO_Real v, int degree, VIO_Real coefs[], int n_derivs, VIO_Real derivs[] ); VIOAPI void evaluate_trivariate_interpolating_spline( VIO_Real u, VIO_Real v, VIO_Real w, int degree, VIO_Real coefs[], int n_derivs, VIO_Real derivs[] ); VIOAPI void evaluate_interpolating_spline( int n_dims, VIO_Real parameters[], int degree, int n_values, VIO_Real coefs[], int n_derivs, VIO_Real derivs[] ); VIOAPI void spline_tensor_product( int n_dims, VIO_Real positions[], int degrees[], VIO_Real *bases[], int n_values, VIO_Real coefs[], int n_derivs[], VIO_Real results[] ); VIOAPI void make_identity_transform( VIO_Transform *transform ); VIOAPI VIO_BOOL close_to_identity( VIO_Transform *transform ); VIOAPI void get_transform_origin( VIO_Transform *transform, VIO_Point *origin ); VIOAPI void set_transform_origin( VIO_Transform *transform, VIO_Point *origin ); VIOAPI void get_transform_origin_real( VIO_Transform *transform, VIO_Real origin[] ); VIOAPI void get_transform_x_axis( VIO_Transform *transform, VIO_Vector *x_axis ); VIOAPI void get_transform_x_axis_real( VIO_Transform *transform, VIO_Real x_axis[] ); VIOAPI void set_transform_x_axis( VIO_Transform *transform, VIO_Vector *x_axis ); VIOAPI void set_transform_x_axis_real( VIO_Transform *transform, VIO_Real x_axis[] ); VIOAPI void get_transform_y_axis( VIO_Transform *transform, VIO_Vector *y_axis ); VIOAPI void get_transform_y_axis_real( VIO_Transform *transform, VIO_Real y_axis[] ); VIOAPI void set_transform_y_axis( VIO_Transform *transform, VIO_Vector *y_axis ); VIOAPI void set_transform_y_axis_real( VIO_Transform *transform, VIO_Real y_axis[] ); VIOAPI void get_transform_z_axis( VIO_Transform *transform, VIO_Vector *z_axis ); VIOAPI void get_transform_z_axis_real( VIO_Transform *transform, VIO_Real z_axis[] ); VIOAPI void set_transform_z_axis( VIO_Transform *transform, VIO_Vector *z_axis ); VIOAPI void set_transform_z_axis_real( VIO_Transform *transform, VIO_Real z_axis[] ); VIOAPI void make_change_to_bases_transform( VIO_Point *origin, VIO_Vector *x_axis, VIO_Vector *y_axis, VIO_Vector *z_axis, VIO_Transform *transform ); VIOAPI void make_change_from_bases_transform( VIO_Point *origin, VIO_Vector *x_axis, VIO_Vector *y_axis, VIO_Vector *z_axis, VIO_Transform *transform ); VIOAPI void concat_transforms( VIO_Transform *result, VIO_Transform *t1, VIO_Transform *t2 ); VIOAPI void transform_point( VIO_Transform *transform, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_trans, VIO_Real *y_trans, VIO_Real *z_trans ); VIOAPI void transform_vector( VIO_Transform *transform, VIO_Real x, VIO_Real y, VIO_Real z, VIO_Real *x_trans, VIO_Real *y_trans, VIO_Real *z_trans ); VIOAPI void *alloc_memory_in_bytes( size_t n_bytes _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void *alloc_memory_1d( size_t n_elements, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void *alloc_memory_2d( size_t n1, size_t n2, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void *alloc_memory_3d( size_t n1, size_t n2, size_t n3, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void *alloc_memory_4d( size_t n1, size_t n2, size_t n3, size_t n4, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void *alloc_memory_5d( size_t n1, size_t n2, size_t n3, size_t n4, size_t n5, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void realloc_memory( void **ptr, size_t n_elements, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void free_memory_1d( void **ptr _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void free_memory_2d( void ***ptr _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void free_memory_3d( void ****ptr _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void free_memory_4d( void *****ptr _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI void free_memory_5d( void ******ptr _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI size_t get_total_memory_alloced( void ); VIOAPI VIO_BOOL alloc_checking_enabled( void ); VIOAPI void set_alloc_checking( VIO_BOOL state ); VIOAPI void record_ptr_alloc_check( void *ptr, size_t n_bytes, VIO_STR source_file, int line_number ); VIOAPI void change_ptr_alloc_check( void *old_ptr, void *new_ptr, size_t n_bytes, VIO_STR source_file, int line_number ); VIOAPI VIO_BOOL unrecord_ptr_alloc_check( void *ptr, VIO_STR source_file, int line_number ); VIOAPI void output_alloc_to_file( VIO_STR filename ); VIOAPI void print_alloc_source_line( VIO_STR filename, int line_number ); VIOAPI void set_array_size( void **array, size_t type_size, size_t previous_n_elems, size_t new_n_elems, size_t chunk_size _ALLOC_SOURCE_LINE_ARG_DEF ); VIOAPI VIO_BOOL real_is_double( void ); VIOAPI VIO_BOOL file_exists( VIO_STR filename ); VIOAPI VIO_BOOL file_directory_exists( VIO_STR filename ); VIOAPI VIO_BOOL check_clobber_file( VIO_STR filename ); VIOAPI VIO_BOOL check_clobber_file_default_suffix( VIO_STR filename, VIO_STR default_suffix ); VIOAPI VIO_Status make_backup_file( VIO_STR filename, VIO_STR *backup_filename ); VIOAPI void cleanup_backup_file( VIO_STR filename, VIO_STR backup_filename, VIO_Status status_of_write ); VIOAPI void remove_file( VIO_STR filename ); VIOAPI VIO_Status copy_file( VIO_STR src, VIO_STR dest ); VIOAPI VIO_Status move_file( VIO_STR src, VIO_STR dest ); VIOAPI VIO_STR expand_filename( VIO_STR filename ); VIOAPI VIO_BOOL filename_extension_matches( VIO_STR filename, VIO_STR extension ); VIOAPI VIO_STR remove_directories_from_filename( VIO_STR filename ); VIOAPI VIO_BOOL file_exists_as_compressed( VIO_STR filename, VIO_STR *compressed_filename ); VIOAPI VIO_STR get_temporary_filename( void ); VIOAPI VIO_Status open_file( VIO_STR filename, VIO_IO_types io_type, VIO_File_formats file_format, FILE **file ); VIOAPI VIO_Status open_file_with_default_suffix( VIO_STR filename, VIO_STR default_suffix, VIO_IO_types io_type, VIO_File_formats file_format, FILE **file ); VIOAPI VIO_Status set_file_position( FILE *file, long byte_position ); VIOAPI VIO_Status close_file( FILE *file ); VIOAPI VIO_STR extract_directory( VIO_STR filename ); VIOAPI VIO_STR get_absolute_filename( VIO_STR filename, VIO_STR directory ); VIOAPI VIO_Status flush_file( FILE *file ); VIOAPI VIO_Status input_character( FILE *file, char *ch ); VIOAPI VIO_Status unget_character( FILE *file, char ch ); VIOAPI VIO_Status input_nonwhite_character( FILE *file, char *ch ); VIOAPI VIO_Status output_character( FILE *file, char ch ); VIOAPI VIO_Status skip_input_until( FILE *file, char search_char ); VIOAPI VIO_Status output_string( FILE *file, VIO_STR str ); VIOAPI VIO_Status input_string( FILE *file, VIO_STR *str, char termination_char ); VIOAPI VIO_Status input_quoted_string( FILE *file, VIO_STR *str ); VIOAPI VIO_Status input_possibly_quoted_string( FILE *file, VIO_STR *str ); VIOAPI VIO_Status output_quoted_string( FILE *file, VIO_STR str ); VIOAPI VIO_Status input_binary_data( FILE *file, void *data, size_t element_size, int n ); VIOAPI VIO_Status output_binary_data( FILE *file, void *data, size_t element_size, int n ); VIOAPI VIO_Status input_newline( FILE *file ); VIOAPI VIO_Status output_newline( FILE *file ); VIOAPI VIO_Status input_line( FILE *file, VIO_STR *line ); VIOAPI VIO_Status input_boolean( FILE *file, VIO_BOOL *b ); VIOAPI VIO_Status output_boolean( FILE *file, VIO_BOOL b ); VIOAPI VIO_Status input_short( FILE *file, short *s ); VIOAPI VIO_Status output_short( FILE *file, short s ); VIOAPI VIO_Status input_unsigned_short( FILE *file, unsigned short *s ); VIOAPI VIO_Status output_unsigned_short( FILE *file, unsigned short s ); VIOAPI VIO_Status input_int( FILE *file, int *i ); VIOAPI VIO_Status output_int( FILE *file, int i ); VIOAPI VIO_Status input_real( FILE *file, VIO_Real *r ); VIOAPI VIO_Status output_real( FILE *file, VIO_Real r ); VIOAPI VIO_Status input_float( FILE *file, float *f ); VIOAPI VIO_Status output_float( FILE *file, float f ); VIOAPI VIO_Status input_double( FILE *file, double *d ); VIOAPI VIO_Status output_double( FILE *file, double d ); VIOAPI VIO_Status io_binary_data( FILE *file, VIO_IO_types io_flag, void *data, size_t element_size, int n ); VIOAPI VIO_Status io_newline( FILE *file, VIO_IO_types io_flag, VIO_File_formats format ); VIOAPI VIO_Status io_quoted_string( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, VIO_STR *str ); VIOAPI VIO_Status io_boolean( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, VIO_BOOL *b ); VIOAPI VIO_Status io_short( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, short *short_int ); VIOAPI VIO_Status io_unsigned_short( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, unsigned short *unsigned_short ); VIOAPI VIO_Status io_unsigned_char( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, unsigned char *c ); VIOAPI VIO_Status io_int( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, int *i ); VIOAPI VIO_Status io_real( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, VIO_Real *r ); VIOAPI VIO_Status io_float( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, float *f ); VIOAPI VIO_Status io_double( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, double *d ); VIOAPI VIO_Status io_ints( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, int n, int *ints[] ); VIOAPI VIO_Status io_unsigned_chars( FILE *file, VIO_IO_types io_flag, VIO_File_formats format, int n, unsigned char *unsigned_chars[] ); VIOAPI void set_print_function( void (*function) ( VIO_STR ) ); VIOAPI void push_print_function( void ); VIOAPI void pop_print_function( void ); VIOAPI void print( VIO_STR format, ... ); VIOAPI void set_print_error_function( void (*function) ( char [] ) ); VIOAPI void push_print_error_function( void ); VIOAPI void pop_print_error_function( void ); VIOAPI void print_error( char format[], ... ); VIOAPI void handle_internal_error( char str[] ); VIOAPI void abort_if_allowed( void ); VIOAPI void initialize_progress_report( VIO_progress_struct *progress, VIO_BOOL one_line_only, int n_steps, VIO_STR title ); VIOAPI void update_progress_report( VIO_progress_struct *progress, int current_step ); VIOAPI void terminate_progress_report( VIO_progress_struct *progress ); VIOAPI VIO_STR alloc_string( int length ); VIOAPI VIO_STR create_string( VIO_STR initial ); VIOAPI void delete_string( VIO_STR string ); VIOAPI VIO_STR concat_strings( VIO_STR str1, VIO_STR str2 ); VIOAPI void replace_string( VIO_STR *string, VIO_STR new_string ); VIOAPI void concat_char_to_string( VIO_STR *string, char ch ); VIOAPI void concat_to_string( VIO_STR *string, VIO_STR str2 ); VIOAPI int string_length( VIO_STR string ); VIOAPI VIO_BOOL equal_strings( VIO_STR str1, VIO_STR str2 ); VIOAPI VIO_BOOL is_lower_case( char ch ); VIOAPI VIO_BOOL is_upper_case( char ch ); VIOAPI char get_lower_case( char ch ); VIOAPI char get_upper_case( char ch ); VIOAPI VIO_BOOL string_ends_in( VIO_STR string, VIO_STR ending ); VIOAPI VIO_STR strip_outer_blanks( VIO_STR str ); VIOAPI int find_character( VIO_STR string, char ch ); VIOAPI void make_string_upper_case( VIO_STR string ); VIOAPI VIO_BOOL blank_string( VIO_STR string ); VIOAPI VIO_Real current_cpu_seconds( void ); VIOAPI VIO_Real current_realtime_seconds( void ); VIOAPI VIO_STR format_time( VIO_STR format, VIO_Real seconds ); VIOAPI void print_time( VIO_STR format, VIO_Real seconds ); VIOAPI VIO_STR get_clock_time( void ); VIOAPI void sleep_program( VIO_Real seconds ); VIOAPI VIO_STR get_date( void ); #endif minc-2.2.00/volume_io/Include/volume_io/volume.h0000644000265600003100000004253712027132664016514 00000000000000#ifndef DEF_VOLUME #define DEF_VOLUME /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/volume.h,v 1.57 2006-04-07 14:47:15 rotor Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : volume.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Types for use in dealing with volumes. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include #include #include typedef struct { VIO_Real global_image_range[2]; VIO_STR dimension_names[VIO_MAX_DIMENSIONS]; VIO_BOOL use_starts_set; VIO_BOOL use_volume_starts_and_steps; } minc_output_options; #include extern VIO_STR XYZ_dimension_names[]; extern VIO_STR File_order_dimension_names[]; /* -------------------------- volume struct --------------------- */ #define ANY_SPATIAL_DIMENSION "any_spatial_dimension" #define MI_UNKNOWN_SPACE "unknown___" typedef struct { VIO_BOOL is_cached_volume; VIO_volume_cache_struct cache; VIO_multidim_array array; VIO_STR dimension_names[VIO_MAX_DIMENSIONS]; int spatial_axes[VIO_N_DIMENSIONS]; nc_type nc_data_type; VIO_BOOL signed_flag; VIO_BOOL is_rgba_data; VIO_Real voxel_min; VIO_Real voxel_max; VIO_BOOL real_range_set; VIO_Real real_value_scale; VIO_Real real_value_translation; VIO_Real separations[VIO_MAX_DIMENSIONS]; VIO_Real starts[VIO_MAX_DIMENSIONS]; VIO_Real direction_cosines[VIO_MAX_DIMENSIONS][VIO_N_DIMENSIONS]; VIO_BOOL voxel_to_world_transform_uptodate; VIO_General_transform voxel_to_world_transform; VIO_STR coordinate_system_name; VIO_Real *irregular_starts[VIO_MAX_DIMENSIONS]; VIO_Real *irregular_widths[VIO_MAX_DIMENSIONS]; } volume_struct; typedef volume_struct *VIO_Volume; #if !VIO_PREFIX_NAMES typedef VIO_Volume Volume; #endif /* !VIO_PREFIX_NAMES */ /* ---- macro for stepping through entire volume */ #define BEGIN_ALL_VOXELS( volume, v0, v1, v2, v3, v4 ) \ { \ int _i_, _sizes_[VIO_MAX_DIMENSIONS]; \ int _size0_, _size1_, _size2_, _size3_, _size4_; \ \ get_volume_sizes( volume, _sizes_ ); \ for_less( _i_, get_volume_n_dimensions(volume), VIO_MAX_DIMENSIONS ) \ _sizes_[_i_] = 1; \ _size0_ = _sizes_[0]; \ _size1_ = _sizes_[1]; \ _size2_ = _sizes_[2]; \ _size3_ = _sizes_[3]; \ _size4_ = _sizes_[4]; \ \ for_less( v0, 0, _size0_ ) \ for_less( v1, 0, _size1_ ) \ for_less( v2, 0, _size2_ ) \ for_less( v3, 0, _size3_ ) \ for_less( v4, 0, _size4_ ) \ { #define END_ALL_VOXELS \ } \ } /* ------------------------- set voxel value ------------------------ */ /* --- public macros to set the [x][y]... voxel of 'volume' to 'value' */ #define SET_VOXEL_1D( volume, x, value ) \ if( (volume)->is_cached_volume ) \ set_cached_volume_voxel( volume, x, 0, 0, 0, 0, (VIO_Real) value ); \ else \ SET_MULTIDIM_1D( (volume)->array, x, value ) #define SET_VOXEL_2D( volume, x, y, value ) \ if( (volume)->is_cached_volume ) \ set_cached_volume_voxel( volume, x, y, 0, 0, 0, (VIO_Real) value ); \ else \ SET_MULTIDIM_2D( (volume)->array, x, y, value ) #define SET_VOXEL_3D( volume, x, y, z, value ) \ if( (volume)->is_cached_volume ) \ set_cached_volume_voxel( volume, x, y, z, 0, 0, (VIO_Real) value ); \ else \ SET_MULTIDIM_3D( (volume)->array, x, y, z, value ) #define SET_VOXEL_4D( volume, x, y, z, t, value ) \ if( (volume)->is_cached_volume ) \ set_cached_volume_voxel( volume, x, y, z, t, 0, (VIO_Real) value ); \ else \ SET_MULTIDIM_4D( (volume)->array, x, y, z, t, value ) #define SET_VOXEL_5D( volume, x, y, z, t, v, value ) \ if( (volume)->is_cached_volume ) \ set_cached_volume_voxel( volume, x, y, z, t, v, (VIO_Real) value ); \ else \ SET_MULTIDIM_5D( (volume)->array, x, y, z, t, v, value ) /* --- same as previous, but don't have to know dimensions of volume */ #define SET_VOXEL( volume, x, y, z, t, v, value ) \ if( (volume)->is_cached_volume ) \ set_cached_volume_voxel( volume, x, y, z, t, v, (VIO_Real) value ); \ else \ SET_MULTIDIM( (volume)->array, x, y, z, t, v, value ) /* --- public macros to place the [x][y]...'th voxel of 'volume' in 'value' */ #define GET_VOXEL_1D_TYPED( value, vtype, volume, x ) \ if( (volume)->is_cached_volume ) \ (value) = vtype get_cached_volume_voxel( volume, x, 0, 0, 0, 0 ); \ else \ GET_MULTIDIM_1D( value, vtype, (volume)->array, x ) #define GET_VOXEL_2D_TYPED( value, vtype, volume, x, y ) \ if( (volume)->is_cached_volume ) \ (value) = vtype get_cached_volume_voxel( volume, x, y, 0, 0, 0 ); \ else \ GET_MULTIDIM_2D( value, vtype, (volume)->array, x, y ) #define GET_VOXEL_3D_TYPED( value, vtype, volume, x, y, z ) \ if( (volume)->is_cached_volume ) \ (value) = vtype get_cached_volume_voxel( volume, x, y, z, 0, 0 ); \ else \ GET_MULTIDIM_3D( value, vtype, (volume)->array, x, y, z ) #define GET_VOXEL_4D_TYPED( value, vtype, volume, x, y, z, t ) \ if( (volume)->is_cached_volume ) \ (value) = vtype get_cached_volume_voxel( volume, x, y, z, t, 0 ); \ else \ GET_MULTIDIM_4D( value, vtype, (volume)->array, x, y, z, t ) #define GET_VOXEL_5D_TYPED( value, vtype, volume, x, y, z, t, v ) \ if( (volume)->is_cached_volume ) \ (value) = vtype get_cached_volume_voxel( volume, x, y, z, t, v ); \ else \ GET_MULTIDIM_5D( value, vtype, (volume)->array, x, y, z, t, v ) /* --- same as previous, but no need to know volume dimensions */ #define GET_VOXEL_TYPED( value, vtype, volume, x, y, z, t, v ) \ if( (volume)->is_cached_volume ) \ (value) = vtype get_cached_volume_voxel( volume, x, y, z, t, v ); \ else \ GET_MULTIDIM( value, vtype, (volume)->array, x, y, z, t, v ) /* --- public macros to place the [x][y]...'th voxel of 'volume' in 'value' */ #define GET_VOXEL_1D( value, volume, x ) \ GET_VOXEL_1D_TYPED( value, , volume, x ) #define GET_VOXEL_2D( value, volume, x, y ) \ GET_VOXEL_2D_TYPED( value, , volume, x, y ) #define GET_VOXEL_3D( value, volume, x, y, z ) \ GET_VOXEL_3D_TYPED( value, , volume, x, y, z ) #define GET_VOXEL_4D( value, volume, x, y, z, t ) \ GET_VOXEL_4D_TYPED( value, , volume, x, y, z, t ) #define GET_VOXEL_5D( value, volume, x, y, z, t, v ) \ GET_VOXEL_5D_TYPED( value, , volume, x, y, z, t, v ) /* --- same as previous, but no need to know volume dimensions */ #define GET_VOXEL( value, volume, x, y, z, t, v ) \ GET_VOXEL_TYPED( value, , volume, x, y, z, t, v ) /* ------------------------- get voxel ptr ------------------------ */ /* --- public macros to return a pointer to the [x][y]'th voxel of the 'volume', and place it in 'ptr' */ #define GET_VOXEL_PTR_1D( ptr, volume, x ) \ if( (volume)->is_cached_volume ) \ /* handle_internal_error( "Cannot get pointer to cached Volume.\n");\ else */ \ GET_MULTIDIM_PTR_1D( ptr, (volume)->array, x ) #define GET_VOXEL_PTR_2D( ptr, volume, x, y ) \ if( (volume)->is_cached_volume ) \ handle_internal_error( "Cannot get pointer to cached Volume.\n");\ else \ GET_MULTIDIM_PTR_2D( ptr, (volume)->array, x, y ) #define GET_VOXEL_PTR_3D( ptr, volume, x, y, z ) \ if( (volume)->is_cached_volume ) \ handle_internal_error( "Cannot get pointer to cached Volume.\n");\ else \ GET_MULTIDIM_PTR_3D( ptr, (volume)->array, x, y, z ) #define GET_VOXEL_PTR_4D( ptr, volume, x, y, z, t ) \ if( (volume)->is_cached_volume ) \ handle_internal_error( "Cannot get pointer to cached Volume.\n");\ else \ GET_MULTIDIM_PTR_4D( ptr, (volume)->array, x, y, z, t ) #define GET_VOXEL_PTR_5D( ptr, volume, x, y, z, t, v ) \ if( (volume)->is_cached_volume ) \ handle_internal_error( "Cannot get pointer to cached Volume.\n");\ else \ GET_MULTIDIM_PTR_5D( ptr, (volume)->array, x, y, z, t, v ) /* --- same as previous, but no need to know voxel dimensions */ #define GET_VOXEL_PTR( ptr, volume, x, y, z, t, v ) \ if( (volume)->is_cached_volume ) \ handle_internal_error( "Cannot get pointer to cached Volume.\n");\ else \ GET_MULTIDIM_PTR( ptr, (volume)->array, x, y, z, t, v ) /* --- returns the conversion of the 'voxel' value to a real value */ #define CONVERT_VOXEL_TO_VALUE( volume, voxel ) \ convert_voxel_to_value( volume, voxel ) /* --- returns the conversion of the 'real' value to a voxel value */ #define CONVERT_VALUE_TO_VOXEL( volume, value ) \ convert_value_to_voxel( volume, value ) /* --- assigns 'value' the value of the [x][y]...'th voxel of 'volume' */ #define GET_VALUE_1D_TYPED( value, vtype, volume, x ) \ { \ GET_VOXEL_1D_TYPED( value, vtype, volume, x ); \ value = CONVERT_VOXEL_TO_VALUE( volume, value ); \ } #define GET_VALUE_2D_TYPED( value, vtype, volume, x, y ) \ { \ GET_VOXEL_2D_TYPED( value, vtype, volume, x, y ); \ value = CONVERT_VOXEL_TO_VALUE( volume, value ); \ } #define GET_VALUE_3D_TYPED( value, vtype, volume, x, y, z ) \ { \ GET_VOXEL_3D_TYPED( value, vtype, volume, x, y, z ); \ value = CONVERT_VOXEL_TO_VALUE( volume, value ); \ } #define GET_VALUE_4D_TYPED( value, vtype, volume, x, y, z, t ) \ { \ GET_VOXEL_4D_TYPED( value, vtype, volume, x, y, z, t ); \ value = CONVERT_VOXEL_TO_VALUE( volume, value ); \ } #define GET_VALUE_5D_TYPED( value, vtype, volume, x, y, z, t, v ) \ { \ GET_VOXEL_5D_TYPED( value, vtype, volume, x, y, z, t, v ); \ value = CONVERT_VOXEL_TO_VALUE( volume, value ); \ } /* --- same as previous, without knowing number of dimensions of volume */ #define GET_VALUE_TYPED( value, vtype, volume, x, y, z, t, v ) \ switch( (volume)->n_dimensions ) \ { \ case 1: GET_VALUE_1D_TYPED( value, vtype, volume, x ); break; \ case 2: GET_VALUE_2D_TYPED( value, vtype, volume, x, y ); break; \ case 3: GET_VALUE_3D_TYPED( value, vtype, volume, x, y, z ); break; \ case 4: GET_VALUE_4D_TYPED( value, vtype, volume, x, y, z, t ); break; \ case 5: GET_VALUE_5D_TYPED( value, vtype, volume, x, y, z, t, v ); break; \ } /* --- assigns 'value' the value of the [x][y]...'th voxel of 'volume' */ #define GET_VALUE_1D( value, volume, x ) \ GET_VALUE_1D_TYPED( value, , volume, x ) #define GET_VALUE_2D( value, volume, x, y ) \ GET_VALUE_2D_TYPED( value, , volume, x, y ) #define GET_VALUE_3D( value, volume, x, y, z ) \ GET_VALUE_3D_TYPED( value, , volume, x, y, z ) #define GET_VALUE_4D( value, volume, x, y, z, t ) \ GET_VALUE_4D_TYPED( value, , volume, x, y, z, t ) #define GET_VALUE_5D( value, volume, x, y, z, t, v ) \ GET_VALUE_5D_TYPED( value, , volume, x, y, z, t, v ) /* --- same as previous, without knowing number of dimensions of volume */ #define GET_VALUE( value, volume, x, y, z, t, v ) \ GET_VALUE_TYPED( value, , volume, x, y, z, t, v ) /* -------------------- minc file struct -------------------- */ typedef struct { int arent_any_yet; } volume_creation_options; typedef struct { VIO_BOOL promote_invalid_to_zero_flag; VIO_BOOL convert_vector_to_scalar_flag; VIO_BOOL convert_vector_to_colour_flag; int dimension_size_for_colour_data; int max_dimension_size_for_colour_data; int rgba_indices[4]; double user_real_range[2]; } minc_input_options; typedef struct { VIO_BOOL file_is_being_read; /* input and output */ int cdfid; int img_var; int n_file_dimensions; long sizes_in_file[MAX_VAR_DIMS]; long indices[MAX_VAR_DIMS]; VIO_STR dim_names[MAX_VAR_DIMS]; VIO_Volume volume; int to_volume_index[MAX_VAR_DIMS]; int to_file_index[VIO_MAX_DIMENSIONS]; int minc_icv; VIO_STR filename; /* input only */ VIO_BOOL end_volume_flag; VIO_BOOL converting_to_colour; int rgba_indices[4]; int n_volumes_in_file; int valid_file_axes[VIO_MAX_DIMENSIONS]; int n_slab_dims; int spatial_axes[VIO_N_DIMENSIONS]; VIO_General_transform voxel_to_world_transform; minc_input_options original_input_options; /* output only */ int img_var_id; int min_id; int max_id; double image_range[2]; VIO_BOOL end_def_done; VIO_BOOL ignoring_because_cached; VIO_BOOL variables_written; int dim_ids[MAX_VAR_DIMS]; VIO_BOOL outputting_in_order; VIO_BOOL entire_file_written; nc_type nc_data_type; VIO_BOOL signed_flag; double valid_range[2]; int image_dims[MAX_VAR_DIMS]; int src_cdfid; int src_img_var; } minc_file_struct; typedef minc_file_struct *Minc_file; #define MNC_ENDING "mnc" /* --- recognized file formats */ typedef enum { MNC_FORMAT, FREE_FORMAT } Volume_file_formats; typedef struct { Volume_file_formats file_format; Minc_file minc_file; /* for free format files only */ FILE *volume_file; int slice_index; long sizes_in_file[VIO_MAX_DIMENSIONS]; int axis_index_from_file[VIO_MAX_DIMENSIONS]; VIO_Data_types file_data_type; VIO_BOOL one_file_per_slice; VIO_STR directory; VIO_STR *slice_filenames; int *slice_byte_offsets; unsigned char *byte_slice_buffer; unsigned short *short_slice_buffer; } volume_input_struct; /* --------------------- filter types -------------------------------- */ typedef enum { NEAREST_NEIGHBOUR, LINEAR_INTERPOLATION, BOX_FILTER, TRIANGLE_FILTER, GAUSSIAN_FILTER } Filter_types; #endif minc-2.2.00/volume_io/Include/volume_io/volume_cache.h0000644000265600003100000000776312027132664017641 00000000000000#ifndef DEF_VOLUME_CACHE #define DEF_VOLUME_CACHE /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io/volume_cache.h,v 1.11 2005-05-19 21:19:28 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : volume_cache.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Volume block caching mechanism for treating large volumes as if they are in memory. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 14, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #include typedef enum { SLICE_ACCESS, RANDOM_VOLUME_ACCESS } VIO_Cache_block_size_hints; #define CACHE_DEBUGGING #undef CACHE_DEBUGGING typedef struct VIO_cache_block_struct { int block_index; VIO_SCHAR modified_flag; VIO_multidim_array array; struct VIO_cache_block_struct *prev_used; struct VIO_cache_block_struct *next_used; struct VIO_cache_block_struct **prev_hash; struct VIO_cache_block_struct *next_hash; } VIO_cache_block_struct; typedef struct { int block_index_offset; int block_offset; } VIO_cache_lookup_struct; typedef struct { int n_dimensions; int file_offset[VIO_MAX_DIMENSIONS]; VIO_STR input_filename; VIO_STR output_filename; nc_type file_nc_data_type; VIO_BOOL file_signed_flag; VIO_Real file_voxel_min; VIO_Real file_voxel_max; VIO_STR original_filename; VIO_STR history; minc_output_options options; VIO_BOOL writing_to_temp_file; int total_block_size; int block_sizes[VIO_MAX_DIMENSIONS]; int blocks_per_dim[VIO_MAX_DIMENSIONS]; VIO_BOOL output_file_is_open; VIO_BOOL must_read_blocks_before_use; void *minc_file; int n_blocks; int max_cache_bytes; int max_blocks; int hash_table_size; VIO_cache_block_struct *head; VIO_cache_block_struct *tail; VIO_cache_block_struct **hash_table; VIO_cache_lookup_struct *lookup[VIO_MAX_DIMENSIONS]; VIO_cache_block_struct *previous_block; int previous_block_index; VIO_BOOL debugging_on; int n_accesses; int output_every; int n_hits; int n_prev_hits; } VIO_volume_cache_struct; #if !VIO_PREFIX_NAMES typedef VIO_Cache_block_size_hints Cache_block_size_hints; typedef VIO_cache_block_struct cache_block_struct; typedef VIO_cache_lookup_struct cache_lookup_struct; typedef VIO_volume_cache_struct volume_cache_struct; #endif /* !VIO_PREFIX_NAMES */ #endif minc-2.2.00/volume_io/Include/volume_io.h0000644000265600003100000000414612027132664015177 00000000000000#ifndef DEF_VOLUME_IO #define DEF_VOLUME_IO #ifdef __cplusplus extern "C" { #endif /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. @VERSION : $Header: /private-cvsroot/minc/volume_io/Include/volume_io.h,v 1.13 2005-05-19 21:19:27 bert Exp $ ---------------------------------------------------------------------------- */ /* ----------------------------- MNI Header ----------------------------------- @NAME : volume_io.h @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: A set of macros and definitions useful for all MNI programs. @METHOD : @GLOBALS : @CALLS : @CREATED : July 15, 1991 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #ifndef VIO_PREFIX_NAMES #define VIO_PREFIX_NAMES 0 /* Allow old-fashioned namespace pollution */ #endif /* VIO_PREFIX_NAMES */ #include #include #include #include #include #include #include #include #include #ifndef VIOAPI #if defined(_MSC_VER) #define VIOAPI __declspec(dllimport) #else #define VIOAPI extern #endif /* _MSC_VER not defined */ #endif /* VIOAPI not defined */ #include #ifdef __cplusplus } #endif #endif /* DEF_VOLUME_IO */ minc-2.2.00/volume_io/Include/internal_volume_io.h0000644000265600003100000000210712027132664017066 00000000000000#ifndef _INTERNAL_VOLUME_IO_H #define _INTERNAL_VOLUME_IO_H /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include "config.h" #ifndef VIOAPI #if defined(_MSC_VER) #define VIOAPI __declspec(dllexport) #else #define VIOAPI #endif /* _MSC_VER not defined */ #endif /* VIOAPI not defined */ #include #endif minc-2.2.00/volume_io/MNI_formats/0000755000265600003100000000000012030114722013663 500000000000000minc-2.2.00/volume_io/MNI_formats/gen_xf_io.c0000644000265600003100000005534512027132664015733 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /*--------------------- file format keywords ------------------------------ */ static const STRING TRANSFORM_FILE_HEADER = "MNI Transform File"; static const STRING TYPE_STRING = "Transform_Type"; static const STRING LINEAR_TRANSFORM_STRING = "Linear_Transform"; static const STRING LINEAR_TYPE = "Linear"; static const STRING THIN_PLATE_SPLINE_STRING = "Thin_Plate_Spline_Transform"; static const STRING INVERT_FLAG_STRING = "Invert_Flag"; static const STRING TRUE_STRING = "True"; static const STRING FALSE_STRING = "False"; static const STRING N_DIMENSIONS_STRING = "Number_Dimensions"; static const STRING POINTS_STRING = "Points"; static const STRING DISPLACEMENTS_STRING = "Displacements"; static const STRING GRID_TRANSFORM_STRING = "Grid_Transform"; static const STRING DISPLACEMENT_VOLUME = "Displacement_Volume"; /* ----------------------------- MNI Header ----------------------------------- @NAME : get_default_transform_file_suffix @INPUT : @OUTPUT : @RETURNS : "xfm" @DESCRIPTION: Returns the default transform file suffix. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING get_default_transform_file_suffix( void ) { return( "xfm" ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_one_transform @INPUT : file filename \ these two used to manufacture unique filenames volume_count / for grid transform volume files. invert - whether to invert the transform transform @OUTPUT : @RETURNS : @DESCRIPTION: Outputs a transform to the MNI transform file. : Increment *volume_count. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Feb 21, 1995 David MacDonald : added grid transforms ---------------------------------------------------------------------------- */ static void output_one_transform( FILE *file, STRING filename, int *volume_count, BOOLEAN invert, General_transform *transform ) { int i, c, trans; Transform *lin_transform; STRING volume_filename, base_filename, prefix_filename; switch( transform->type ) { case LINEAR: (void) fprintf( file, "%s = %s;\n", TYPE_STRING, LINEAR_TYPE ); (void) fprintf( file, "%s =\n", LINEAR_TRANSFORM_STRING ); if( invert ) lin_transform = get_inverse_linear_transform_ptr( transform ); else lin_transform = get_linear_transform_ptr( transform ); for_less( i, 0, 3 ) { (void) fprintf( file, " %.15g %.15g %.15g %.15g", Transform_elem(*lin_transform,i,0), Transform_elem(*lin_transform,i,1), Transform_elem(*lin_transform,i,2), Transform_elem(*lin_transform,i,3) ); if( i == 2 ) (void) fprintf( file, ";" ); (void) fprintf( file, "\n" ); } break; case THIN_PLATE_SPLINE: (void) fprintf( file, "%s = %s;\n", TYPE_STRING, THIN_PLATE_SPLINE_STRING); if( transform->inverse_flag ) invert = !invert; if( invert ) (void) fprintf( file, "%s = %s;\n", INVERT_FLAG_STRING,TRUE_STRING); (void) fprintf( file, "%s = %d;\n", N_DIMENSIONS_STRING, transform->n_dimensions ); (void) fprintf( file, "%s =\n", POINTS_STRING ); for_less( i, 0, transform->n_points ) { for_less( c, 0, transform->n_dimensions ) (void) fprintf( file, " %.15g", transform->points[i][c] ); if( i == transform->n_points-1 ) (void) fprintf( file, ";" ); (void) fprintf( file, "\n" ); } (void) fprintf( file, "%s =\n", DISPLACEMENTS_STRING ); for_less( i, 0, transform->n_points + transform->n_dimensions + 1 ) { for_less( c, 0, transform->n_dimensions ) (void) fprintf( file, " %.15g", transform->displacements[i][c]); if( i == transform->n_points + transform->n_dimensions + 1 - 1 ) (void) fprintf( file, ";" ); (void) fprintf( file, "\n" ); } break; case GRID_TRANSFORM: (void) fprintf( file, "%s = %s;\n", TYPE_STRING, GRID_TRANSFORM_STRING ); if( transform->inverse_flag ) invert = !invert; if( invert ) (void) fprintf( file, "%s = %s;\n", INVERT_FLAG_STRING,TRUE_STRING); /*--- the volume will be stored in a file of the same prefix as this transform, but ending in _grid.mnc */ if( filename == NULL || string_length(filename) == 0 ) prefix_filename = create_string( "grid" ); else { prefix_filename = create_string( filename ); i = string_length( prefix_filename ) - 1; while( i > 0 && prefix_filename[i] != '.' && prefix_filename[i] != '/' ) --i; if( i >= 0 && prefix_filename[i] == '.' ) prefix_filename[i] = END_OF_STRING; } /*--- write out the volume filename to the transform file */ volume_filename = alloc_string( string_length(prefix_filename) + 100 ); (void) sprintf( volume_filename, "%s_grid_%d.mnc", prefix_filename, *volume_count ); /* Increment the volume counter as a side-effect to ensure that grid * files have different names. */ (*volume_count)++; /*--- decide where to write the volume file */ base_filename = remove_directories_from_filename( volume_filename ); (void) fprintf( file, "%s = %s;\n", DISPLACEMENT_VOLUME, base_filename); /*--- write the volume file */ (void) output_volume( volume_filename, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, (Volume) transform->displacement_volume, NULL, NULL ); delete_string( prefix_filename ); delete_string( volume_filename ); delete_string( base_filename ); break; case USER_TRANSFORM: print_error( "Cannot output user transformation.\n" ); output_comments( file, "User transform goes here." ); break; case CONCATENATED_TRANSFORM: if( transform->inverse_flag ) invert = !invert; if( invert ) { for( trans = get_n_concated_transforms(transform)-1; trans >= 0; --trans ) { output_one_transform( file, filename, volume_count, invert, get_nth_general_transform(transform,trans) ); } } else { for_less( trans, 0, get_n_concated_transforms(transform) ) { output_one_transform( file, filename, volume_count, invert, get_nth_general_transform(transform,trans) ); } } break; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_transform file filename \ these two args used to manufacture unique volume_count_ptr / filenames for grid transform volumes comments - can be null transform @INPUT : @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Outputs the transform to the file in MNI transform format. The filename is used to define the prefix for writing out volumes that are part of grid transforms. The volume_count_ptr is used to give each volume written in a given file a unique index, and therefore a unique filename. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Feb. 21, 1995 D. MacDonald ---------------------------------------------------------------------------- */ VIOAPI Status output_transform( FILE *file, STRING filename, int *volume_count_ptr, STRING comments, General_transform *transform ) { int volume_count; /* --- parameter checking */ if( file == NULL ) { print_error( "output_transform(): passed NULL FILE ptr.\n" ); return( ERROR ); } /* --- okay write the file */ (void) fprintf( file, "%s\n", TRANSFORM_FILE_HEADER ); output_comments( file, comments ); (void) fprintf( file, "\n" ); /*--- if the user has not initialized the volume count, then do so */ if( volume_count_ptr == NULL ) { volume_count = 0; volume_count_ptr = &volume_count; } output_one_transform( file, filename, volume_count_ptr, FALSE, transform ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_one_transform @INPUT : file filename - used to get relative paths @OUTPUT : transform @RETURNS : OK or ERROR @DESCRIPTION: Inputs a transform from the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Feb. 21, 1995 David MacDonald - added grid transforms ---------------------------------------------------------------------------- */ static Status input_one_transform( FILE *file, STRING filename, General_transform *transform ) { Status status; int i, j, n_points, n_dimensions; Real **points, **displacements; Real value, *points_1d; STRING type_name, str, volume_filename, directory, tmp_filename; Volume volume; Transform linear_transform; Transform_types type; BOOLEAN inverse_flag; General_transform inverse; minc_input_options options; inverse_flag = FALSE; /* --- read the type of transform */ status = mni_input_keyword_and_equal_sign( file, TYPE_STRING, FALSE ); if( status != OK ) return( status ); if( mni_input_string( file, &type_name, (char) ';', (char) 0 ) != OK ) { print_error( "input_transform(): missing transform type.\n"); return( ERROR ); } if( mni_skip_expected_character( file, (char) ';' ) != OK ) return( ERROR ); if( equal_strings( type_name, LINEAR_TYPE ) ) type = LINEAR; else if( equal_strings( type_name, THIN_PLATE_SPLINE_STRING ) ) type = THIN_PLATE_SPLINE; else if( equal_strings( type_name, GRID_TRANSFORM_STRING ) ) type = GRID_TRANSFORM; else { delete_string( type_name ); print_error( "input_transform(): invalid transform type.\n"); return( ERROR ); } delete_string( type_name ); /* --- read the next string */ if( mni_input_string( file, &str, (char) '=', (char) 0 ) != OK ) return( ERROR ); if( equal_strings( str, INVERT_FLAG_STRING ) ) { delete_string( str ); if( mni_skip_expected_character( file, (char) '=' ) != OK ) return( ERROR ); if( mni_input_string( file, &str, (char) ';', (char) 0 ) != OK ) return( ERROR ); if( mni_skip_expected_character( file, (char) ';' ) != OK ) { delete_string( str ); return( ERROR ); } if( equal_strings( str, TRUE_STRING ) ) inverse_flag = TRUE; else if( equal_strings( str, FALSE_STRING ) ) inverse_flag = FALSE; else { delete_string( str ); print_error( "Expected %s or %s after %s =\n", TRUE_STRING, FALSE_STRING, INVERT_FLAG_STRING ); return( ERROR ); } delete_string( str ); if( mni_input_string( file, &str, (char) '=', (char) 0 ) != OK ) return( ERROR ); } switch( type ) { case LINEAR: if( !equal_strings( str, LINEAR_TRANSFORM_STRING ) ) { print_error( "Expected %s =\n", LINEAR_TRANSFORM_STRING ); delete_string( str ); return( ERROR ); } delete_string( str ); if( mni_skip_expected_character( file, (char) '=' ) != OK ) return( ERROR ); make_identity_transform( &linear_transform ); /* now read the 3 lines of transforms */ for_less( i, 0, 3 ) { for_less( j, 0, 4 ) { if( mni_input_real( file, &value ) != OK ) { print_error( "input_transform(): error reading transform elem [%d,%d]\n", i+1, j+1 ); return( ERROR ); } Transform_elem(linear_transform,i,j) = value; } } if( mni_skip_expected_character( file, (char) ';' ) != OK ) return( ERROR ); create_linear_transform( transform, &linear_transform ); break; case THIN_PLATE_SPLINE: /* --- read Number_Dimensions = 3; */ if( !equal_strings( str, N_DIMENSIONS_STRING ) ) { print_error( "Expected %s =\n", N_DIMENSIONS_STRING ); delete_string( str ); return( ERROR ); } delete_string( str ); if( mni_skip_expected_character( file, (char) '=' ) != OK ) return( ERROR ); if( mni_input_int( file, &n_dimensions ) != OK ) return( ERROR ); if( mni_skip_expected_character( file, (char) ';' ) != OK ) return( ERROR ); /* --- read Points = x y z x y z .... ; */ if( mni_input_keyword_and_equal_sign( file, POINTS_STRING, TRUE ) != OK) return( ERROR ); if( mni_input_reals( file, &n_points, &points_1d ) != OK ) return( ERROR ); if( n_points % n_dimensions != 0 ) { print_error( "Number of points (%d) must be multiple of number of dimensions (%d)\n", n_points, n_dimensions ); return( ERROR ); } n_points = n_points / n_dimensions; ALLOC2D( points, n_points, n_dimensions ); for_less( i, 0, n_points ) { for_less( j, 0, n_dimensions ) { points[i][j] = points_1d[IJ(i,j,n_dimensions)]; } } FREE( points_1d ); /* --- allocate and input the displacements */ ALLOC2D( displacements, n_points + n_dimensions + 1, n_dimensions ); if( mni_input_keyword_and_equal_sign( file, DISPLACEMENTS_STRING, TRUE ) != OK ) return( ERROR ); for_less( i, 0, n_points + n_dimensions + 1 ) { for_less( j, 0, n_dimensions ) { if( mni_input_real( file, &value ) != OK ) { print_error( "Expected more displacements.\n" ); return( ERROR ); } displacements[i][j] = value; } } if( mni_skip_expected_character( file, (char) ';' ) != OK ) return( ERROR ); create_thin_plate_transform_real( transform, n_dimensions, n_points, points, displacements ); FREE2D( points ); FREE2D( displacements ); break; case GRID_TRANSFORM: /*--- read the displacement volume filename */ if( !equal_strings( str, DISPLACEMENT_VOLUME ) ) { print_error( "Expected %s =\n", DISPLACEMENT_VOLUME ); delete_string( str ); return( ERROR ); } delete_string( str ); if( mni_skip_expected_character( file, (char) '=' ) != OK ) return( ERROR ); if( mni_input_string( file, &volume_filename, (char) ';', (char) 0 ) != OK ) return( ERROR ); if( mni_skip_expected_character( file, (char) ';' ) != OK ) { delete_string( volume_filename ); return( ERROR ); } /*--- if the volume filename is relative, add the required directory */ if( volume_filename[0] != '/' && filename != NULL ) { directory = extract_directory( filename ); if( string_length(directory) > 0 ) { tmp_filename = concat_strings( directory, "/" ); concat_to_string( &tmp_filename, volume_filename ); replace_string( &volume_filename, tmp_filename ); } delete_string( directory ); } /*--- input the displacement volume */ set_default_minc_input_options( &options ); set_minc_input_vector_to_scalar_flag( &options, FALSE ); if( input_volume( volume_filename, 4, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &volume, &options ) != OK ) { delete_string( volume_filename ); return( ERROR ); } delete_string( volume_filename ); /*--- create the transform */ create_grid_transform_no_copy( transform, volume ); break; } if( inverse_flag ) { create_inverse_general_transform( transform, &inverse ); delete_general_transform( transform ); *transform = inverse; } return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_transform @INPUT : file filename - used to define directory for relative filename @OUTPUT : transform @RETURNS : OK or ERROR @DESCRIPTION: Inputs the transform from the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Feb. 21, 1995 D. MacDonald ---------------------------------------------------------------------------- */ VIOAPI Status input_transform( FILE *file, STRING filename, General_transform *transform ) { Status status; int n_transforms; STRING line; General_transform next, concated; /* parameter checking */ if( file == (FILE *) 0 ) { print_error( "input_transform(): passed NULL FILE ptr.\n"); return( ERROR ); } /* okay read the header */ if( mni_input_string( file, &line, (char) 0, (char) 0 ) != OK ) { delete_string( line ); print_error( "input_transform(): could not read header in file.\n"); return( ERROR ); } if( !equal_strings( line, TRANSFORM_FILE_HEADER ) ) { delete_string( line ); print_error( "input_transform(): invalid header in file.\n"); return( ERROR ); } delete_string( line ); n_transforms = 0; while( (status = input_one_transform( file, filename, &next )) == OK ) { if( n_transforms == 0 ) *transform = next; else { concat_general_transforms( transform, &next, &concated ); delete_general_transform( transform ); delete_general_transform( &next ); *transform = concated; } ++n_transforms; } if( status == ERROR ) { print_error( "input_transform: error reading transform.\n" ); return( ERROR ); } else if( n_transforms == 0 ) { print_error( "input_transform: no transform present.\n" ); return( ERROR ); } return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_transform_file @INPUT : filename comments transform @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Opens the file, outputs the transform, and closes the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_transform_file( STRING filename, STRING comments, General_transform *transform ) { Status status; FILE *file; int volume_count; status = open_file_with_default_suffix( filename, get_default_transform_file_suffix(), WRITE_FILE, ASCII_FORMAT, &file ); volume_count = 0; if( status == OK ) status = output_transform( file, filename, &volume_count, comments, transform ); if( status == OK ) status = close_file( file ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_transform_file @INPUT : filename @OUTPUT : transform @RETURNS : OK or ERROR @DESCRIPTION: Opens the file, inputs the transform, and closes the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_transform_file( STRING filename, General_transform *transform ) { Status status; FILE *file; status = open_file_with_default_suffix( filename, get_default_transform_file_suffix(), READ_FILE, ASCII_FORMAT, &file ); if( status == OK ) status = input_transform( file, filename, transform ); if( status == OK ) status = close_file( file ); return( status ); } minc-2.2.00/volume_io/MNI_formats/gen_xfs.c0000644000265600003100000010234112027132664015414 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_linear_transform @INPUT : transform @OUTPUT : @RETURNS : @DESCRIPTION: Allocates memory for the linear transform and its inverse. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void alloc_linear_transform( General_transform *transform ) { transform->type = LINEAR; transform->inverse_flag = FALSE; ALLOC( transform->linear_transform, 1 ); ALLOC( transform->inverse_linear_transform, 1 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_linear_transform @INPUT : linear_transform @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a general transform of type linear, copying the linear_transform and computing its inverse. If the linear transform is NULL, the identity transform is created. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_linear_transform( General_transform *transform, Transform *linear_transform ) { alloc_linear_transform( transform ); if( linear_transform != (Transform *) NULL && compute_transform_inverse( linear_transform, transform->inverse_linear_transform ) ) { *(transform->linear_transform) = *linear_transform; } else { make_identity_transform( transform->linear_transform ); make_identity_transform( transform->inverse_linear_transform ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_thin_plate_transform @INPUT : transform n_dimensions n_points @OUTPUT : @RETURNS : @DESCRIPTION: Initializes a General_transform structure for thin plate transforms. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void initialize_thin_plate_transform( General_transform *transform, int n_dimensions, int n_points ) { transform->type = THIN_PLATE_SPLINE; transform->inverse_flag = FALSE; transform->n_dimensions = n_dimensions; transform->n_points = n_points; ALLOC2D( transform->points, n_points, n_dimensions ); ALLOC2D( transform->displacements, n_points + n_dimensions + 1, n_dimensions ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_thin_plate_transform_real @INPUT : n_dimensions n_points points displacements @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a general transform of type thin plate spline, given Real-type points and displacements. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Feb. 21, 1995 David MacDonald - make a real and float version ---------------------------------------------------------------------------- */ VIOAPI void create_thin_plate_transform_real( General_transform *transform, int n_dimensions, int n_points, Real **points, Real **displacements ) { int p, d; initialize_thin_plate_transform( transform, n_dimensions, n_points ); for_less( p, 0, n_points ) { for_less( d, 0, n_dimensions ) transform->points[p][d] = points[p][d]; } for_less( p, 0, n_points + n_dimensions + 1 ) { for_less( d, 0, n_dimensions ) transform->displacements[p][d] = displacements[p][d]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_thin_plate_transform @INPUT : n_dimensions n_points points displacements @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a general transform of type thin plate spline. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Feb. 21, 1995 David MacDonald - make a real and float version ---------------------------------------------------------------------------- */ VIOAPI void create_thin_plate_transform( General_transform *transform, int n_dimensions, int n_points, float **points, float **displacements ) { int p, d; initialize_thin_plate_transform( transform, n_dimensions, n_points ); for_less( p, 0, n_points ) { for_less( d, 0, n_dimensions ) transform->points[p][d] = (Real) points[p][d]; } for_less( p, 0, n_points + n_dimensions + 1 ) { for_less( d, 0, n_dimensions ) transform->displacements[p][d] = (Real) displacements[p][d]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : internal_create_grid_transform @INPUT : displacement_volume @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a general transform of type grid. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void internal_create_grid_transform( General_transform *transform, Volume displacement_volume, BOOLEAN copy_flag ) { int dim, sizes[MAX_DIMENSIONS], vector_dim; STRING *dim_names; Volume copy; BOOLEAN volume_ok, dim_found[N_DIMENSIONS]; volume_ok = TRUE; if( get_volume_n_dimensions(displacement_volume) != 4 ) { volume_ok = FALSE; print_error( "Grid transform must be 4 dimensional.\n" ); } else { dim_names = get_volume_dimension_names( displacement_volume ); get_volume_sizes( displacement_volume, sizes ); dim_found[X] = FALSE; dim_found[Y] = FALSE; dim_found[Z] = FALSE; vector_dim = -1; for_less( dim, 0, 4 ) { if( equal_strings( dim_names[dim], MIxspace ) ) dim_found[X] = TRUE; else if( equal_strings( dim_names[dim], MIyspace ) ) dim_found[Y] = TRUE; else if( equal_strings( dim_names[dim], MIzspace ) ) dim_found[Z] = TRUE; else { if( sizes[dim] != 3 ) { print_error( "displacement_volume must have 3 components on " ); print_error( "the non-spatial axis.\n" ); volume_ok = FALSE; } vector_dim = dim; } } if( !dim_found[X] || !dim_found[Y] || !dim_found[Z] ) { print_error( "Must have an x, y, and z dimension in displacement volume.\n" ); volume_ok = FALSE; } delete_dimension_names( displacement_volume, dim_names ); } if( !volume_ok ) { create_linear_transform( transform, NULL ); /*--- make identity */ return; } transform->type = GRID_TRANSFORM; transform->inverse_flag = FALSE; if( copy_flag ) copy = copy_volume( displacement_volume ); else copy = displacement_volume; /* --- force 4th dimension to be vector dimension */ replace_string( ©->dimension_names[vector_dim], create_string(MIvector_dimension) ); transform->displacement_volume = (void *) copy; } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_grid_transform @INPUT : displacement_volume @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a grid transform General_transform. Makes a copy of the displacement volume and puts it in the General_transform. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_grid_transform( General_transform *transform, Volume displacement_volume ) { internal_create_grid_transform( transform, displacement_volume, TRUE ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_grid_transform_no_copy @INPUT : displacement_volume @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a grid transform General_transform. Places the displacement volume into the General_transform; therefore the calling program should not delete the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_grid_transform_no_copy( General_transform *transform, Volume displacement_volume ) { internal_create_grid_transform( transform, displacement_volume, FALSE ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_user_transform @INPUT : user_data size_user_data transform_function inverse_transform_function @OUTPUT : transform @RETURNS : @DESCRIPTION: Creates a general transform of type user transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_user_transform( General_transform *transform, void *user_data, size_t size_user_data, User_transform_function transform_function, User_transform_function inverse_transform_function ) { unsigned char *byte_ptr; transform->type = USER_TRANSFORM; transform->inverse_flag = FALSE; transform->size_user_data = size_user_data; ALLOC( byte_ptr, size_user_data ); transform->user_data = byte_ptr; (void) memcpy( transform->user_data, user_data, size_user_data ); transform->user_transform_function = transform_function; transform->user_inverse_transform_function = inverse_transform_function; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_transform_type @INPUT : transform @OUTPUT : @RETURNS : type @DESCRIPTION: Returns the type of the general transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Transform_types get_transform_type( General_transform *transform ) { return( transform->type ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_n_concated_transforms @INPUT : transform @OUTPUT : @RETURNS : # transforms @DESCRIPTION: Returns the number of concatenated transforms if the transform type is concatenated, otherwise, 1. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_n_concated_transforms( General_transform *transform ) { if( transform->type == CONCATENATED_TRANSFORM ) return( transform->n_transforms ); else return( 1 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_nth_general_transform @INPUT : transform n @OUTPUT : @RETURNS : pointer to nth transform @DESCRIPTION: Returns a pointer to the nth transform of the general transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI General_transform *get_nth_general_transform( General_transform *transform, int n ) { if( n < 0 || n >= get_n_concated_transforms( transform ) ) { handle_internal_error( "get_nth_general_transform" ); return( (General_transform *) NULL ); } else if( transform->type == CONCATENATED_TRANSFORM ) return( &transform->transforms[n] ); else return( transform ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_linear_transform_ptr @INPUT : transform @OUTPUT : @RETURNS : pointer to linear transform @DESCRIPTION: Returns a pointer to the linear transform of the general transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Transform *get_linear_transform_ptr( General_transform *transform ) { if( transform->type == LINEAR ) { if( transform->inverse_flag ) return( transform->inverse_linear_transform ); else return( transform->linear_transform ); } else { handle_internal_error( "get_linear_transform_ptr" ); return( (Transform *) NULL ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_inverse_linear_transform_ptr @INPUT : transform @OUTPUT : @RETURNS : pointer to inverse linear transform @DESCRIPTION: Returns a pointer to the inverse linear transform of the general transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Transform *get_inverse_linear_transform_ptr( General_transform *transform ) { if( transform->type == LINEAR ) { if( transform->inverse_flag ) return( transform->linear_transform ); else return( transform->inverse_linear_transform ); } else { handle_internal_error( "get_inverse_linear_transform_ptr" ); return( (Transform *) NULL ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : transform_or_invert_point @INPUT : transform inverse_flag x y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : @DESCRIPTION: Transforms a point by the general transform or its inverse, depending on inverse_flag. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Feb. 27, 1995 D. MacDonald - added grid transforms ---------------------------------------------------------------------------- */ static void transform_or_invert_point( General_transform *transform, BOOLEAN inverse_flag, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { int trans; switch( transform->type ) { case LINEAR: if( inverse_flag ) transform_point( transform->inverse_linear_transform, x, y, z, x_transformed, y_transformed, z_transformed ); else transform_point( transform->linear_transform, x, y, z, x_transformed, y_transformed, z_transformed ); break; case THIN_PLATE_SPLINE: if( inverse_flag ) { thin_plate_spline_inverse_transform( transform->n_dimensions, transform->n_points, transform->points, transform->displacements, x, y, z, x_transformed, y_transformed, z_transformed ); } else { thin_plate_spline_transform( transform->n_dimensions, transform->n_points, transform->points, transform->displacements, x, y, z, x_transformed, y_transformed, z_transformed ); } break; case GRID_TRANSFORM: if( inverse_flag ) { grid_inverse_transform_point( transform, x, y, z, x_transformed, y_transformed, z_transformed ); } else { grid_transform_point( transform, x, y, z, x_transformed, y_transformed, z_transformed ); } break; case USER_TRANSFORM: if( inverse_flag ) { transform->user_inverse_transform_function( transform->user_data, x, y, z, x_transformed, y_transformed, z_transformed ); } else { transform->user_transform_function( transform->user_data, x, y, z, x_transformed, y_transformed, z_transformed ); } break; case CONCATENATED_TRANSFORM: *x_transformed = x; *y_transformed = y; *z_transformed = z; if( inverse_flag ) { for( trans = transform->n_transforms-1; trans >= 0; --trans ) { general_inverse_transform_point( &transform->transforms[trans], *x_transformed, *y_transformed, *z_transformed, x_transformed, y_transformed, z_transformed ); } } else { for_less( trans, 0, transform->n_transforms ) { general_transform_point( &transform->transforms[trans], *x_transformed, *y_transformed, *z_transformed, x_transformed, y_transformed, z_transformed ); } } break; default: handle_internal_error( "transform_or_invert_point" ); break; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : general_transform_point @INPUT : transform x y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : @DESCRIPTION: Transforms a point by the general transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void general_transform_point( General_transform *transform, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { transform_or_invert_point( transform, transform->inverse_flag, x, y, z, x_transformed, y_transformed, z_transformed ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : general_inverse_transform_point @INPUT : transform x y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : @DESCRIPTION: Transforms a point by the inverse of the general transform. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void general_inverse_transform_point( General_transform *transform, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { transform_or_invert_point( transform, !transform->inverse_flag, x, y, z, x_transformed, y_transformed, z_transformed ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_and_invert_transform @INPUT : transform invert_it @OUTPUT : copy @RETURNS : @DESCRIPTION: Copies the transform or its inverse to copy. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : @MODIFIED : Feb. 27, 1995 D. MacDonald - added grid transforms ---------------------------------------------------------------------------- */ static void copy_and_invert_transform( General_transform *transform, BOOLEAN invert_it, General_transform *copy ) { unsigned char *byte_ptr; Transform *swap; int i, j, trans; *copy = *transform; switch( transform->type ) { case LINEAR: alloc_linear_transform( copy ); *(copy->linear_transform) = *(transform->linear_transform); *(copy->inverse_linear_transform) = *(transform->inverse_linear_transform); if( transform->inverse_flag ) invert_it = !invert_it; if( invert_it ) { swap = copy->linear_transform; copy->linear_transform = copy->inverse_linear_transform; copy->inverse_linear_transform = swap; } copy->inverse_flag = FALSE; break; case THIN_PLATE_SPLINE: ALLOC2D( copy->points, copy->n_points, copy->n_dimensions); ALLOC2D( copy->displacements, copy->n_points + copy->n_dimensions + 1, copy->n_dimensions); for_less( i, 0, copy->n_points ) for_less( j, 0, copy->n_dimensions ) copy->points[i][j] = transform->points[i][j]; for_less( i, 0, copy->n_points + copy->n_dimensions + 1 ) for_less( j, 0, copy->n_dimensions ) copy->displacements[i][j] = transform->displacements[i][j]; if( invert_it ) copy->inverse_flag = !copy->inverse_flag; break; case GRID_TRANSFORM: copy->displacement_volume = (void *) copy_volume( (Volume) transform->displacement_volume ); if( invert_it ) copy->inverse_flag = !copy->inverse_flag; break; case USER_TRANSFORM: ALLOC( byte_ptr, copy->size_user_data ); copy->user_data = byte_ptr; (void) memcpy( copy->user_data, transform->user_data, copy->size_user_data ); if( invert_it ) copy->inverse_flag = !copy->inverse_flag; break; case CONCATENATED_TRANSFORM: ALLOC( copy->transforms, copy->n_transforms ); for_less( trans, 0, copy->n_transforms ) { copy_general_transform( &transform->transforms[trans], ©->transforms[trans] ); } if( invert_it ) copy->inverse_flag = !copy->inverse_flag; break; default: handle_internal_error( "copy_and_invert_transform" ); break; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_general_transform @INPUT : transform @OUTPUT : copy @RETURNS : @DESCRIPTION: Copies the general transform to copy. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void copy_general_transform( General_transform *transform, General_transform *copy ) { copy_and_invert_transform( transform, FALSE, copy ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : invert_general_transform @INPUT : transform @OUTPUT : transform @RETURNS : @DESCRIPTION: Inverts a general transform in place. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 20, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void invert_general_transform( General_transform *transform ) { transform->inverse_flag = !transform->inverse_flag; } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_inverse_general_transform @INPUT : transform @OUTPUT : inverse @RETURNS : @DESCRIPTION: Creates a general transform that is the inverse of the given one. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_inverse_general_transform( General_transform *transform, General_transform *inverse ) { copy_and_invert_transform( transform, TRUE, inverse ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : concat_general_transforms @INPUT : first second @OUTPUT : result @RETURNS : @DESCRIPTION: Concatenates two general transforms into result. Transforming a point by result is the same as transforming it by 'first', then transforming by 'second'. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void concat_general_transforms( General_transform *first, General_transform *second, General_transform *result ) { int first_start, first_end, first_step; int second_start, second_end, second_step; int i, trans; BOOLEAN crunching_linear; BOOLEAN first_inverted_concat, second_inverted_concat; Transform *first_transform, *first_inverse; Transform *second_transform, *second_inverse; General_transform result_tmp, *result_ptr; General_transform *transform; if( result == first || result == second ) result_ptr = &result_tmp; else result_ptr = result; first_inverted_concat = first->type == CONCATENATED_TRANSFORM && first->inverse_flag; second_inverted_concat = second->type == CONCATENATED_TRANSFORM && second->inverse_flag; if( first->inverse_flag ) { first_start = get_n_concated_transforms( first ) - 1; first_end = 0; first_step = -1; } else { first_start = 0; first_end = get_n_concated_transforms( first ) - 1; first_step = 1; } if( second->inverse_flag ) { second_start = get_n_concated_transforms( second ) - 1; second_end = 0; second_step = -1; } else { second_start = 0; second_end = get_n_concated_transforms( second ) - 1; second_step = 1; } result_ptr->n_transforms = ABS( first_end - first_start ) + 1 + ABS( second_end - second_start ) + 1; crunching_linear = FALSE; if( get_nth_general_transform( first, first_end )->type == LINEAR && get_nth_general_transform( second, second_start )->type == LINEAR ) { --result_ptr->n_transforms; crunching_linear = TRUE; first_end -= first_step; second_start += second_step; } if( result_ptr->n_transforms == 1 ) result_ptr->type = LINEAR; else { result_ptr->type = CONCATENATED_TRANSFORM; ALLOC( result_ptr->transforms, result_ptr->n_transforms ); } result_ptr->inverse_flag = FALSE; trans = 0; for( i = first_start; i != first_end + first_step; i += first_step ) { copy_and_invert_transform( get_nth_general_transform( first, i ), first_inverted_concat, get_nth_general_transform(result_ptr,trans)); ++trans; } if( crunching_linear ) { transform = get_nth_general_transform( result_ptr, trans ); alloc_linear_transform( transform ); if( first_inverted_concat ) { first_inverse = get_linear_transform_ptr( get_nth_general_transform(first,first_end+first_step)); first_transform = get_inverse_linear_transform_ptr( get_nth_general_transform(first,first_end+first_step)); } else { first_transform = get_linear_transform_ptr( get_nth_general_transform(first,first_end+first_step)); first_inverse = get_inverse_linear_transform_ptr( get_nth_general_transform(first,first_end+first_step)); } if( second_inverted_concat ) { second_inverse = get_linear_transform_ptr( get_nth_general_transform(second,second_start-second_step)); second_transform = get_inverse_linear_transform_ptr( get_nth_general_transform(second,second_start-second_step)); } else { second_transform = get_linear_transform_ptr( get_nth_general_transform(second,second_start-second_step)); second_inverse = get_inverse_linear_transform_ptr( get_nth_general_transform(second,second_start-second_step)); } concat_transforms( get_linear_transform_ptr(transform), first_transform, second_transform ); concat_transforms( get_inverse_linear_transform_ptr(transform), second_inverse, first_inverse ); ++trans; } for( i = second_start; i != second_end + second_step; i += second_step ) { copy_and_invert_transform( get_nth_general_transform( second, i ), second_inverted_concat, get_nth_general_transform(result_ptr,trans)); ++trans; } if( result == first || result == second ) *result = *result_ptr; } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_general_transform @INPUT : transform @OUTPUT : @RETURNS : @DESCRIPTION: Deletes the transform, freeing up memory. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : @MODIFIED : Feb. 27, 1995 D. MacDonald - added grid transforms ---------------------------------------------------------------------------- */ VIOAPI void delete_general_transform( General_transform *transform ) { int trans; switch( transform->type ) { case LINEAR: FREE( transform->linear_transform ); FREE( transform->inverse_linear_transform ); break; case THIN_PLATE_SPLINE: if( transform->n_points > 0 && transform->n_dimensions > 0 ) { FREE2D( transform->points ); FREE2D( transform->displacements ); } break; case GRID_TRANSFORM: delete_volume( (Volume) transform->displacement_volume ); break; case USER_TRANSFORM: if( transform->size_user_data ) FREE( transform->user_data ); break; case CONCATENATED_TRANSFORM: for_less( trans, 0, transform->n_transforms ) delete_general_transform( &transform->transforms[trans] ); if( transform->n_transforms > 0 ) FREE( transform->transforms ); break; default: handle_internal_error( "delete_general_transform" ); break; } } minc-2.2.00/volume_io/MNI_formats/grid_transforms.c0000644000265600003100000004335212027132664017174 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #define DEGREES_CONTINUITY 2 /* -1 = Nearest; 0 = Linear; 1 = Quadratic; 2 = Cubic interpolation */ #define SPLINE_DEGREE ((DEGREES_CONTINUITY) + 2) #define N_COMPONENTS N_DIMENSIONS /* displacement vector has 3 components */ #define FOUR_DIMS 4 #define INVERSE_FUNCTION_TOLERANCE 0.01 #define INVERSE_DELTA_TOLERANCE 1.0e-5 #define MAX_INVERSE_ITERATIONS 20 static void evaluate_grid_volume( Volume volume, Real x, Real y, Real z, int degrees_continuity, Real values[], Real deriv_x[], Real deriv_y[], Real deriv_z[] ); /* ----------------------------- MNI Header ----------------------------------- @NAME : grid_transform_point @INPUT : transform x y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : @DESCRIPTION: Applies a grid transform to the point @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void grid_transform_point( General_transform *transform, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { Real displacements[N_COMPONENTS]; Volume volume; /* --- the volume that defines the transform is an offset vector, so evaluate the volume at the given position and add the resulting offset to the given position */ volume = (Volume) transform->displacement_volume; evaluate_grid_volume( volume, x, y, z, DEGREES_CONTINUITY, displacements, NULL, NULL, NULL ); *x_transformed = x + displacements[X]; *y_transformed = y + displacements[Y]; *z_transformed = z + displacements[Z]; } #ifdef USE_NEWTONS_METHOD /* ----------------------------- MNI Header ----------------------------------- @NAME : forward_function @INPUT : function_data - contains transform info parameters - x,y,z position @OUTPUT : values - where x,y,z, maps to derivatives - the 3 by 3 derivatives of the mapping @RETURNS : @DESCRIPTION: This function does the same thing as grid_transform_point(), but also gets derivatives. This function is passed to the newton function solution routine to perform the inverse mapping of the grid transformation. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. , 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ private void forward_function( void *function_data, Real parameters[], Real values[], Real **derivatives ) { int c; General_transform *transform; Real deriv_x[N_COMPONENTS], deriv_y[N_COMPONENTS]; Real deriv_z[N_COMPONENTS]; Volume volume; transform = (General_transform *) function_data; /* --- store the offset vector in values[0-2] */ volume = transform->displacement_volume; evaluate_grid_volume( volume, parameters[X], parameters[Y], parameters[Z], DEGREES_CONTINUITY, values, deriv_x, deriv_y, deriv_z ); for_less( c, 0, N_COMPONENTS ) { values[c] += parameters[c]; /* to get x',y',z', add offset to x,y,z */ /*--- given the derivatives of the offset, compute the derivatives of (x,y,z) + offset, with respect to x,y,z */ derivatives[c][X] = deriv_x[c]; derivatives[c][Y] = deriv_y[c]; derivatives[c][Z] = deriv_z[c]; derivatives[c][c] += 1.0; /* deriv of (x,y,z) w.r.t. x or y or z */ } } /* ----------------------------- MNI Header ----------------------------------- @NAME : grid_inverse_transform_point @INPUT : transform x y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : @DESCRIPTION: Applies the inverse grid transform to the point. This is done by using newton-rhapson steps to find the point which maps to the parameters (x,y,z). @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- There are two different versions of the grid inverse function. I would have hoped that my version worked best, since it uses first derivatives and Newton's method. However, Louis' version seems to work better, perhaps since it matches the code he uses in minctracc to generate the grid transforms. - David MacDonald ---------------------------------------------------------------------------- */ VIOAPI void grid_inverse_transform_point( General_transform *transform, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { Real solution[N_DIMENSIONS]; Real initial_guess[N_DIMENSIONS]; Real desired_values[N_DIMENSIONS]; /* --- fill in the initial guess */ initial_guess[X] = x; initial_guess[Y] = y; initial_guess[Z] = z; /* --- define what the desired function values are */ desired_values[X] = x; desired_values[Y] = y; desired_values[Z] = z; /* --- find the x,y,z that are mapped to the desired values */ if( newton_root_find( N_DIMENSIONS, forward_function, (void *) transform, initial_guess, desired_values, solution, INVERSE_FUNCTION_TOLERANCE, INVERSE_DELTA_TOLERANCE, MAX_INVERSE_ITERATIONS )) { *x_transformed = solution[X]; *y_transformed = solution[Y]; *z_transformed = solution[Z]; } else /* --- if no solution found, not sure what is reasonable to return */ { *x_transformed = x; *y_transformed = y; *z_transformed = z; } } #endif /* ----------------------------- MNI Header ----------------------------------- @NAME : grid_inverse_transform_point @INPUT : transform x y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : @DESCRIPTION: Transforms the point by the inverse of the grid transform. Approximates the solution using a simple iterative step method. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993? Louis Collins @MODIFIED : 1994 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void grid_inverse_transform_point( General_transform *transform, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { #define NUMBER_TRIES 10 int tries; Real best_x, best_y, best_z; Real tx, ty, tz; Real gx, gy, gz; Real error_x, error_y, error_z, error, smallest_e; Real ftol; grid_transform_point( transform, x, y, z, &tx, &ty, &tz ); tx = x - (tx - x); ty = y - (ty - y); tz = z - (tz - z); grid_transform_point( transform, tx, ty, tz, &gx, &gy, &gz ); error_x = x - gx; error_y = y - gy; error_z = z - gz; tries = 0; error = smallest_e = FABS(error_x) + FABS(error_y) + FABS(error_z); best_x = tx; best_y = ty; best_z = tz; // Adapt ftol to grid step sizes. For 1mm stx volume with grid 4mm, we // are using ftol=0.05 (=4mm/80). For histology data at grid 0.125mm, // then use ftol=0.125/80=0.0015625, which is fine on 0.01mm volume. // ftol = 0.05; // good for MNI space at 1mm (grid 2mm or 4mm) // ftol = 0.001; // acceptable for big brain slice (grid at 0.125, voxel at 0.01mm) // This is ok too: // Make the error a fraction of the initial residual. // ftol = 0.05 * smallest_e + 0.0001; int sizes[MAX_DIMENSIONS]; Real steps[MAX_DIMENSIONS]; Volume volume = (Volume) transform->displacement_volume; get_volume_sizes( volume, sizes ); get_volume_separations( volume, steps ); /*--- find which of 4 dimensions is the vector dimension */ short d, vector_dim = -1; for_less( vector_dim, 0, FOUR_DIMS ) { for_less( d, 0, N_DIMENSIONS ) { if( volume->spatial_axes[d] == vector_dim ) break; } if( d == N_DIMENSIONS ) break; } ftol = -1.0; for_less( d, 0, FOUR_DIMS ) { if( d == vector_dim ) continue; if( sizes[d] == 1 ) continue; if( ftol < 0 ) ftol = steps[d]; if( steps[d] < ftol ) ftol = steps[d]; } ftol = ftol / 80.0; if( ftol > 0.05 ) ftol = 0.05; // just to be sure for large grids while( ++tries < NUMBER_TRIES && smallest_e > ftol ) { tx += 0.95 * error_x; ty += 0.95 * error_y; tz += 0.95 * error_z; grid_transform_point( transform, tx, ty, tz, &gx, &gy, &gz ); error_x = x - gx; error_y = y - gy; error_z = z - gz; error = FABS(error_x) + FABS(error_y) + FABS(error_z); if( error < smallest_e ) { smallest_e = error; best_x = tx; best_y = ty; best_z = tz; } } *x_transformed = best_x; *y_transformed = best_y; *z_transformed = best_z; } /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_grid_volume @INPUT : volume voxel degrees_continuity @OUTPUT : values derivs (if non-NULL) @RETURNS : @DESCRIPTION: Takes a voxel space position and evaluates the value within the volume by nearest_neighbour, linear, quadratic, or cubic interpolation. Rather than use the generic evaluate_volume function, this special purpose function is a bit faster. @CREATED : Mar. 16, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void evaluate_grid_volume( Volume volume, Real x, Real y, Real z, int degrees_continuity, Real values[], Real deriv_x[], Real deriv_y[], Real deriv_z[] ) { Real voxel[MAX_DIMENSIONS], voxel_vector[MAX_DIMENSIONS]; int inc0, inc1, inc2, inc3, inc[MAX_DIMENSIONS], derivs_per_value; int ind0, vector_dim; int start0, start1, start2, start3, inc_so_far; int end0, end1, end2, end3; int v0, v1, v2, v3; int v, d, id, sizes[MAX_DIMENSIONS]; int start[MAX_DIMENSIONS]; int end[MAX_DIMENSIONS]; Real fraction[MAX_DIMENSIONS], bound, pos; Real coefs[SPLINE_DEGREE*SPLINE_DEGREE*SPLINE_DEGREE*N_COMPONENTS]; Real values_derivs[N_COMPONENTS + N_COMPONENTS * N_DIMENSIONS]; convert_world_to_voxel( volume, x, y, z, voxel ); if( get_volume_n_dimensions(volume) != FOUR_DIMS ) handle_internal_error( "evaluate_grid_volume" ); /*--- find which of 4 dimensions is the vector dimension */ for_less( vector_dim, 0, FOUR_DIMS ) { for_less( d, 0, N_DIMENSIONS ) { if( volume->spatial_axes[d] == vector_dim ) break; } if( d == N_DIMENSIONS ) break; } get_volume_sizes( volume, sizes ); /*--- if a 2-d slice, do best interpolation in the plane */ int is_2dslice = -1; for_less( d, 0, FOUR_DIMS ) { if( d == vector_dim ) continue; if( sizes[d] == 1 ) { is_2dslice = d; } } bound = (Real) degrees_continuity / 2.0; /*--- if near the edges, reduce the degrees of continuity. This is very important. Doing cubic (with a shifted stencil) near a boundary will cause trouble because the stencil needs to be centered. This is why quadratic is also disabled (not symmetric stencil). CL. */ for_less( d, 0, FOUR_DIMS ) { if( d == is_2dslice ) continue; if( d == vector_dim ) continue; while( degrees_continuity >= -1 && (voxel[d] < bound || voxel[d] > (Real) sizes[d] - 1.0 - bound || bound == (Real) sizes[d] - 1.0 - bound ) ) { --degrees_continuity; if( degrees_continuity == 1 ) degrees_continuity = 0; bound = (Real) degrees_continuity / 2.0; } } /*--- check to fill in the first derivative */ if( degrees_continuity < 0 && deriv_x != NULL ) { for_less( v, 0, N_COMPONENTS ) { deriv_x[v] = 0.0; deriv_y[v] = 0.0; deriv_z[v] = 0.0; } } /*--- check if outside */ for( d = 0; d < FOUR_DIMS; d++ ) { if( d == vector_dim ) continue; if( voxel[d] < -0.5 || voxel[d] > sizes[d]-0.5 ) { for_less( v, 0, N_COMPONENTS ) { values[v] = 0.0; } return; } } /*--- determine the starting positions in the volume to grab control vertices */ id = 0; for_less( d, 0, FOUR_DIMS ) { if( d == vector_dim ) continue; if( d == is_2dslice ) { pos = 0.0; start[d] = 0; end[d] = 1; } else { pos = voxel[d] - bound; start[d] = FLOOR( pos ); if( start[d] < 0 ) { start[d] = 0; } else if( start[d]+degrees_continuity+1 >= sizes[d] ) { start[d] = sizes[d] - degrees_continuity - 2; } end[d] = start[d] + degrees_continuity + 2; fraction[id] = pos - (double) start[d]; ++id; } } /*--- create the strides */ start[vector_dim] = 0; end[vector_dim] = N_COMPONENTS; inc_so_far = N_COMPONENTS; for_down( d, FOUR_DIMS-1, 0 ) { if( d != vector_dim ) { inc[d] = inc_so_far; inc_so_far *= ( end[d] - start[d] ); } } /*--- copy stride arrays to variables for speed */ inc[vector_dim] = 1; start0 = start[0]; start1 = start[1]; start2 = start[2]; start3 = start[3]; end0 = end[0]; end1 = end[1]; end2 = end[2]; end3 = end[3]; inc0 = inc[0] - inc[1] * (end1 - start1); inc1 = inc[1] - inc[2] * (end2 - start2); inc2 = inc[2] - inc[3] * (end3 - start3); inc3 = inc[3]; /*--- extract values from volume */ ind0 = 0; for_less( v0, start0, end0 ) { for_less( v1, start1, end1 ) { for_less( v2, start2, end2 ) { for_less( v3, start3, end3 ) { GET_VALUE_4D_TYPED( coefs[ind0], (Real), volume, v0, v1, v2, v3 ); ind0 += inc3; } ind0 += inc2; } ind0 += inc1; } ind0 += inc0; } /*--- interpolate values */ if( degrees_continuity == -1 ) { for_less( v, 0, N_COMPONENTS ) values[v] = coefs[v]; } else { if( is_2dslice == -1 ) { evaluate_interpolating_spline( N_DIMENSIONS, fraction, degrees_continuity + 2, N_COMPONENTS, coefs, 0, values_derivs ); } else { evaluate_interpolating_spline( N_DIMENSIONS-1, fraction, degrees_continuity + 2, N_COMPONENTS, coefs, 0, values_derivs ); } /*--- extract values and derivatives from values_derivs */ if( deriv_x != NULL ) derivs_per_value = 8; else derivs_per_value = 1; for_less( v, 0, N_COMPONENTS ) { values[v] = values_derivs[v*derivs_per_value]; } if( deriv_x != NULL ) { for_less( v, 0, N_COMPONENTS ) { id = 0; for_less( d, 0, FOUR_DIMS ) { if( d != vector_dim ) { voxel_vector[d] = values_derivs[v*8 + (4>>id)]; ++id; } else voxel_vector[d] = 0.0; } convert_voxel_normal_vector_to_world( volume, voxel_vector, &deriv_x[v], &deriv_y[v], &deriv_z[v] ); } } } } minc-2.2.00/volume_io/MNI_formats/mni_io.c0000644000265600003100000002723512027132664015245 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include static const char COMMENT_CHAR1 = '%'; static const char COMMENT_CHAR2 = '#'; /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_get_nonwhite_character @INPUT : file @OUTPUT : ch @RETURNS : OK or END_OF_FILE @DESCRIPTION: Gets the next non white space character from the MNI file (i.e., tags or transforms). This routine handles comment characters, and is thus the base routine for all MNI tag or transform file input. Any part of a line starting with a comment character is ignored. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_get_nonwhite_character( FILE *file, char *ch ) { BOOLEAN in_comment; Status status; in_comment = FALSE; do { status = input_character( file, ch ); if( status == OK ) if( *ch == COMMENT_CHAR1 || *ch == COMMENT_CHAR2 ) in_comment = TRUE; else if( *ch == '\n' ) in_comment = FALSE; } while( status == OK && (in_comment || *ch == ' ' || *ch == '\t' || *ch == '\n' || *ch == '\r') ); /* ignore carriage returns */ if( status == ERROR ) status = END_OF_FILE; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_skip_expected_character @INPUT : file expected_ch @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Gets the next nonwhite character. If it is the expected character, fine, otherwise print an error message. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_skip_expected_character( FILE *file, char expected_ch ) { char ch; Status status; status = mni_get_nonwhite_character( file, &ch ); if( status == OK ) { if( ch != expected_ch ) { print_error( "Expected '%c', found '%c'.\n", expected_ch, ch ); status = ERROR; } } else { print_error( "Expected '%c', found end of file.\n", expected_ch ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_input_line @INPUT : file max_length @OUTPUT : string @RETURNS : OK or END_OF_FILE @DESCRIPTION: Inputs a line of text from a file. The carriage return is read, but not placed in the string. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_input_line( FILE *file, STRING *string ) { Status status; char ch; *string = create_string( NULL ); status = input_character( file, &ch ); while( status == OK && ch != '\n' ) { if (ch != '\r') { /* Always ignore carriage returns */ concat_char_to_string( string, ch ); } status = input_character( file, &ch ); } if( status != OK ) { delete_string( *string ); *string = NULL; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_input_string @INPUT : file max_length termination_char1 termination_char2 @OUTPUT : string @RETURNS : OK or END_OF_FILE @DESCRIPTION: Inputs a string from the file, up to the next occurrence of one of the termination characters or a carriage return. If the first nonwhite character is a '"', then the termination characters become '"'. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_input_string( FILE *file, STRING *string, char termination_char1, char termination_char2 ) { Status status; char ch; BOOLEAN quoted; *string = create_string( NULL ); status = mni_get_nonwhite_character( file, &ch ); if( status == OK && ch == '"' ) { quoted = TRUE; status = mni_get_nonwhite_character( file, &ch ); termination_char1 = '"'; termination_char2 = '"'; } else quoted = FALSE; while( status == OK && ch != termination_char1 && ch != termination_char2 && ch != '\n' ) { if (ch != '\r') { /* Always ignore carriage returns */ concat_char_to_string( string, ch ); } status = input_character( file, &ch ); } if( !quoted ) (void) unget_character( file, ch ); while( string_length(*string) > 0 && (*string)[string_length(*string)-1] == ' ' ) (*string)[string_length(*string)-1] = END_OF_STRING; if( status != OK ) { delete_string( *string ); *string = NULL; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_input_keyword_and_equal_sign @INPUT : file keyword print_error_message - whether to print error messages @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Inputs the desired keyword from the file and an equal sign. If there is no match, then an error message may be printed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_input_keyword_and_equal_sign( FILE *file, const char keyword[], BOOLEAN print_error_message ) { Status status; STRING str; status = mni_input_string( file, &str, (char) '=', (char) 0 ); if( status == END_OF_FILE ) return( status ); if( status != OK || !equal_strings( str, (STRING) keyword ) || mni_skip_expected_character( file, (char) '=' ) != OK ) { if( print_error_message ) print_error( "Expected \"%s =\"\n", keyword ); status = ERROR; } delete_string( str ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : unget_string @INPUT : file str @OUTPUT : @RETURNS : @DESCRIPTION: Places the first nonblank character of the string back onto the input stream, as an approximation to pushing the entire string back on the input stream, which only happens in error situations. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void unget_string( FILE *file, STRING str ) { int len; len = 0; while( str[len] == ' ' || str[len] == '\t' ) ++len; if( str[len] != END_OF_STRING ) (void) unget_character( file, str[len] ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_input_real @INPUT : file @OUTPUT : d @RETURNS : OK or ERROR @DESCRIPTION: Inputs an ascii representation of a real value. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_input_real( FILE *file, Real *d ) { Status status; STRING str; status = mni_input_string( file, &str, (char) ' ', (char) ';' ); if( status == OK && sscanf( str, "%lf", d ) != 1 ) { unget_string( file, str ); status = ERROR; } delete_string( str ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_input_reals @INPUT : file @OUTPUT : n reals @RETURNS : OK or ERROR @DESCRIPTION: Inputs an arbitrary number of real values, up to the next semicolon. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_input_reals( FILE *file, int *n, Real *reals[] ) { Real d; *n = 0; while( mni_input_real( file, &d ) != ERROR ) { ADD_ELEMENT_TO_ARRAY( *reals, *n, d, DEFAULT_CHUNK_SIZE ); } return( mni_skip_expected_character( file, (char) ';' ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : mni_input_int @INPUT : file @OUTPUT : i @RETURNS : OK or ERROR @DESCRIPTION: Inputs an integer from an ascii file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status mni_input_int( FILE *file, int *i ) { Status status; STRING str; status = mni_input_string( file, &str, (char) ' ', (char) ';' ); if( status == OK && sscanf( str, "%d", i ) != 1 ) { unget_string( file, str ); status = ERROR; } delete_string( str ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_comments @INPUT : file comments @OUTPUT : @RETURNS : @DESCRIPTION: Outputs a string to the file, in comment format, by placing a comment at the beginning of the string, and after each carriage return. An extra carriage return is placed after the comments, if the comments do not end in a carriage return. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void output_comments( FILE *file, STRING comments ) { int i, len; if( comments != NULL ) { len = string_length( comments ); (void) output_character( file, COMMENT_CHAR1 ); for( i = 0; i < len; ++i ) { (void) output_character( file, comments[i] ); if( comments[i] == '\n' && i < len - 1 ) (void) output_character( file, COMMENT_CHAR1 ); } if( len > 0 && comments[len-1] != '\n' ) (void) output_character( file, (char) '\n' ); } } minc-2.2.00/volume_io/MNI_formats/tag_points.c0000644000265600003100000006131012027132664016132 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include static const char *TAG_FILE_HEADER = "MNI Tag Point File"; static const char *VOLUMES_STRING = "Volumes"; static const char *TAG_POINTS_STRING = "Points"; /* ----------------------------- MNI Header ----------------------------------- @NAME : get_default_tag_file_suffix @INPUT : @OUTPUT : @RETURNS : "tag" @DESCRIPTION: Returns the default tag file suffix. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING get_default_tag_file_suffix( void ) { return( "tag" ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_tag_file_output @INPUT : file comments n_volumes @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Writes the header and first part of a tag file. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status initialize_tag_file_output( FILE *file, STRING comments, int n_volumes ) { Status status; /* parameter checking */ status = OK; if( file == NULL ) { print_error( "start_writing_tags(): passed NULL FILE ptr.\n"); status = ERROR; } if( n_volumes != 1 && n_volumes != 2 ) { print_error( "output_tag_points():" ); print_error( " can only support 1 or 2 volumes;\n" ); print_error( " you've supplied %d.\n", n_volumes ); status = ERROR; } if( status == OK ) { /* okay write the file header and tag points header */ (void) fprintf( file, "%s\n", TAG_FILE_HEADER ); (void) fprintf( file, "%s = %d;\n", VOLUMES_STRING, n_volumes ); output_comments( file, comments ); (void) fprintf( file, "\n" ); (void) fprintf( file, "%s =", TAG_POINTS_STRING ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_one_tag @INPUT : file n_volumes tag_volume1 tag_volume2 weight - NULL if not desired to specify structure_id - NULL if not desired to specify patient_id - NULL if not desired to specify label - NULL if not desired to specify @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Writes one tag to the output. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_one_tag( FILE *file, int n_volumes, Real tag_volume1[], Real tag_volume2[], Real *weight, int *structure_id, int *patient_id, STRING label ) { Status status; BOOLEAN aux_present; /* parameter checking */ status = OK; (void) fprintf( file, "\n %.15g %.15g %.15g", tag_volume1[0], tag_volume1[1], tag_volume1[2] ); if( n_volumes >= 2 ) { (void) fprintf( file, " %.15g %.15g %.15g", tag_volume2[0], tag_volume2[1], tag_volume2[2] ); } /*--- decide whether to output the 3 numerical information */ aux_present = (weight != NULL || structure_id != NULL || patient_id != NULL); if( aux_present ) { if( weight != (Real *) NULL ) (void) fprintf( file, " %.15g", *weight ); else (void) fprintf( file, " %.15g", 0.0 ); if( structure_id != NULL ) (void) fprintf( file, " %d", *structure_id ); else (void) fprintf( file, " %d", -1 ); if( patient_id != NULL ) (void) fprintf( file, " %d", *patient_id ); else (void) fprintf( file, " %d", -1 ); } if( label != NULL ) (void) fprintf( file, " \"%s\"", label ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : terminate_tag_file_output @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Finishes writing the tag file, by placing the closing semicolon. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void terminate_tag_file_output( FILE *file ) { (void) fprintf( file, ";\n" ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_tag_points @INPUT : file comments - may be null n_volumes n_tag_points tags_volume1 tags_volume2 weights structure_ids patient_ids labels @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Outputs the tag points in MNI tag point format. If weights, structure_ids, and patient_ids are all NULL, they are not written to the file. If labels is NULL, it is not written. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Oct. 19, 1995 D. MacDonald, now calls the 1 at a time routine @MODIFIED : Apr. 1, 1996 D. MacDonald, fixed bug of passing non-null tags_volume2 with n_volumes==1 ---------------------------------------------------------------------------- */ VIOAPI Status output_tag_points( FILE *file, STRING comments, int n_volumes, int n_tag_points, Real **tags_volume1, Real **tags_volume2, Real weights[], int structure_ids[], int patient_ids[], STRING *labels ) { Status status; int i; status = initialize_tag_file_output( file, comments, n_volumes ); if( status == OK ) { for( i = 0; i < n_tag_points; ++i ) { status = output_one_tag( file, n_volumes, tags_volume1[i], (n_volumes == 1) ? NULL : tags_volume2[i], weights == NULL ? NULL : &weights[i], structure_ids == NULL ? NULL : &structure_ids[i], patient_ids == NULL ? NULL : &patient_ids[i], labels == NULL ? NULL : labels[i] ); if( status != OK ) break; } } if( status == OK ) terminate_tag_file_output( file ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_tags @INPUT : tags n_tag_points @OUTPUT : @RETURNS : @DESCRIPTION: Frees the tag x,y,z positions. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void free_tags( Real **tags, int n_tag_points ) { int i; for( i = 0; i < n_tag_points; ++i ) FREE( tags[i] ); if( n_tag_points > 0 ) FREE( tags ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_tag_points @INPUT : n_volumes n_tag_points tags_volume1 tags_volume2 weights structure_ids patient_ids labels @OUTPUT : @RETURNS : @DESCRIPTION: Frees the tag point data. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void free_tag_points( int n_volumes, int n_tag_points, Real **tags_volume1, Real **tags_volume2, Real weights[], int structure_ids[], int patient_ids[], char **labels ) { int i; if( n_tag_points > 0 ) { free_tags( tags_volume1, n_tag_points ); if( n_volumes == 2 ) free_tags( tags_volume2, n_tag_points ); if( weights != (Real *) NULL ) FREE( weights ); if( structure_ids != (int *) NULL ) FREE( structure_ids ); if( patient_ids != (int *) NULL ) FREE( patient_ids ); if( labels != (char **) NULL ) { for( i = 0; i < n_tag_points; ++i ) delete_string( labels[i] ); if( n_tag_points > 0 ) FREE( labels ); } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : extract_label @INPUT : str @OUTPUT : label @RETURNS : @DESCRIPTION: Extracts the label from the string, by either taking the first space delimited word, or first quoted string. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static STRING extract_label( STRING str ) { BOOLEAN quoted; int i; STRING label; i = 0; /* --- skip leading space */ while( str[i] == ' ' || str[i] == '\t' ) ++i; if( str[i] == '"' ) { quoted = TRUE; ++i; } else quoted = FALSE; /* --- copy characters until either closing quote is found (if quoted), or white space or end of string is found */ label = create_string( NULL ); while( str[i] != END_OF_STRING && (quoted && str[i] != '"' || !quoted && str[i] != ' ' && str[i] != '\t') ) { concat_char_to_string( &label, str[i] ); ++i; } return( label ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_tag_file_input @INPUT : file @OUTPUT : n_volumes @RETURNS : OK or ERROR @DESCRIPTION: Reads the tag file header and first part of file. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status initialize_tag_file_input( FILE *file, int *n_volumes_ptr ) { STRING line; int n_volumes; /* parameter checking */ if( file == NULL ) { print_error( "initialize_tag_file_input(): passed NULL FILE ptr.\n"); return( ERROR ); } /* okay read the header */ if( mni_input_string( file, &line, (char) 0, (char) 0 ) != OK || !equal_strings( line, (STRING) TAG_FILE_HEADER ) ) { print_error( "input_tag_points(): invalid header in file.\n"); delete_string( line ); return( ERROR ); } delete_string( line ); /* now read the number of volumes */ if( mni_input_keyword_and_equal_sign( file, VOLUMES_STRING, TRUE ) != OK ) return( ERROR ); if( mni_input_int( file, &n_volumes ) != OK ) { print_error( "input_tag_points(): expected # volumes after %s.\n", VOLUMES_STRING ); return( ERROR ); } if( mni_skip_expected_character( file, (char) ';' ) != OK ) return( ERROR ); if( n_volumes != 1 && n_volumes != 2 ) { print_error( "input_tag_points(): invalid # volumes: %d \n", n_volumes ); return( ERROR ); } /* now read the tag points header */ if( mni_input_keyword_and_equal_sign( file, TAG_POINTS_STRING, TRUE ) != OK) return( ERROR ); if( n_volumes_ptr != NULL ) *n_volumes_ptr = n_volumes; return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_one_tag @INPUT : file n_volumes @OUTPUT : tags_volume1_ptr tags_volume2_ptr weight_ptr structure_id_ptr patient_id_ptr label_ptr @RETURNS : OK or ERROR @DESCRIPTION: Inputs the file and passes back the data. The last four arguments can each be set to NULL if the corresponding information is not desired. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status read_one_tag( FILE *file, int n_volumes, Real tags_volume1_ptr[], Real tags_volume2_ptr[], Real *weight_ptr, int *structure_id_ptr, int *patient_id_ptr, STRING *label_ptr ) { Status status; STRING line; BOOLEAN last_was_blank, in_quotes; int n_strings, pos, i; Real x1, y1, z1, x2, y2, z2; int structure_id, patient_id; Real weight; STRING label; /* parameter checking */ if( file == NULL ) { print_error( "read_one_tag(): passed NULL FILE ptr.\n"); return( ERROR ); } status = mni_input_real( file, &x1 ); if( status == OK ) { if( mni_input_real( file, &y1 ) != OK || mni_input_real( file, &z1 ) != OK || (n_volumes == 2 && (mni_input_real( file, &x2 ) != OK || mni_input_real( file, &y2 ) != OK || mni_input_real( file, &z2 ) != OK)) ) { print_error( "read_one_tag(): error reading tag point\n" ); return( ERROR ); } if( tags_volume1_ptr != NULL ) { tags_volume1_ptr[X] = x1; tags_volume1_ptr[Y] = y1; tags_volume1_ptr[Z] = z1; } if( n_volumes == 2 && tags_volume2_ptr != NULL ) { tags_volume2_ptr[X] = x2; tags_volume2_ptr[Y] = y2; tags_volume2_ptr[Z] = z2; } label = NULL; weight = 0.0; structure_id = -1; patient_id = -1; n_strings = 0; if( mni_input_line( file, &line ) == OK ) { i = 0; last_was_blank = TRUE; in_quotes = FALSE; while( line[i] != END_OF_STRING ) { if( line[i] == ' ' || line[i] == '\t' ) { last_was_blank = TRUE; } else { if( last_was_blank && !in_quotes ) ++n_strings; last_was_blank = FALSE; if( line[i] == '\"' ) in_quotes = !in_quotes; } ++i; } while( i > 0 && (line[i] == ' ' || line[i] == '\t' || line[i] == END_OF_STRING) ) --i; if( line[i] == ';' ) { (void) unget_character( file, (char) ';' ); line[i] = END_OF_STRING; } } if( n_strings != 0 ) { if( n_strings == 1 ) { label = extract_label( line ); } else if( n_strings < 3 || n_strings > 4 || sscanf( line, "%lf %d %d %n", &weight, &structure_id, &patient_id, &pos ) != 3 ) { print_error( "input_tag_points(): error reading tag point\n" ); return( ERROR ); } else if( n_strings == 4 ) { label = extract_label( &line[pos] ); } } delete_string( line ); if( weight_ptr != NULL ) *weight_ptr = weight; if( structure_id_ptr != NULL ) *structure_id_ptr = structure_id; if( patient_id_ptr != NULL ) *patient_id_ptr = patient_id; if( label_ptr != NULL ) *label_ptr = label; else delete_string( label ); } if( status == ERROR ) /* --- found no more tag points, should now find ; */ { if( mni_skip_expected_character( file, (char) ';' ) != OK ) status = ERROR; else status = END_OF_FILE; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_tag_file @INPUT : filename comments n_volumes n_tag_points tags_volume1 tags_volume2 weights structure_ids patient_ids labels @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Opens the file, outputs the tag points, and closes the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Oct. 19, 1995 D. MacDonald - now calls the 1 at a time funcs ---------------------------------------------------------------------------- */ VIOAPI Status output_tag_file( STRING filename, STRING comments, int n_volumes, int n_tag_points, Real **tags_volume1, Real **tags_volume2, Real weights[], int structure_ids[], int patient_ids[], STRING labels[] ) { Status status; FILE *file; status = open_file_with_default_suffix( filename, get_default_tag_file_suffix(), WRITE_FILE, ASCII_FORMAT, &file ); if( status == OK ) status = output_tag_points( file, comments, n_volumes, n_tag_points, tags_volume1, tags_volume2, weights, structure_ids, patient_ids, labels ); if( status == OK ) status = close_file( file ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_tag_file @INPUT : filename @OUTPUT : n_volumes n_tag_points tags_volume1 tags_volume2 weights structure_ids patient_ids labels @RETURNS : OK or ERROR @DESCRIPTION: Opens the file, inputs the tag points, and closes the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_tag_file( STRING filename, int *n_volumes, int *n_tag_points, Real ***tags_volume1, Real ***tags_volume2, Real **weights, int **structure_ids, int **patient_ids, STRING *labels[] ) { Status status; FILE *file; status = open_file_with_default_suffix( filename, get_default_tag_file_suffix(), READ_FILE, ASCII_FORMAT, &file ); if( status == OK ) status = input_tag_points( file, n_volumes, n_tag_points, tags_volume1, tags_volume2, weights, structure_ids, patient_ids, labels ); if( status == OK ) status = close_file( file ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_one_tag @INPUT : file n_volumes @OUTPUT : tag_volume1 tag_volume2 weight structure_id patient_id label status @RETURNS : TRUE if successful. @DESCRIPTION: Reads one tag point line from the file. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN input_one_tag( FILE *file, int n_volumes, Real tag_volume1[], Real tag_volume2[], Real *weight, int *structure_id, int *patient_id, STRING *label, Status *status ) { BOOLEAN read_one; Status read_status; read_status = read_one_tag( file, n_volumes, tag_volume1, tag_volume2, weight, structure_id, patient_id, label ); read_one = (read_status == OK); if( read_status == END_OF_FILE ) read_status = OK; if( status != NULL ) *status = read_status; return( read_one ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_tag_points @INPUT : file @OUTPUT : n_volumes n_tag_points tags_volume1 tags_volume2 weights structure_ids patient_ids labels @RETURNS : OR or ERROR @DESCRIPTION: Inputs an entire tag point file into a set of arrays. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_tag_points( FILE *file, int *n_volumes_ptr, int *n_tag_points, Real ***tags_volume1, Real ***tags_volume2, Real **weights, int **structure_ids, int **patient_ids, STRING *labels[] ) { Status status; Real tags1[N_DIMENSIONS]; Real tags2[N_DIMENSIONS]; Real weight; int structure_id, patient_id, n_volumes; STRING label; status = initialize_tag_file_input( file, &n_volumes ); if( n_volumes_ptr != NULL ) *n_volumes_ptr = n_volumes; *n_tag_points = 0; while( status == OK && input_one_tag( file, n_volumes, tags1, tags2, &weight, &structure_id, &patient_id, &label, &status ) ) { if( tags_volume1 != NULL ) { SET_ARRAY_SIZE( *tags_volume1, *n_tag_points, *n_tag_points+1, DEFAULT_CHUNK_SIZE ); ALLOC( (*tags_volume1)[*n_tag_points], 3 ); (*tags_volume1)[*n_tag_points][X] = tags1[X]; (*tags_volume1)[*n_tag_points][Y] = tags1[Y]; (*tags_volume1)[*n_tag_points][Z] = tags1[Z]; } if( n_volumes == 2 && tags_volume2 != NULL ) { SET_ARRAY_SIZE( *tags_volume2, *n_tag_points, *n_tag_points+1, DEFAULT_CHUNK_SIZE ); ALLOC( (*tags_volume2)[*n_tag_points], 3 ); (*tags_volume2)[*n_tag_points][X] = tags2[X]; (*tags_volume2)[*n_tag_points][Y] = tags2[Y]; (*tags_volume2)[*n_tag_points][Z] = tags2[Z]; } if( weights != NULL ) { SET_ARRAY_SIZE( *weights, *n_tag_points, *n_tag_points+1, DEFAULT_CHUNK_SIZE); (*weights)[*n_tag_points] = weight; } if( structure_ids != NULL ) { SET_ARRAY_SIZE( *structure_ids, *n_tag_points, *n_tag_points+1, DEFAULT_CHUNK_SIZE); (*structure_ids)[*n_tag_points] = structure_id; } if( patient_ids != NULL ) { SET_ARRAY_SIZE( *patient_ids, *n_tag_points, *n_tag_points+1, DEFAULT_CHUNK_SIZE); (*patient_ids)[*n_tag_points] = patient_id; } if( labels != NULL ) { SET_ARRAY_SIZE( *labels, *n_tag_points, *n_tag_points+1, DEFAULT_CHUNK_SIZE); (*labels)[*n_tag_points] = label; } else delete_string( label ); ++(*n_tag_points); } return( status ); } minc-2.2.00/volume_io/MNI_formats/thin_plate_spline.c0000644000265600003100000003467612027132664017503 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #define INVERSE_FUNCTION_TOLERANCE 0.01 #define INVERSE_DELTA_TOLERANCE 0.01 #define MAX_INVERSE_ITERATIONS 20 /* ----------------------------- MNI Header ----------------------------------- @NAME : thin_plate_spline.c @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: library of routines for warping/mapping transformations. @METHOD : The original source code for these routines are taken from program VOI, written by Weiqian Dai. @GLOBALS : @CALLS : @CREATED : Dec 2, 1991 LC @MODIFIED : Mon Apr 5 09:00:54 EST 1993 louis - building new library routines, with prototypes @MODIFIED : Wed Jul 14 1993 david - incorporated into libmni.c Feb. 28, 1995 D. MacDonald - rewrote to get rid of mnewt and floats ---------------------------------------------------------------------------- */ /* ----- structure used by newton root finding ---- */ typedef struct { Real **points; Real **weights; int n_points; int n_dims; } spline_data_struct; /*------------ private functions -----------------*/ static void newton_function( void *function_data, Real parameters[], Real values[], Real **first_derivs ); static Real thin_plate_spline_U_deriv( Real pos[], Real landmark[], int n_dims, int deriv_dim ); /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_thin_plate_spline @INPUT : n_dims - dimensionality of the function n_values - number of values of the function n_points - number of defining landmarks points[n_points][n_dims] - landmarks weights[n_points+1+n_dims][n_values] - weights for the points pos[n_dims] - position at which to evaluate @OUTPUT : values[n_values] - function values at this position deriv[n_values][n_dims] - function derivatives at this point @RETURNS : @DESCRIPTION: Evaluates the thin plate spline at the given point, and, if the argument is non-null, the derivatives also. The thin-plate spline takes a point in n_dims dimensional space and returns a point in n_values dimensional space. When used for transforms, as in this file, n_values == n_dims, but the code will work for the general case where n_values != n_dims. @METHOD : @GLOBALS : @CALLS : @CREATED : @MODIFIED : Feb. 27, 1995 David MacDonald modified from some code written by WeiQian Dai later modified by Louis Collins ---------------------------------------------------------------------------- */ VIOAPI void evaluate_thin_plate_spline( int n_dims, int n_values, int n_points, Real **points, Real **weights, Real pos[], Real values[], Real **derivs ) { int v, d, p; Real dist, dist_deriv; /* f(x,y[,z]) =a_{n} + a_{n+1}x + a_{n+1}y + sum_{0}^{n-1} * w_{i}U(|P_{i} - (x,y)|) */ /* --- initialize derivatives, if desired */ if( derivs != NULL ) { for_less( v, 0, n_values ) for_less( d, 0, n_dims ) derivs[v][d] = 0.0; } /* --- initialize value of thin plate spline to 0 */ for_less( v, 0, n_values ) values[v] = 0.0; /* --- for each point, add its contribution to the values and derivs */ for_less( p, 0, n_points ) { /* --- the thin plate spline weighting function for this point */ dist = thin_plate_spline_U( pos, points[p], n_dims ); /* --- add the weighted component to the values */ for_less( v, 0, n_values ) values[v] = values[v] + (Real) weights[p][v] * dist; /* --- add the weighted component to the derivatives */ if( derivs != NULL ) { for_less( v, 0, n_values ) { for_less( d, 0, n_dims ) { dist_deriv = thin_plate_spline_U_deriv( pos, points[p], n_dims, d ); derivs[v][d] += (Real) weights[p][v] * dist_deriv; } } } } /* --- add the constant component to the values */ for_less( v, 0, n_values ) values[v] += (Real) weights[n_points][v]; /* --- add the linear components to the values and derivatives */ for_less( v, 0, n_values ) { for_less( d, 0, n_dims ) { values[v] += (Real) weights[n_points+1+d][v] * pos[d]; if( derivs != NULL ) derivs[v][d] += (Real) weights[n_points+1+d][v]; } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : thin_plate_spline_transform @INPUT : n_dims - number of dimensions (either 2 or 3). n_points - number of points points - array with 'n_points' rows, and 'n_dims' cols, the list of landmarks points in the 'source' volume weights - array with 'n_points+n_dims+1' rows, and 'n_dims' cols, the deformation weights that define the thin plate spline n_points - number of landmark points x - coordinate to transform y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : nothing @DESCRIPTION: Transforms the 1,2, or 3D point given the thin plate spline transform @METHOD : @GLOBALS : none @CALLS : @CREATED : Mon Apr 5 09:00:54 EST 1993 @MODIFIED : Feb. 27, 1995 D. MacDonald - reorganized to call evaluate_thin_plane_spline() ---------------------------------------------------------------------------- */ VIOAPI void thin_plate_spline_transform( int n_dims, int n_points, Real **points, Real **weights, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { Real input_point[N_DIMENSIONS], output_point[N_DIMENSIONS]; input_point[0] = x; input_point[1] = y; input_point[2] = z; evaluate_thin_plate_spline( n_dims, n_dims, n_points, points, weights, input_point, output_point, NULL ); *x_transformed = output_point[0]; if( n_dims >= 2 ) *y_transformed = output_point[1]; if( n_dims >= 3 ) *z_transformed = output_point[2]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : thin_plate_spline_inverse_transform @INPUT : n_dims - number of dimensions (either 2 or 3). n_points - number of points points - array with 'n_points' rows, and 'n_dims' cols, the list of landmarks points in the 'source' volume weights - array with 'n_points+n_dims+1' rows, and 'n_dims' cols, the deformation weights that define the thin plate spline n_points - number of landmark points x - coordinate to inverse transform y z @OUTPUT : x_transformed y_transformed z_transformed @RETURNS : nothing @DESCRIPTION: Inverse transforms the 1,2, or 3D point given the thin plate spline transform. @METHOD : @GLOBALS : none @CALLS : @CREATED : Mon Apr 5 09:00:54 EST 1993 @MODIFIED : Feb. 27, 1995 D. MacDonald - reorganized to call evaluate_thin_plane_spline() ---------------------------------------------------------------------------- */ VIOAPI void thin_plate_spline_inverse_transform( int n_dims, int n_points, Real **points, Real **weights, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) { Real x_in[N_DIMENSIONS], solution[N_DIMENSIONS]; spline_data_struct data; x_in[X] = x; if( n_dims >= 2 ) x_in[Y] = y; else x_in[Y] = 0.0; if( n_dims >= 3 ) x_in[Z] = z; else x_in[Z] = 0.0; data.points = points; data.weights = weights; data.n_points = n_points; data.n_dims = n_dims; /* --- solve for the root of the function using Newton steps, which require a function (newton_function) that evaluates the thin plate spline and its derivative at an arbitrary point */ if( newton_root_find( n_dims, newton_function, (void *) &data, x_in, x_in, solution, INVERSE_FUNCTION_TOLERANCE, INVERSE_DELTA_TOLERANCE, MAX_INVERSE_ITERATIONS ) ) { *x_transformed = solution[0]; *y_transformed = solution[1]; *z_transformed = solution[2]; } else { *x_transformed = x_in[0]; *y_transformed = x_in[1]; *z_transformed = x_in[2]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : newton_function @INPUT : function_data parameters @OUTPUT : values first_derivs @RETURNS : @DESCRIPTION: This function is passed to the newton function root finding routine, and evaluates the values and derivatives of the thin plate spline. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 27, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void newton_function( void *function_data, Real parameters[], Real values[], Real **first_derivs ) { spline_data_struct *spline_data; spline_data = (spline_data_struct *) function_data; evaluate_thin_plate_spline( spline_data->n_dims, spline_data->n_dims, spline_data->n_points, spline_data->points, spline_data->weights, parameters, values, first_derivs ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : thin_plate_spline_U @INPUT : pos - position at which to evaluate landmark - landmark n_dims number of dimensions (1,2, or 3) @OUTPUT : @RETURNS : U interpolation function of distance between the two args @DESCRIPTION: Returns the U interpolation function of the distance between points. In order to correspond to a thin-plate spline, this function has a different form in each of the 3 dimensions. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. , 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real thin_plate_spline_U( Real pos[], Real landmark[], int n_dims ) { Real r, fu, dx, dy, dz; switch( n_dims ) { case 1: dx = pos[X] - landmark[X]; r = FABS( dx ); fu = r * r * r; break; case 2: /* r is actually r^2 */ dx = pos[X] - landmark[X]; dy = pos[Y] - landmark[Y]; r = dx * dx + dy * dy; if( r == 0.0 ) fu = 0.0; else fu = r * log( r ); break; case 3: dx = pos[X] - landmark[X]; dy = pos[Y] - landmark[Y]; dz = pos[Z] - landmark[Z]; r = sqrt( dx * dx + dy * dy + dz * dz ); fu = r; break; default: handle_internal_error( " impossible error in FU" ); fu = 0.0; break; } return( fu ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : thin_plate_spline_U_deriv @INPUT : pos - position at which to evaluate landmark - landmark n_dims - number of dimensions (1,2, or 3) deriv_dim - dimension to differentiate @OUTPUT : @RETURNS : derivative of U interpolation function @DESCRIPTION: Returns the derivative of the U interpolation function of the distance between points (as specified by thin_plate_spline_U() above). @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. , 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Real thin_plate_spline_U_deriv( Real pos[], Real landmark[], int n_dims, int deriv_dim ) { Real r, r2, deriv, delta[N_DIMENSIONS]; switch( n_dims ) { case 1: delta[X] = pos[X] - landmark[X]; r = delta[X]; deriv = 3.0 * r * r; break; case 2: /* r2 is r^2 */ delta[X] = pos[X] - landmark[X]; delta[Y] = pos[Y] - landmark[Y]; r2 = delta[X] * delta[X] + delta[Y] * delta[Y]; if( r2 == 0.0 ) deriv = 0.0; else deriv = (1.0 + log( r2 )) * 2.0 * delta[deriv_dim]; break; case 3: delta[X] = pos[X] - landmark[X]; delta[Y] = pos[Y] - landmark[Y]; delta[Z] = pos[Z] - landmark[Z]; r = sqrt( delta[X] * delta[X] + delta[Y] * delta[Y] + delta[Z] * delta[Z] ); if( r == 0.0 ) deriv = 0.0; else deriv = delta[deriv_dim] / r; break; default: handle_internal_error( " invalid dimensions error in FU" ); deriv = 0.0; break; } return( deriv ); } minc-2.2.00/volume_io/Prog_utils/0000755000265600003100000000000012030114722013634 500000000000000minc-2.2.00/volume_io/Prog_utils/alloc.c0000644000265600003100000005410612027132664015033 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include /* ----------------------------- MNI Header ----------------------------------- @NAME : set_up_array_pointers_2D @INPUT : ptr n1 n2 type_size @OUTPUT : @RETURNS : @DESCRIPTION: Given a pointer allocated for 2D, creates the 1st level pointers. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void set_up_array_pointers_2D( void **ptr, size_t n1, size_t n2, size_t type_size ) { size_t i; for_less( i, 1, n1 ) ptr[i] = (void *) ((long) ptr[i-1] + (long) n2* (long) type_size); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_alloc_memory @INPUT : n_bytes @OUTPUT : ptr @RETURNS : @DESCRIPTION: Allocates the specified number of bytes. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status private_alloc_memory( void **ptr, size_t n_bytes ) { if( n_bytes != 0 ) { *ptr = (void *) malloc( n_bytes ); if( *ptr == NULL ) return( ERROR ); } else *ptr = NULL; return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_alloc_memory_2d @INPUT : n1 n2 type_size @OUTPUT : ptr @RETURNS : @DESCRIPTION: Allocates the specified number of 2d elements. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status private_alloc_memory_2d( void ***ptr, size_t n1, size_t n2, size_t type_size ) { if( private_alloc_memory( (void **) ptr, n1 * sizeof(**ptr) ) != OK || private_alloc_memory( *ptr, n1 * n2 * type_size ) != OK ) { return( ERROR ); } set_up_array_pointers_2D( *ptr, n1, n2, type_size ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_alloc_memory_3d @INPUT : n1 n2 n3 type_size @OUTPUT : ptr @RETURNS : @DESCRIPTION: Allocates the specified number of 3d elements. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status private_alloc_memory_3d( void ****ptr, size_t n1, size_t n2, size_t n3, size_t type_size ) { if( private_alloc_memory_2d( (void ***) ptr, n1, n2, sizeof(***ptr) )!= OK|| private_alloc_memory( **ptr, n1 * n2 * n3 * type_size ) != OK) { return( ERROR ); } set_up_array_pointers_2D( **ptr, n1 * n2, n3, type_size ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_alloc_memory_4d @INPUT : n1 n2 n3 n4 type_size @OUTPUT : ptr @RETURNS : @DESCRIPTION: Allocates the specified number of 4d elements. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status private_alloc_memory_4d( void *****ptr, size_t n1, size_t n2, size_t n3, size_t n4, size_t type_size ) { if( private_alloc_memory_3d( (void ****) ptr, n1, n2, n3, sizeof(****ptr) )!= OK || private_alloc_memory( ***ptr, n1 * n2 * n3 * n4 * type_size ) != OK ) { return( ERROR ); } set_up_array_pointers_2D( ***ptr, n1 * n2 * n3, n4, type_size ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_alloc_memory_5d @INPUT : n1 n2 n3 n4 n5 type_size @OUTPUT : ptr @RETURNS : @DESCRIPTION: Allocates the specified number of 5d elements. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status private_alloc_memory_5d( void ******ptr, size_t n1, size_t n2, size_t n3, size_t n4, size_t n5, size_t type_size ) { if( private_alloc_memory_4d( (void *****) ptr, n1, n2, n3, n4, sizeof(*****ptr) )!= OK || private_alloc_memory( ****ptr, n1 * n2 * n3 * n4 * n5 * type_size )!=OK) { return( ERROR ); } set_up_array_pointers_2D( ****ptr, n1 * n2 * n3 * n4, n5, type_size ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_memory_in_bytes @INPUT : n_bytes filename line_number @OUTPUT : @RETURNS : void * @DESCRIPTION: Allocates the specified amount of memory, and if successful, calls the routine to record the memory allocated, and returns the pointer. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void *alloc_memory_in_bytes( size_t n_bytes _ALLOC_SOURCE_LINE_ARG_DEF ) { void *ptr; if( private_alloc_memory( &ptr, n_bytes ) != OK ) { print_error( "Cannot alloc 1D array of %d bytes.\n", n_bytes ); PRINT_ALLOC_SOURCE_LINE abort_if_allowed(); } #ifndef NO_DEBUG_ALLOC else record_ptr_alloc_check( ptr, n_bytes, filename, line_number ); #endif return( ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_memory_1d @INPUT : n_elements type_size filename line_number @OUTPUT : @RETURNS : void * @DESCRIPTION: Allocates a 1D array and returns it. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : Apr. 16, 1996 D. MacDonald : returns the pointer ---------------------------------------------------------------------------- */ VIOAPI void *alloc_memory_1d( size_t n_elements, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ) { void *ptr; if( private_alloc_memory( &ptr, n_elements * type_size ) != OK ) { print_error( "Cannot alloc 1D array of %d elements of %d bytes.\n", n_elements, type_size ); PRINT_ALLOC_SOURCE_LINE abort_if_allowed(); } #ifndef NO_DEBUG_ALLOC else record_ptr_alloc_check( ptr, n_elements * type_size, filename, line_number ); #endif return( ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_memory_2d @INPUT : n1 n2 type_size filename line_number @OUTPUT : @RETURNS : void * @DESCRIPTION: Allocates a 2D array and returns a pointer to it. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void *alloc_memory_2d( size_t n1, size_t n2, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ) { void **ptr; if( private_alloc_memory_2d( &ptr, n1, n2, type_size ) != OK ) { print_error( "Cannot alloc 2D array of %d by %d elements of %d bytes.\n", n1, n2, type_size ); PRINT_ALLOC_SOURCE_LINE abort_if_allowed(); } #ifndef NO_DEBUG_ALLOC else { record_ptr_alloc_check( ptr, n1 * sizeof(*ptr), filename, line_number ); record_ptr_alloc_check( *ptr, n1 * n2 * type_size, filename, line_number ); } #endif return( (void *) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_memory_3d @INPUT : n1 n2 n3 type_size filename line_number @OUTPUT : @RETURNS : void * @DESCRIPTION: Allocates a 3D array. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void *alloc_memory_3d( size_t n1, size_t n2, size_t n3, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ) { void ***ptr; if( private_alloc_memory_3d( &ptr, n1, n2, n3, type_size ) != OK ) { print_error( "Cannot alloc 3D array of %d by %d by %d elements of %d bytes.\n", n1, n2, n3, type_size ); PRINT_ALLOC_SOURCE_LINE abort_if_allowed(); } #ifndef NO_DEBUG_ALLOC else { record_ptr_alloc_check( ptr, n1 * sizeof(*ptr), filename, line_number ); record_ptr_alloc_check( *ptr, n1 * n2 * sizeof(**ptr), filename, line_number ); record_ptr_alloc_check( **ptr, n1 * n2 * n3 * type_size, filename, line_number ); } #endif return( (void *) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_memory_4d @INPUT : n1 n2 n3 n4 type_size filename line_number @OUTPUT : @RETURNS : void * @DESCRIPTION: Allocates a 4D array. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void *alloc_memory_4d( size_t n1, size_t n2, size_t n3, size_t n4, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ) { void ****ptr; if( private_alloc_memory_4d( &ptr, n1, n2, n3, n4, type_size ) != OK ) { print_error( "Cannot alloc 4D array of %d by %d by %d by %d elements of %d bytes.\n", n1, n2, n3, n4, type_size ); PRINT_ALLOC_SOURCE_LINE abort_if_allowed(); } #ifndef NO_DEBUG_ALLOC else { record_ptr_alloc_check( ptr, n1 * sizeof(*ptr), filename, line_number ); record_ptr_alloc_check( *ptr, n1 * n2 * sizeof(**ptr), filename, line_number ); record_ptr_alloc_check( **ptr, n1 * n2 * n3 * sizeof(***ptr), filename, line_number ); record_ptr_alloc_check( ***ptr, n1 * n2 * n3 * n4 * type_size, filename, line_number ); } #endif return( (void *) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_memory_5d @INPUT : n1 n2 n3 n4 n5 type_size filename line_number @OUTPUT : @RETURNS : void * @DESCRIPTION: Allocates a 5D array. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void *alloc_memory_5d( size_t n1, size_t n2, size_t n3, size_t n4, size_t n5, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ) { void *****ptr; if( private_alloc_memory_5d( &ptr, n1, n2, n3, n4, n5, type_size ) != OK ) { print_error( "Cannot alloc 4D array of %d by %d by %d by %d by %d elements of %d bytes.\n", n1, n2, n3, n4, n5, type_size ); PRINT_ALLOC_SOURCE_LINE abort_if_allowed(); } #ifndef NO_DEBUG_ALLOC else { record_ptr_alloc_check( ptr, n1 * sizeof(*ptr), filename, line_number ); record_ptr_alloc_check( *ptr, n1 * n2 * sizeof(**ptr), filename, line_number ); record_ptr_alloc_check( **ptr, n1 * n2 * n3 * sizeof(***ptr), filename, line_number ); record_ptr_alloc_check( ***ptr, n1 * n2 * n3 * n4 * sizeof(****ptr), filename, line_number ); record_ptr_alloc_check( ****ptr, n1 * n2 * n3 * n4 * n5 * type_size, filename, line_number ); } #endif return( (void *) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : realloc_memory @INPUT : ptr n_elements type_size filename line_number @OUTPUT : @RETURNS : @DESCRIPTION: Reallocates the ptr. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void realloc_memory( void **ptr, size_t n_elements, size_t type_size _ALLOC_SOURCE_LINE_ARG_DEF ) { #ifndef NO_DEBUG_ALLOC void *old_ptr = *ptr; #endif if( n_elements != 0 ) { *ptr = (void *) realloc( *ptr, n_elements * type_size ); if( *ptr == NULL ) { print_error( "Error reallocing %d elements of size %d.\n", n_elements, type_size ); PRINT_ALLOC_SOURCE_LINE abort_if_allowed(); } #ifndef NO_DEBUG_ALLOC change_ptr_alloc_check( old_ptr, *ptr, n_elements * type_size, filename, line_number ); #endif } else { print_error("Error: tried to realloc invalid number of elements, %d.\n", n_elements ); PRINT_ALLOC_SOURCE_LINE } } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_free_memory_1d @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees the array and assigns the pointer to NULL. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void private_free_memory_1d( void **ptr) { if( *ptr != NULL ) { free( *ptr ); *ptr = NULL; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_free_memory_2d @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees the array and assigns the pointer to NULL. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void private_free_memory_2d( void ***ptr) { private_free_memory_1d( *ptr ); private_free_memory_1d( (void **) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_free_memory_3d @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees the array and assigns the pointer to NULL. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void private_free_memory_3d( void ****ptr) { private_free_memory_1d( **ptr ); private_free_memory_2d( (void ***) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_free_memory_4d @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees the array and assigns the pointer to NULL. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void private_free_memory_4d( void *****ptr) { private_free_memory_1d( ***ptr ); private_free_memory_3d( (void ****) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : private_free_memory_5d @INPUT : ptr @OUTPUT : @RETURNS : @DESCRIPTION: Frees the array and assigns the pointer to NULL. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void private_free_memory_5d( void ******ptr) { private_free_memory_1d( ****ptr ); private_free_memory_4d( (void *****) ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_memory_1d @INPUT : ptr filename line_number @OUTPUT : @RETURNS : @DESCRIPTION: Frees the pointer, and sets it to NIL. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void free_memory_1d( void **ptr _ALLOC_SOURCE_LINE_ARG_DEF ) { #ifndef NO_DEBUG_ALLOC if( unrecord_ptr_alloc_check( *ptr, filename, line_number ) ) #endif private_free_memory_1d( ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_memory_2d @INPUT : ptr filename line_number @OUTPUT : @RETURNS : @DESCRIPTION: Frees the pointer, and sets it to NIL. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void free_memory_2d( void ***ptr _ALLOC_SOURCE_LINE_ARG_DEF ) { #ifndef NO_DEBUG_ALLOC if( unrecord_ptr_alloc_check( **ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) *ptr, filename, line_number ) ) #endif private_free_memory_2d( ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_memory_3d @INPUT : ptr filename line_number @OUTPUT : @RETURNS : @DESCRIPTION: Frees the pointer, and sets it to NIL. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void free_memory_3d( void ****ptr _ALLOC_SOURCE_LINE_ARG_DEF ) { #ifndef NO_DEBUG_ALLOC if( unrecord_ptr_alloc_check( ***ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) **ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) *ptr, filename, line_number ) ) #endif private_free_memory_3d( ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_memory_4d @INPUT : ptr filename line_number @OUTPUT : @RETURNS : @DESCRIPTION: Frees the pointer, and sets it to NIL. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void free_memory_4d( void *****ptr _ALLOC_SOURCE_LINE_ARG_DEF ) { #ifndef NO_DEBUG_ALLOC if( unrecord_ptr_alloc_check( ****ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) ***ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) **ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) *ptr, filename, line_number ) ) #endif private_free_memory_4d( ptr ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_memory_5d @INPUT : ptr filename line_number @OUTPUT : @RETURNS : @DESCRIPTION: Frees the pointer, and sets it to NIL. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void free_memory_5d( void ******ptr _ALLOC_SOURCE_LINE_ARG_DEF ) { #ifndef NO_DEBUG_ALLOC if( unrecord_ptr_alloc_check( *****ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) ****ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) ***ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) **ptr, filename, line_number ) && unrecord_ptr_alloc_check( (void *) *ptr, filename, line_number ) ) #endif private_free_memory_5d( ptr ); } minc-2.2.00/volume_io/Prog_utils/alloc_check.c0000644000265600003100000006650312027132664016174 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_check.c @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Maintains a skiplist structure to list all memory allocated, : and check for errors such as freeing a pointer twice or : overlapping allocations. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define MAX_SKIP_LEVELS 50 #define SKIP_P 0.5 #define MEMORY_DIFFERENCE 1000000 typedef struct skip_entry { void *ptr; size_t n_bytes; STRING source_file; int line_number; int sequence_number; struct skip_entry *forward[1]; } skip_entry; typedef struct { size_t next_memory_threshold; size_t total_memory_allocated; skip_entry *header; int level; } alloc_struct; typedef struct { skip_entry *update[MAX_SKIP_LEVELS]; } update_struct; static void update_total_memory( alloc_struct *, size_t ); static int get_random_level( void ); static void output_entry( FILE *, skip_entry * ); static BOOLEAN size_display_enabled( void ); static size_t skip_alloc_size = 0; typedef void *alloc_ptr; #define ALLOC_SKIP_STRUCT( ptr, n_level ) \ (ptr) = (skip_entry *) malloc( \ (sizeof(skip_entry)+((size_t)(n_level)-1) * sizeof(skip_entry *)) ); /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_alloc_list @INPUT : alloc_list @OUTPUT : @RETURNS : @DESCRIPTION: Initializes the allocation list to empty. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void initialize_alloc_list( alloc_struct *alloc_list ) { int i; alloc_list->next_memory_threshold = MEMORY_DIFFERENCE; alloc_list->total_memory_allocated = 0; ALLOC_SKIP_STRUCT( alloc_list->header, MAX_SKIP_LEVELS ); skip_alloc_size += sizeof(skip_entry)+(MAX_SKIP_LEVELS-1) * sizeof(skip_entry *); alloc_list->level = 1; for_less( i, 0, MAX_SKIP_LEVELS ) alloc_list->header->forward[i] = (skip_entry *) 0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_initialized_alloc_list @INPUT : alloc_list @OUTPUT : @RETURNS : @DESCRIPTION: Checks to make sure the allocation list is initialized. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void check_initialized_alloc_list( alloc_struct *alloc_list ) { static BOOLEAN first = TRUE; if( first ) { first = FALSE; initialize_alloc_list( alloc_list ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : find_pointer_position @INPUT : alloc_list : ptr @OUTPUT : update @RETURNS : TRUE if found @DESCRIPTION: Searches the alloc_list for the given ptr, and sets the update : struct so that it can provide an insert. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN find_pointer_position( alloc_struct *alloc_list, void *ptr, update_struct *update ) { int i; skip_entry *x; BOOLEAN found; x = alloc_list->header; for( i = alloc_list->level-1; i >= 0; --i ) { while( x->forward[i] != NULL && (void *) x->forward[i]->ptr < ptr ) { x = x->forward[i]; } update->update[i] = x; } x = update->update[0]->forward[0]; found = (x != NULL) && (x->ptr == ptr); return( found ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : insert_ptr_in_alloc_list @INPUT : alloc_list : update - the set of pointers indicating where to insert : ptr } : n_bytes }} : source_file }}} these are recorded in the list : line_number }} : sequence_number } @OUTPUT : @RETURNS : @DESCRIPTION: Records the allocated pointer in the allocation list. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void insert_ptr_in_alloc_list( alloc_struct *alloc_list, update_struct *update, void *ptr, size_t n_bytes, STRING source_file, int line_number, int sequence_number ) { int i, new_level; skip_entry *x; new_level = get_random_level(); if( new_level > alloc_list->level ) { for( i = alloc_list->level; i < new_level; ++i ) update->update[i] = alloc_list->header; alloc_list->level = new_level; } ALLOC_SKIP_STRUCT( x, new_level ); skip_alloc_size += sizeof(skip_entry)+((size_t)new_level-1) * sizeof(skip_entry *); x->ptr = ptr; x->n_bytes = n_bytes; x->source_file = source_file; x->line_number = line_number; x->sequence_number = sequence_number; update_total_memory( alloc_list, n_bytes ); for( i = 0; i < new_level; ++i ) { x->forward[i] = update->update[i]->forward[i]; update->update[i]->forward[i] = x; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_overlap @INPUT : update : ptr : n_bytes @OUTPUT : entry @RETURNS : TRUE if an overlap @DESCRIPTION: Checks the new ptr to see if it overlaps with the previous and : following memory allocations in the list, and returns the result. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN check_overlap( alloc_struct *alloc_list, update_struct *update, void *ptr, size_t n_bytes, skip_entry **entry ) { BOOLEAN overlap; overlap = FALSE; *entry = update->update[0]; if( *entry != alloc_list->header && *entry != (skip_entry *) 0 ) { if( (void *) ((char *) (*entry)->ptr + (*entry)->n_bytes) > ptr ) overlap = TRUE; else { (*entry) = (*entry)->forward[0]; if( *entry != (skip_entry *) 0 && (void *) ((char*)ptr + n_bytes) > (*entry)->ptr ) overlap = TRUE; } } return( overlap ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : remove_ptr_from_alloc_list @INPUT : alloc_list : ptr @OUTPUT : source_file : line_number : sequence_number @RETURNS : TRUE if it existed @DESCRIPTION: Finds and deletes the entry in the skip list associated with : ptr, and returns the information associated with the entry : (source_file, line_number, sequence_number). @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN remove_ptr_from_alloc_list( alloc_struct *alloc_list, void *ptr, STRING *source_file, int *line_number, int *sequence_number ) { int i; BOOLEAN found; skip_entry *x; update_struct update; found = find_pointer_position( alloc_list, ptr, &update ); if( found ) { x = update.update[0]->forward[0]; *source_file = x->source_file; *line_number = x->line_number; *sequence_number = x->sequence_number; update_total_memory( alloc_list, -x->n_bytes ); for( i = 0; i < alloc_list->level; ++i ) { if( update.update[i]->forward[i] != x ) break; update.update[i]->forward[i] = x->forward[i]; } skip_alloc_size -= sizeof(skip_entry) + (size_t) (i-1) * sizeof(skip_entry *); free( (alloc_ptr) x ); while( alloc_list->level > 1 && alloc_list->header->forward[alloc_list->level-1] == (skip_entry *) 0 ) { --alloc_list->level; } } return( found ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_random_0_to_1 @INPUT : @OUTPUT : @RETURNS : random number @DESCRIPTION: Returns a random number >= 0 and < 1. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Real get_random_0_to_1( void ) { return( (Real) rand() ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_random_level @INPUT : @OUTPUT : @RETURNS : a random level between 1 and MAX_LEVELS @DESCRIPTION: Determines a random level with exponential probability of higher : levels. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static int get_random_level( void ) { int level; level = 1; while( get_random_0_to_1() < SKIP_P && level < MAX_SKIP_LEVELS ) ++level; return( level ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : memory_still_alloced @INPUT : alloc_list @OUTPUT : @RETURNS : TRUE or FALSE @DESCRIPTION: Decides if any memory is still alloced, thus checking for memory leaks. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN memory_still_alloced( alloc_struct *alloc_list ) { return( alloc_list->header->forward[0] != (skip_entry *) NULL ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_alloc_list @INPUT : file : alloc_list @OUTPUT : @RETURNS : @DESCRIPTION: Outputs the list of allocated memory to the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void output_alloc_list( FILE *file, alloc_struct *alloc_list ) { skip_entry *ptr; ptr = alloc_list->header->forward[0]; while( ptr != (skip_entry *) 0 ) { output_entry( file, ptr ); ptr = ptr->forward[0]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_total_memory @INPUT : alloc_list : n_bytes @OUTPUT : @RETURNS : @DESCRIPTION: Adds n_bytes to the size of memory recorded. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void update_total_memory( alloc_struct *alloc_list, size_t n_bytes ) { alloc_list->total_memory_allocated += n_bytes; if( size_display_enabled() && alloc_list->total_memory_allocated > alloc_list->next_memory_threshold ) { alloc_list->next_memory_threshold = MEMORY_DIFFERENCE * (alloc_list->total_memory_allocated / MEMORY_DIFFERENCE + 1); print( "Memory allocated =%5.1f Megabytes (Overhead = %5.1f Mb)\n", (Real) alloc_list->total_memory_allocated / 1000000.0, (Real) skip_alloc_size / 1000000.0 ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : print_source_location @INPUT : source_file : line_number : sequence_number @OUTPUT : @RETURNS : @DESCRIPTION: Prints the information about a particular allocation. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void print_source_location( STRING source_file, int line_number, int sequence_number ) { print_error( "%s:%d\t%d'th alloc", source_file, line_number, sequence_number ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_entry @INPUT : file : entry @OUTPUT : @RETURNS : @DESCRIPTION: Outputs the information about an allocation entry to the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void output_entry( FILE *file, skip_entry *entry ) { (void) fprintf( file, "%s:%d\t%d'th alloc\n", entry->source_file, entry->line_number, entry->sequence_number ); } /* -------------------------------------------------------------------------- Routines that are to be called from outside this file -------------------------------------------------------------------------- */ static alloc_struct alloc_list; /* ----------------------------- MNI Header ----------------------------------- @NAME : get_total_memory_alloced @INPUT : @OUTPUT : @RETURNS : size_t - the number of bytes allocated @DESCRIPTION: Returns the total amount of memory allocated by the program, : not counting that used by the skip list. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI size_t get_total_memory_alloced( void ) { return( alloc_list.total_memory_allocated ); } static BOOLEAN checking_enabled; static BOOLEAN enabled_initialized = FALSE; /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_checking_enabled @INPUT : @OUTPUT : @RETURNS : TRUE if alloc checking is turned on @DESCRIPTION: Checks an environment variable to see if alloc checking is : not disabled. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN alloc_checking_enabled( void ) { #ifdef NO_DEBUG_ALLOC return( FALSE ); #else if( !enabled_initialized ) { set_alloc_checking( ENV_EXISTS( "DEBUG_ALLOC" ) ); } return( checking_enabled ); #endif } VIOAPI void set_alloc_checking( BOOLEAN state ) { enabled_initialized = TRUE; checking_enabled = state; } /* ----------------------------- MNI Header ----------------------------------- @NAME : size_display_enabled @INPUT : @OUTPUT : @RETURNS : TRUE if size displaying is turned on @DESCRIPTION: Checks an environment variable to see if memory size display : is disabled. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN size_display_enabled( void ) { #ifdef NO_DEBUG_ALLOC return( FALSE ); #else static BOOLEAN first = TRUE; static BOOLEAN enabled; if( first ) { enabled = ENV_EXISTS( "ALLOC_SIZE" ); first = FALSE; } return( enabled ); #endif } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_stop_sequence_number @INPUT : @OUTPUT : @RETURNS : which allocation number @DESCRIPTION: Returns the number at which allocation should stop. This is used for debugging. For instance, if an error message indicates a problem with the 100'th alloc of the program, then do a SETENV STOP_ALLOC_AT 100 and run the program from the debugger. It will stop at the requested allocation. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static int get_stop_sequence_number( void ) { static int first = TRUE; static int stop_sequence_number = -1; STRING str; if( first ) { first = FALSE; str = getenv( "STOP_ALLOC_AT" ); if( str == NULL || sscanf( str, "%d", &stop_sequence_number ) != 1 ) stop_sequence_number = -1; } return( stop_sequence_number ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_current_sequence_number @INPUT : @OUTPUT : @RETURNS : the index of this alloc @DESCRIPTION: Returns the count of how many allocations have been done, so that each allocation can be assigned a value equal to its cardinality in the set of allocations over the life of the program. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static int get_current_sequence_number( void ) { static int current_sequence_number = 0; ++current_sequence_number; if( current_sequence_number == get_stop_sequence_number() ) handle_internal_error( "get_current_sequence_number" ); return( current_sequence_number ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : record_ptr @INPUT : ptr : n_bytes : source_file : line_number @OUTPUT : @RETURNS : @DESCRIPTION: Records the information about a single allocation in the list. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void record_ptr_alloc_check( void *ptr, size_t n_bytes, STRING source_file, int line_number ) { update_struct update_ptrs; skip_entry *entry; if( alloc_checking_enabled() ) { check_initialized_alloc_list( &alloc_list ); if( n_bytes == 0 ) { print_source_location( source_file, line_number, -1 ); print_error( ": Alloc called with zero size.\n" ); abort_if_allowed(); } else if( ptr == (void *) 0 ) { print_source_location( source_file, line_number, -1 ); print_error( ": Alloc returned a NIL pointer.\n" ); abort_if_allowed(); } else { (void) find_pointer_position( &alloc_list, ptr, &update_ptrs ); if( check_overlap( &alloc_list, &update_ptrs, ptr, n_bytes, &entry)) { print_source_location( source_file, line_number, -1 ); print_error( ": Alloc returned a pointer overlapping an existing block:\n" ); print_source_location( entry->source_file, entry->line_number, entry->sequence_number ); print_error( "\n" ); abort_if_allowed(); } else insert_ptr_in_alloc_list( &alloc_list, &update_ptrs, ptr, n_bytes, source_file, line_number, get_current_sequence_number() ); } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : change_ptr @INPUT : old_ptr : new_ptr : n_bytes : source_file : line_number @OUTPUT : @RETURNS : @DESCRIPTION: Changes the information (mainly the n_bytes) associated with a : given pointer. This function is called from the def_alloc : macros after a realloc(). @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void change_ptr_alloc_check( void *old_ptr, void *new_ptr, size_t n_bytes, STRING source_file, int line_number ) { STRING orig_source; int orig_line; int sequence_number; skip_entry *entry; update_struct update_ptrs; if( alloc_checking_enabled() ) { check_initialized_alloc_list( &alloc_list ); if( n_bytes == 0 ) { print_source_location( source_file, line_number, -1 ); print_error( ": Realloc called with zero size.\n" ); abort_if_allowed(); } else if( !remove_ptr_from_alloc_list( &alloc_list, old_ptr, &orig_source, &orig_line, &sequence_number ) ) { print_source_location( source_file, line_number, -1 ); print_error( ": Tried to realloc a pointer not already alloced.\n"); abort_if_allowed(); } else { (void) find_pointer_position( &alloc_list, new_ptr, &update_ptrs ); if( check_overlap( &alloc_list, &update_ptrs, new_ptr, n_bytes, &entry ) ) { print_source_location( source_file, line_number, -1 ); print_error( ": Realloc returned a pointer overlapping an existing block:\n"); print_source_location( entry->source_file, entry->line_number, entry->sequence_number ); print_error( "\n" ); abort_if_allowed(); } else insert_ptr_in_alloc_list( &alloc_list, &update_ptrs, new_ptr, n_bytes, orig_source, orig_line, sequence_number ); } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : unrecord_ptr @INPUT : ptr : source_file : line_number @OUTPUT : @RETURNS : TRUE if ptr was in list @DESCRIPTION: Removes the entry for the given ptr from the list. Called by : the macros during a FREE. Returns TRUE if the pointer was : in the list. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN unrecord_ptr_alloc_check( void *ptr, STRING source_file, int line_number ) { BOOLEAN was_previously_alloced; STRING orig_source; int orig_line; int sequence_number; was_previously_alloced = TRUE; if( alloc_checking_enabled() ) { check_initialized_alloc_list( &alloc_list ); if( ptr == (void *) 0 ) { print_source_location( source_file, line_number, -1 ); print_error( ": Tried to free a NIL pointer.\n" ); abort_if_allowed(); was_previously_alloced = FALSE; } else if( !remove_ptr_from_alloc_list( &alloc_list, ptr, &orig_source, &orig_line, &sequence_number ) ) { print_source_location( source_file, line_number, -1 ); print_error( ": Tried to free a pointer not alloced.\n" ); abort_if_allowed(); was_previously_alloced = FALSE; } } return( was_previously_alloced ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_alloc_to_file @INPUT : filename @OUTPUT : @RETURNS : @DESCRIPTION: Outputs a list of all memory allocated to the given file. Usually : done at the end of the program to see if there is any memory that : was orphaned. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void output_alloc_to_file( STRING filename ) { FILE *file; STRING date_str; if( alloc_checking_enabled() ) { check_initialized_alloc_list( &alloc_list ); if( memory_still_alloced( &alloc_list ) ) { print_error( "\n" ); print_error( "\n" ); print_error( "A memory leak was found in this program.\n" ); if( filename != NULL ) print_error( "A description has been recorded in the file %s.\n", filename ); print_error( "Please report this file to the author of the program.\n" ); print_error( "\n" ); if( filename != NULL && filename[0] != (char) 0 ) file = fopen( filename, "w" ); else file = stdout; if( file != (FILE *) 0 ) { date_str = get_date(); (void) fprintf( file, "Alloc table at %s\n", date_str ); delete_string( date_str ); output_alloc_list( file, &alloc_list ); if( file != stdout ) (void) fclose( file ); } } } } #ifndef NO_DEBUG_ALLOC VIOAPI void print_alloc_source_line( STRING filename, int line_number ) { print_error( " Source position: %s:%d\n", filename, line_number ); } #endif minc-2.2.00/volume_io/Prog_utils/arrays.c0000644000265600003100000000465312027132664015244 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : set_array_size @INPUT : array type_size previous_n_elems new_n_elems - desired new array size chunk_size filename line_number @OUTPUT : @RETURNS : @DESCRIPTION: Sets the number of items allocated in the array to a multiple of : chunk_size larger than new_n_elems @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_array_size( void **array, size_t type_size, size_t previous_n_elems, size_t new_n_elems, size_t chunk_size _ALLOC_SOURCE_LINE_ARG_DEF ) { size_t new_chunk, previous_chunk; if( new_n_elems != 0 ) { new_chunk = ((new_n_elems+chunk_size-1) / chunk_size) * chunk_size; if( previous_n_elems == 0 ) { *array = alloc_memory_1d( new_chunk, type_size _ALLOC_SOURCE_LINE_ARGUMENTS ); } else { previous_chunk = ((previous_n_elems+chunk_size-1) / chunk_size) * chunk_size; if( new_chunk != previous_chunk ) realloc_memory( array, new_chunk, type_size _ALLOC_SOURCE_LINE_ARGUMENTS ); } } else if( previous_n_elems != 0 ) free_memory_1d( array _ALLOC_SOURCE_LINE_ARGUMENTS ); } minc-2.2.00/volume_io/Prog_utils/files.c0000644000265600003100000021543412030075003015031 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #if HAVE_SYS_TYPES_H #include #endif /* HAVE_SYS_TYPES_H */ #if HAVE_PWD_H #include #endif /* HAVE_PWD_H */ #include #if HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ #include static BOOLEAN has_no_extension( STRING ); static STRING compressed_endings[] = { ".z", ".Z", ".gz" }; #if !HAVE_STRERROR static char *strerror(int errnum) { extern int sys_nerr; extern char *sys_errlist[]; if( errnum < 0 || errnum >= sys_nerr ) { return( "" ); } return( sys_errlist[errnum] ); } #endif /* !HAVE_STRERROR */ /* ----------------------------- MNI Header ----------------------------------- @NAME : print_system_error @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Prints the most recent system error. @METHOD : @GLOBALS : @CALLS : @CREATED : , 1996 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void print_system_error( void ) { char *error; error = strerror( errno ); print_error( "\nSystem message: %s\n", error ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : real_is_double @INPUT : @OUTPUT : @RETURNS : TRUE if real is defined to be type double @DESCRIPTION: @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN real_is_double( void ) { static const size_t constant_8 = sizeof(double); return( sizeof(Real) == constant_8 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : file_exists @INPUT : filename @OUTPUT : @RETURNS : TRUE or FALSE if file exists @DESCRIPTION: Checks if the file of the given name exists @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN file_exists( STRING filename ) { BOOLEAN exists; FILE *file; STRING expanded; expanded = expand_filename( filename ); file = fopen( expanded, "r" ); if( file != NULL ) { (void) fclose( file ); exists = TRUE; } else exists = FALSE; delete_string( expanded ); return( exists ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : file_directory_exists @INPUT : filename @OUTPUT : @RETURNS : TRUE if directory containing file exists. @DESCRIPTION: Checks if the directory contained in the path name exists. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 2, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN file_directory_exists( STRING filename ) { BOOLEAN exists; STRING dir; dir = extract_directory( filename ); if( string_length( dir ) != 0 ) exists = file_exists( dir ); else exists = TRUE; delete_string( dir ); return( exists ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_clobber_file @INPUT : filename @OUTPUT : @RETURNS : TRUE if can write file @DESCRIPTION: Checks if the file exists. If so, asks the user for permission to overwrite the file. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN check_clobber_file( STRING filename ) { char ch; BOOLEAN okay; STRING expanded; okay = TRUE; if( file_exists( filename ) ) { expanded = expand_filename( filename ); print( "File <%s> exists, do you wish to overwrite (y or n): ", expanded ); delete_string( expanded ); while( input_character( stdin, &ch ) == OK && ch != 'y' && ch != 'n' && ch != 'N' && ch != 'Y' ) { if( ch == '\n' ) print( " Please type y or n: " ); } (void) input_newline( stdin ); okay = (ch == 'y' || ch == 'Y'); } return( okay ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_clobber_file_default_suffix @INPUT : filename default_suffix @OUTPUT : @RETURNS : TRUE if can write file @DESCRIPTION: Checks if the file exists (adding the default suffix if necessary). If the file exists, asks the user for permission to overwrite the file. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN check_clobber_file_default_suffix( STRING filename, STRING default_suffix ) { STRING expanded; BOOLEAN can_write; expanded = expand_filename( filename ); if( has_no_extension( expanded ) ) { concat_to_string( &expanded, "." ); concat_to_string( &expanded, default_suffix ); } can_write = check_clobber_file( expanded ); delete_string( expanded ); return( can_write ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_backup_filename @INPUT : filename @OUTPUT : @RETURNS : STRING - a backup filename @DESCRIPTION: Creates a backup filename that is filename.{date}.bkp If this already exists (not very likely), then it tries appending _1, _2, ... @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 3, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static STRING create_backup_filename( STRING filename ) { int i, len, count; STRING expanded, backup_filename, date; expanded = expand_filename( filename ); date = get_date(); len = string_length( expanded ) + string_length( date ) + 100; ALLOC( backup_filename, len ); count = 0; do { if( count == 0 ) { (void) sprintf( backup_filename, "%s.%s.bkp", expanded, date ); } else { (void) sprintf( backup_filename, "%s.%s.bkp_%d", expanded, date, count ); } len = string_length( backup_filename ); while( len > 0 && (backup_filename[len-1] == ' ' || backup_filename[len-1] == '\t' || backup_filename[len-1] == '\n') ) { --len; } backup_filename[len] = (char) 0; for_less( i, 0, len ) { if( backup_filename[i] == ' ' || backup_filename[i] == '\t' || backup_filename[i] == '\n' ) backup_filename[i] = '_'; /* remove ':' for windows */ if( backup_filename[i] == ':'){ backup_filename[i] = '-'; } } ++count; } while( file_exists( backup_filename ) ); delete_string( expanded ); delete_string( date ); return( backup_filename ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : make_backup_file @INPUT : filename @OUTPUT : backup_filename @RETURNS : OK or ERROR @DESCRIPTION: If the file exists, creates a backup of the file, and passes back the name of the backup file, which must be passed to cleanup_backup_file after the write of filename is performed. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 3, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status make_backup_file( STRING filename, STRING *backup_filename ) { Status status; status = OK; if( file_exists( filename ) ) { *backup_filename = create_backup_filename( filename ); status = copy_file( filename, *backup_filename ); if( status != OK ) { print_error( "Error making backup file for: %s\n", filename ); *backup_filename = NULL; } } else *backup_filename = NULL; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : cleanup_backup_file @INPUT : filename backup_filename status_of_write @OUTPUT : @RETURNS : @DESCRIPTION: This function is called after writing a file. If a backup file was made before the write, then it is deleted, if the write was successful, or copied to the original file, otherwise. @METHOD : @GLOBALS : @CALLS : @CREATED : Feb. 3, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void cleanup_backup_file( STRING filename, STRING backup_filename, Status status_of_write ) { BOOLEAN can_remove; if( backup_filename != NULL ) { can_remove = TRUE; if( status_of_write != OK ) { if( copy_file( backup_filename, filename ) != OK ) { print_error( "File %s was corrupted during a failed write,\n", filename ); print_error( "File %s contains the state prior to the write attempt.\n", backup_filename ); can_remove = FALSE; } } if( can_remove ) remove_file( backup_filename ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : remove_file @INPUT : filename @OUTPUT : @RETURNS : @DESCRIPTION: Deletes the given file. @METHOD : Makes a system call to unlink(). @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void remove_file( STRING filename ) { STRING expanded; expanded = expand_filename( filename ); if( unlink( expanded ) != 0 ) { print_error( "Error removing %s. ", expanded ); print_system_error(); } delete_string( expanded ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_file @INPUT : src dest @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Copies the src file to the dest file. @METHOD : Makes a UNIX system call, using /bin/cp @GLOBALS : @CALLS : @CREATED : Feb. 3, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status copy_file( STRING src, STRING dest ) { Status status; STRING src_expanded, dest_expanded, command; src_expanded = expand_filename( src ); dest_expanded = expand_filename( dest ); command = concat_strings( "/bin/cp ", src_expanded ); concat_to_string( &command, " " ); concat_to_string( &command, dest_expanded ); if( system( command ) != 0 ) { print_error( "Error copying file %s to %s: ", src_expanded, dest_expanded ); print_system_error(); status = ERROR; } else status = OK; delete_string( src_expanded ); delete_string( dest_expanded ); delete_string( command ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : move_file @INPUT : src dest @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Move the src file to the dest file. @METHOD : Makes a UNIX system call, using /bin/mv @GLOBALS : @CALLS : @CREATED : Feb. 3, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status move_file( STRING src, STRING dest ) { Status status; STRING src_expanded, dest_expanded, command; src_expanded = expand_filename( src ); dest_expanded = expand_filename( dest ); command = concat_strings( "/bin/cp -f ", src_expanded ); concat_to_string( &command, " " ); concat_to_string( &command, dest_expanded ); if( system( command ) != 0 ) { print_error( "Error moving file %s to %s: ", src_expanded, dest_expanded ); print_system_error(); status = ERROR; } else status = OK; delete_string( src_expanded ); delete_string( dest_expanded ); delete_string( command ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_user_home_directory @INPUT : user_name @OUTPUT : @RETURNS : Pointer to home directory string. @DESCRIPTION: Returns the home directory of the specified user. @METHOD : UNIX password file utilities @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static STRING get_user_home_directory( STRING user_name ) { #if HAVE_GETPWNAM struct passwd *p; p = getpwnam( user_name ); if( p == NULL ) return( NULL ); else return( p->pw_dir ); #else return ("."); #endif /* HAVE_GETPWNAM */ } /* ----------------------------- MNI Header ----------------------------------- @NAME : expand_filename @INPUT : filename @OUTPUT : expanded_filename @RETURNS : @DESCRIPTION: Expands certain strings in the filename, if present: environment variables, e.g. "$DATA_DIR/filename.txt" ~ e.g. "~david/filename.txt" If a dollar sign or backslash is desired, it must be preceded by a backslash. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING expand_filename( STRING filename ) { int i, new_i, dest, len, env_index; BOOLEAN tilde_found, prev_was_backslash; char *expand_value; int n_alloced, n_env_alloced; STRING env, expanded; /* --- copy from filename to expanded_filename, changing environment variables and home directories */ len = string_length( filename ); prev_was_backslash = FALSE; i = 0; dest = 0; n_alloced = 0; n_env_alloced = 0; env = NULL; expanded = NULL; while( i < len+1 ) { /* --- if not escaped by backslash, and is either a '~' at the beginning or a '$' anywhere, expand it */ if( !prev_was_backslash && ((i == 0 && filename[i] == '~') || filename[i] == '$') ) { /* --- pick up the environment variable name or user name, by searching until the next '/' or a '.' or end of string */ new_i = i; tilde_found = (filename[new_i] == '~'); ++new_i; env_index = 0; while( filename[new_i] != '/' && filename[new_i] != '.' && filename[new_i] != END_OF_STRING ) { ADD_ELEMENT_TO_ARRAY_WITH_SIZE( env, n_env_alloced, env_index, filename[new_i], DEFAULT_CHUNK_SIZE ); ++new_i; } ADD_ELEMENT_TO_ARRAY_WITH_SIZE( env, n_env_alloced, env_index, END_OF_STRING, DEFAULT_CHUNK_SIZE ); /* --- if expanding a '~', find the corresponding home directory */ if( tilde_found ) { if( string_length( env ) == 0 ) expand_value = getenv( "HOME" ); else expand_value = get_user_home_directory( env ); } else /* --- get the environment variable value */ expand_value = getenv( env ); /* --- if an expansion is found, copy it, otherwise just copy char*/ if( expand_value != NULL ) { SET_ARRAY_SIZE( expanded, n_alloced, n_alloced + string_length(expand_value), DEFAULT_CHUNK_SIZE ); n_alloced += string_length(expand_value); (void) strcpy( &expanded[dest], expand_value ); dest += string_length( expand_value ); i = new_i; } else { SET_ARRAY_SIZE( expanded, n_alloced, n_alloced + 1, DEFAULT_CHUNK_SIZE ); ++n_alloced; expanded[dest] = filename[i]; ++dest; ++i; } prev_was_backslash = FALSE; } else { /* --- if not a backslash or if it is escaped, add character */ if( filename[i] != '\\' || prev_was_backslash ) { SET_ARRAY_SIZE( expanded, n_alloced, n_alloced + 1, DEFAULT_CHUNK_SIZE ); ++n_alloced; expanded[dest] = filename[i]; ++dest; prev_was_backslash = FALSE; } else prev_was_backslash = TRUE; ++i; } } if( n_env_alloced > 0 ) delete_string( env ); return( expanded ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : filename_extension_matches @INPUT : filename extension @OUTPUT : @RETURNS : TRUE if filename extension matches @DESCRIPTION: Checks if the filename ends in a period, then the given extension. Note that the filename first undergoes expansion for home directories and environment variables, and any ending of ".z", ".Z", or ".gz" is first removed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN filename_extension_matches( STRING filename, STRING extension ) { int len, i; STRING filename_no_z, ending; BOOLEAN matches; filename_no_z = expand_filename( filename ); len = string_length( filename_no_z ); for_less( i, 0, SIZEOF_STATIC_ARRAY(compressed_endings) ) { if( string_ends_in( filename_no_z, compressed_endings[i] ) ) { filename_no_z[len-string_length(compressed_endings[i])] = END_OF_STRING; } } ending = concat_strings( ".", extension ); matches = string_ends_in( filename_no_z, ending ); delete_string( filename_no_z ); delete_string( ending ); return( matches ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : remove_directories_from_filename @INPUT : filename @OUTPUT : filename_no_directories @RETURNS : @DESCRIPTION: Creates a new filename with no directories in it. E.G. if filename equals "/usr/people/david/test.c" filename_no_directories will be set to "test.c" @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING remove_directories_from_filename( STRING filename ) { STRING expanded, no_directories; int i; expanded = expand_filename( filename ); i = string_length( expanded ); while( i >= 0 && expanded[i] != '/' ) --i; ++i; no_directories = create_string( &expanded[i] ); delete_string( expanded ); return( no_directories ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : file_exists_as_compressed @INPUT : filename @OUTPUT : compressed_filename @RETURNS : TRUE if a compressed file exists @DESCRIPTION: Checks to see if a compressed version of the file exists. If so, passes back the name of the compressed file. @METHOD : @GLOBALS : @CALLS : @CREATED : Jun 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN file_exists_as_compressed( STRING filename, STRING *compressed_filename ) { int i; STRING compressed, expanded; BOOLEAN gzipped; gzipped = FALSE; expanded = expand_filename( filename ); /* --- check to see if file.z or file.Z, etc, exists */ for_less( i, 0, SIZEOF_STATIC_ARRAY( compressed_endings ) ) { compressed = concat_strings( expanded, compressed_endings[i] ); if( file_exists( compressed ) ) { if( *compressed_filename == filename ) delete_string( filename ); *compressed_filename = compressed; gzipped = TRUE; break; } delete_string( compressed ); } delete_string( expanded ); return( gzipped ); } VIOAPI STRING get_temporary_filename( void ) { return micreate_tempfile(); } /* ----------------------------- MNI Header ----------------------------------- @NAME : open_file @INPUT : filename : io_type READ_FILE or WRITE_FILE : file_format ASCII_FORMAT or BINARY_FORMAT @OUTPUT : file @RETURNS : @DESCRIPTION: Opens the given filename for ascii or binary input or output. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status open_file( STRING filename, IO_types io_type, File_formats file_format, FILE **file ) { Status status; int i; char *tmp_name; char command[EXTREMELY_LARGE_STRING_SIZE]; STRING access_str, expanded; BOOLEAN gzipped; int command_status; /* --- determine what mode of file access */ switch( io_type ) { case APPEND_FILE: access_str = create_string( "a" ); break; case WRITE_FILE: access_str = create_string( "w" ); break; case READ_FILE: default: access_str = create_string( "r" ); break; } /* --- check if ascii or binary */ if( file_format == BINARY_FORMAT ) concat_to_string( &access_str, "b" ); /* --- expand ~ and $ in filename */ expanded = expand_filename( filename ); gzipped = FALSE; /* --- if reading the file, check if it is in compressed format */ if( io_type == READ_FILE ) { /* --- check if the filename ends in one of the compressed suffixes */ for_less( i, 0, SIZEOF_STATIC_ARRAY( compressed_endings ) ) { if( string_ends_in( expanded, compressed_endings[i] ) ) { gzipped = TRUE; break; } } /* --- if the filename does not have a compressed suffix and the file does not exist, check to see if file.z or file.Z, etc, exists */ if( !gzipped && !file_exists( expanded ) ) gzipped = file_exists_as_compressed( expanded, &expanded ); } /* --- if reading from a compressed file, decompress it to a temp file */ status = OK; if( gzipped ) { /* --- uncompress to a temporary file */ tmp_name = get_temporary_filename(); (void) sprintf( command, "gunzip -c %s > %s", expanded, tmp_name ); command_status = system( command ); /* Try again, using bzip2 */ if( command_status != 0 ) { (void) sprintf( command, "bunzip2 -c %s > %s", expanded, tmp_name ); command_status = system( command ); } /* Check for failure */ if( command_status != 0 ) { print_error( "Error uncompressing %s into %s using gunzip and bunzip2\n", expanded, tmp_name ); status = ERROR; } else replace_string( &expanded, create_string(tmp_name) ); free(tmp_name); } /* --- finally, open the file */ if( status == OK ) { *file = fopen( expanded, access_str ); if( *file == NULL ) /* --- print error message if needed */ { print_error( "Error: could not open file \"%s\". ", expanded ); print_system_error(); status = ERROR; } else if( gzipped ) /* if reading a decompressed temp file, */ remove_file( expanded ); /* unlink it, so that when the program */ /* closes the file or dies, the file is */ /* removed */ } delete_string( access_str ); delete_string( expanded ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : open_file_with_default_suffix @INPUT : filename : default_suffix - e.g. ".obj" : io_type READ_FILE or WRITE_FILE : file_format ASCII_FORMAT or BINARY_FORMAT @OUTPUT : file @RETURNS : @DESCRIPTION: Opens the given filename for ascii or binary input or output. : On output, if the file has no suffix, it adds the default suffix. : On input, if the file does not exist as given, then it tries to : find the file with the default_suffix. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status open_file_with_default_suffix( STRING filename, STRING default_suffix, IO_types io_type, File_formats file_format, FILE **file ) { Status status; BOOLEAN suffix_added; STRING used_filename, expanded; expanded = expand_filename( filename ); if( io_type == READ_FILE ) { suffix_added = FALSE; if( !file_exists(expanded) && has_no_extension( expanded ) ) { used_filename = concat_strings( expanded, "." ); concat_to_string( &used_filename, default_suffix ); if( file_exists( used_filename ) ) suffix_added = TRUE; else delete_string( used_filename ); } if( !suffix_added ) used_filename = create_string( expanded ); } else if( has_no_extension( expanded ) ) { used_filename = concat_strings( expanded, "." ); concat_to_string( &used_filename, default_suffix ); } else { used_filename = create_string( expanded ); } status = open_file( used_filename, io_type, file_format, file ); delete_string( expanded ); delete_string( used_filename ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : has_no_extension @INPUT : filename @OUTPUT : @RETURNS : TRUE if there is no . extension @DESCRIPTION: Checks if there is an extension on the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN has_no_extension( STRING filename ) { STRING base_name; BOOLEAN dot_found; base_name = remove_directories_from_filename( filename ); dot_found = (find_character( base_name, '.' ) >= 0); delete_string( base_name ); return( !dot_found ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_file_position @INPUT : file : byte_position @OUTPUT : @RETURNS : @DESCRIPTION: Sets the file position to the given offset from the start. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status set_file_position( FILE *file, long byte_position ) { Status status; if( fseek( file, byte_position, 0 ) == 0 ) { status = OK; } else { print_error( "Error setting the file position. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : close_file @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Closes the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status close_file( FILE *file ) { if( file != NULL ) { (void) fclose( file ); return( OK ); } else return( ERROR ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : extract_directory @INPUT : filename @OUTPUT : directory @RETURNS : @DESCRIPTION: Extracts the directory from the filename by copying the string : from the beginning up to the last '/'. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING extract_directory( STRING filename ) { int i, slash_index; STRING expanded, directory; expanded = expand_filename( filename ); slash_index = string_length(expanded) - 1; while( slash_index >= 0 && expanded[slash_index] != '/' ) --slash_index; if( slash_index < 0 ) directory = create_string( "." ); else { ++slash_index; directory = alloc_string( slash_index ); for_less( i, 0, slash_index ) directory[i] = expanded[i]; directory[slash_index] = END_OF_STRING; } delete_string( expanded ); return( directory ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_absolute_filename @INPUT : filename : directory @OUTPUT : @RETURNS : @DESCRIPTION: Given a filename and a default directory, determines the correct : filename by checking if the filename is a relative or absolute : pathname, and prepending the directory, if the former. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING get_absolute_filename( STRING filename, STRING directory ) { STRING abs_filename, expanded; /* if the directory is non-null and the filename is not already absolute (begins with '/'), then prefix the directory to the filename */ expanded = expand_filename( filename ); if( string_length( directory ) > 0 && expanded[0] != '/' ) { if( directory[string_length(directory)-1] == '/' ) abs_filename = create_string( directory ); else abs_filename = concat_strings( directory, "/" ); } else { abs_filename = create_string( NULL ); } concat_to_string( &abs_filename, expanded ); delete_string( expanded ); return( abs_filename ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : flush_file @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Flushes the output buffer for the given file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status flush_file( FILE *file ) { Status status; if( fflush( file ) == 0 ) { status = OK; } else { print_error( "Error flushing file. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_character @INPUT : file @OUTPUT : ch @RETURNS : Status @DESCRIPTION: Inputs one character from the file, returning ERROR if eof. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_character( FILE *file, char *ch ) { Status status; int c; c = fgetc( file ); if( c == EOF ) { status = ERROR; } else { *ch = (char) c; status = OK; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : unget_character @INPUT : file @OUTPUT : ch @RETURNS : Status @DESCRIPTION: Ungets one character back to the file, returning status. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status unget_character( FILE *file, char ch ) { Status status; int c; c = ungetc( (int) ch, file ); if( c == EOF ) status = ERROR; else status = OK; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_nonwhite_character @INPUT : file @OUTPUT : ch @RETURNS : Status @DESCRIPTION: Inputs the next nonwhite (tab, space, newline) character. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_nonwhite_character( FILE *file, char *ch ) { Status status; do { status = input_character( file, ch ); } while( status == OK && (*ch == ' ' || *ch == '\t' || *ch == '\n') ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_character @INPUT : file : ch @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs the character to the file, returning the status. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_character( FILE *file, char ch ) { Status status; if( fputc( (int) ch, file ) != ch ) { status = ERROR; } else { status = OK; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : skip_input_until @INPUT : file : search_char @OUTPUT : @RETURNS : Status @DESCRIPTION: Skips characters in the file, up to and including the first match : of the search_char; @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status skip_input_until( FILE *file, char search_char ) { Status status; char ch; status = OK; do { status = input_character( file, &ch ); } while( status == OK && ch != search_char ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_string @INPUT : file : str @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs the string to the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_string( FILE *file, STRING str ) { Status status; if( fprintf( file, "%s", str ) == string_length(str) ) status = OK; else { print_error( "Error outputting string. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_string @INPUT : file : termination_char @OUTPUT : str @RETURNS : Status @DESCRIPTION: Inputs a string from the file. First it skips white space, then : inputs all characters until the termination_char is found. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_string( FILE *file, STRING *str, char termination_char ) { char ch; Status status; status = input_nonwhite_character( file, &ch ); *str = create_string( NULL ); while( status == OK && ch != termination_char && ch != '\n' ) { concat_char_to_string( str, ch ); status = input_character( file, &ch ); } if( termination_char != '\n' && ch == '\n' ) (void) unget_character( file, ch ); if( status != OK ) { delete_string( *str ); *str = NULL; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_quoted_string @INPUT : file @OUTPUT : str @RETURNS : Status @DESCRIPTION: Skips to the next nonwhitespace character, checks if it is a : quotation mark ( ", ', or ` ), then reads characters into the : string until the : next quotation mark. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_quoted_string( FILE *file, STRING *str ) { char ch, quote; Status status; status = input_nonwhite_character( file, "e ); if( status == OK && quote != '"' && quote != '\'' && quote != '`' ) status = ERROR; if( status == OK ) status = input_character( file, &ch ); *str = create_string( NULL ); while( status == OK && ch != quote ) { concat_char_to_string( str, ch ); status = input_character( file, &ch ); } if( status != OK ) { delete_string( *str ); *str = NULL; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_possibly_quoted_string @INPUT : file : str : str_length - size of string storage @OUTPUT : @RETURNS : Status @DESCRIPTION: Skips to the next nonwhitespace character, checks if it is a : quotation mark, then reads characters into the string until the : next quotation mark. If it is not a quotation mark, reads to : the next white space. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_possibly_quoted_string( FILE *file, STRING *str ) { BOOLEAN quoted; char ch, quote; Status status; status = input_nonwhite_character( file, "e ); if( status == OK ) { if( quote == '"' || quote == '\'' || quote == '`' ) { quoted = TRUE; status = input_character( file, &ch ); } else { quoted = FALSE; ch = quote; } } *str = create_string( NULL ); while( status == OK && (quoted && ch != quote || !quoted && ch != ' ' && ch != '\t' && ch != '\n') ) { concat_char_to_string( str, ch ); status = input_character( file, &ch ); } if( !quoted ) (void) unget_character( file, ch ); if( status != OK ) { delete_string( *str ); *str = NULL; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_quoted_string @INPUT : file : str @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs the given string, with quotation marks around it. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_quoted_string( FILE *file, STRING str ) { Status status; if( fprintf( file, " \"%s\"", str ) > 0 ) status = OK; else status = ERROR; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_binary_data @INPUT : file : element_size size of each element : n number of elements @OUTPUT : data array of elements to input @RETURNS : Status @DESCRIPTION: Inputs the data in binary format. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_binary_data( FILE *file, void *data, size_t element_size, int n ) { Status status; int n_done; status = OK; n_done = (int) fread( data, element_size, (size_t) n, file ); if( n_done != n ) { print_error( "Error inputting binary data.\n" ); print_error( " (%d out of %d items of size %ld). ", n_done, n, element_size ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_binary_data @INPUT : file : data array of elements to output : element_size size of each element : n number of elements @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs the data in binary format. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_binary_data( FILE *file, void *data, size_t element_size, int n ) { Status status; int n_done; status = OK; n_done = (int) fwrite( data, element_size, (size_t) n, file ); if( n_done != n ) { print_error( "Error outputting binary data.\n" ); print_error( " (%d out of %d items of size %ld). ", n_done, n, element_size ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_newline @INPUT : file @OUTPUT : @RETURNS : Status @DESCRIPTION: Skips to after the next newline in the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_newline( FILE *file ) { Status status; status = skip_input_until( file, '\n' ); if( status != OK ) { print_error( "Error inputting newline. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_newline @INPUT : file @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs a newline to the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_newline( FILE *file ) { Status status; if( fprintf( file, "\n" ) > 0 ) status = OK; else { print_error( "Error outputting newline. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_line @INPUT : line - string to input to : str_length - storage allocated to the string @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs all characters upto the next newline. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_line( FILE *file, STRING *line ) { Status status; char ch; *line = create_string( NULL ); status = input_character( file, &ch ); while( status == OK && ch != '\n' ) { concat_char_to_string( line, ch ); status = input_character( file, &ch ); } if( status != OK ) { delete_string( *line ); *line = NULL; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_boolean @INPUT : file @OUTPUT : b @RETURNS : Status @DESCRIPTION: Inputs a BOOLEAN value from a file, by looking for an 'f' or 't'. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_boolean( FILE *file, BOOLEAN *b ) { Status status; char ch; status = input_nonwhite_character( file, &ch ); if( status == OK ) { if( ch == 'f' || ch == 'F' ) *b = FALSE; else if( ch == 't' || ch == 'T' ) *b = TRUE; else status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_boolean @INPUT : file : b @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs a T or F to the file. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_boolean( FILE *file, BOOLEAN b ) { Status status; STRING str; status = OK; if( b ) str = "T"; else str = "F"; if( fprintf( file, " %s", str ) <= 0 ) { print_error( "Error outputting BOOLEAN. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_short @INPUT : file @OUTPUT : s @RETURNS : Status @DESCRIPTION: Inputs an ascii short. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_short( FILE *file, short *s ) { Status status; if( fscanf( file, "%hd", s ) == 1 ) status = OK; else status = ERROR; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_short @INPUT : file : s @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs an ascii short. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_short( FILE *file, short s ) { Status status; if( fprintf( file, " %d", s ) > 0 ) status = OK; else { print_error( "Error outputting short. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_unsigned_short @INPUT : file @OUTPUT : s @RETURNS : Status @DESCRIPTION: Inputs an ascii unsigned short. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_unsigned_short( FILE *file, unsigned short *s ) { int i; Status status; if( fscanf( file, "%d", &i ) == 1 ) { *s = (unsigned short) i; status = OK; } else status = ERROR; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_unsigned_short @INPUT : file : s @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs an ascii unsigned short. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_unsigned_short( FILE *file, unsigned short s ) { Status status; if( fprintf( file, " %d", (int) s ) > 0 ) status = OK; else { print_error( "Error outputting unsigned short. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_int @INPUT : file @OUTPUT : i @RETURNS : Status @DESCRIPTION: Inputs an ascii integer. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_int( FILE *file, int *i ) { Status status; if( fscanf( file, "%d", i ) == 1 ) status = OK; else status = ERROR; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_int @INPUT : file : i @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs an ascii integer. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_int( FILE *file, int i ) { Status status; if( fprintf( file, " %d", i ) > 0 ) status = OK; else { print_error( "Error outputting int. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_real @INPUT : file @OUTPUT : r @RETURNS : Status @DESCRIPTION: Inputs an ascii real value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_real( FILE *file, Real *r ) { Status status; if( real_is_double() ) { status = input_double( file, (double *) r ); } else { status = input_float( file, (float *) r ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_real @INPUT : file : i @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs an ascii real value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_real( FILE *file, Real r ) { Status status; if( real_is_double() ) { status = output_double( file, (double) r ); } else { status = output_float( file, (float) r ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_float @INPUT : file @OUTPUT : f @RETURNS : Status @DESCRIPTION: Inputs an ascii float. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_float( FILE *file, float *f ) { Status status; if( fscanf( file, "%f", f ) == 1 ) status = OK; else { status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_float @INPUT : file : f @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs an ascii float value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_float( FILE *file, float f ) { Status status; if( fprintf( file, " %g", f ) > 0 ) status = OK; else { print_error( "Error outputting float. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_double @INPUT : file @OUTPUT : d @RETURNS : Status @DESCRIPTION: Inputs an ascii double. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_double( FILE *file, double *d ) { Status status; if( fscanf( file, "%lf", d ) == 1 ) status = OK; else { status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_double @INPUT : file : d @OUTPUT : @RETURNS : Status @DESCRIPTION: Outputs an ascii double value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_double( FILE *file, double d ) { Status status; if( fprintf( file, " %g", d ) > 0 ) status = OK; else { print_error( "Error outputting double. " ); print_system_error(); status = ERROR; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_binary_data @INPUT : file : io_flag : data : element_size : n @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs binary data, depending on io_flag. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_binary_data( FILE *file, IO_types io_flag, void *data, size_t element_size, int n ) { Status status; if( io_flag == READ_FILE ) status = input_binary_data( file, data, element_size, n ); else status = output_binary_data( file, data, element_size, n ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_newline @INPUT : file : io_flag : data @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary newline char, as appropriate. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_newline( FILE *file, IO_types io_flag, File_formats format ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = OK; else status = output_newline( file ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_quoted_string @INPUT : file : io_flag : format : str : str_length @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary quoted string. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_quoted_string( FILE *file, IO_types io_flag, File_formats format, STRING *str ) { int length; Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_quoted_string( file, str ); else status = output_quoted_string( file, *str ); } else { if( io_flag == WRITE_FILE ) length = string_length( *str ); status = io_int( file, io_flag, format, &length ); if( io_flag == READ_FILE ) *str = alloc_string( length ); if( status == OK ) { status = io_binary_data( file, io_flag, (void *) (*str), sizeof((*str)[0]), length ); } str[length] = END_OF_STRING; } if( status != OK ) print_error( "Error in quoted string in file.\n" ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_boolean @INPUT : file : io_flag : format : b boolean value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary boolean value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_boolean( FILE *file, IO_types io_flag, File_formats format, BOOLEAN *b ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_boolean( file, b ); else status = output_boolean( file, *b ); } else status = io_binary_data( file, io_flag, (void *) b, sizeof(*b), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_short @INPUT : file : io_flag : format : short_int short value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary short value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_short( FILE *file, IO_types io_flag, File_formats format, short *short_int ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_short( file, short_int ); else status = output_short( file, *short_int ); } else status = io_binary_data( file, io_flag, (void *) short_int, sizeof(*short_int), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_unsigned_short @INPUT : file : io_flag : format : unsigned_short short value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary unsigned short value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_unsigned_short( FILE *file, IO_types io_flag, File_formats format, unsigned short *unsigned_short ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_unsigned_short( file, unsigned_short ); else status = output_unsigned_short( file, *unsigned_short ); } else status = io_binary_data( file, io_flag, (void *) unsigned_short, sizeof(*unsigned_short), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_unsigned_char @INPUT : file : io_flag : format : c unsigned char value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary unsigned char. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_unsigned_char( FILE *file, IO_types io_flag, File_formats format, unsigned char *c ) { int i; Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) { if( fscanf( file, "%d", &i ) == 1 ) *c = (unsigned char) i; else { print_error( "Error inputting unsigned char. " ); print_system_error(); status = ERROR; } } else { if( fprintf( file, " %d", (int) *c ) < 0 ) { print_error( "Error outputting unsigned char. " ); print_system_error(); status = ERROR; } } } else status = io_binary_data( file, io_flag, (void *) c, sizeof(*c), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_int @INPUT : file : io_flag : format : i integer value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary integer value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_int( FILE *file, IO_types io_flag, File_formats format, int *i ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_int( file, i ); else status = output_int( file, *i ); } else status = io_binary_data( file, io_flag, (void *) i, sizeof(*i), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_real @INPUT : file : io_flag : format : r real value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary real value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_real( FILE *file, IO_types io_flag, File_formats format, Real *r ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_real( file, r ); else status = output_real( file, *r ); } else status = io_binary_data( file, io_flag, (void *) r, sizeof(*r), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_float @INPUT : file : io_flag : format : f float value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary double value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_float( FILE *file, IO_types io_flag, File_formats format, float *f ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_float( file, f ); else status = output_float( file, *f ); } else status = io_binary_data( file, io_flag, (void *) f, sizeof(*f), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_double @INPUT : file : io_flag : format : d double value @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs an ascii or binary double value. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_double( FILE *file, IO_types io_flag, File_formats format, double *d ) { Status status; status = OK; if( format == ASCII_FORMAT ) { if( io_flag == READ_FILE ) status = input_double( file, d ); else status = output_double( file, *d ); } else status = io_binary_data( file, io_flag, (void *) d, sizeof(*d), 1 ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_ints @INPUT : file : io_flag : format : n number of ints : ints array of ints @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs a list of ascii or binary integers. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_ints( FILE *file, IO_types io_flag, File_formats format, int n, int *ints[] ) { Status status; int i; #define INTS_PER_LINE 8 status = OK; if( io_flag == READ_FILE ) { ALLOC( *ints, n ); } if( format == ASCII_FORMAT ) { for_less( i, 0, n ) { status = io_int( file, io_flag, format, &(*ints)[i] ); if( status == OK ) { if( i == n - 1 || (i+1) % INTS_PER_LINE == 0 ) status = io_newline( file, io_flag, format ); } if( status == ERROR ) break; } } else { status = io_binary_data( file, io_flag, (void *) *ints, sizeof((*ints)[0]), n ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : io_unsigned_chars @INPUT : file : io_flag : format : n number of unsigned chars : unsigned_chars array of unsigned chars @OUTPUT : @RETURNS : Status @DESCRIPTION: Inputs or outputs a list of ascii or binary unsigned chars. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status io_unsigned_chars( FILE *file, IO_types io_flag, File_formats format, int n, unsigned char *unsigned_chars[] ) { Status status; int i; status = OK; if( io_flag == READ_FILE ) ALLOC( *unsigned_chars, n ); if( format == ASCII_FORMAT ) { for_less( i, 0, n ) { status = io_unsigned_char( file, io_flag, format, &(*unsigned_chars)[i] ); if( status == OK ) { if( i == n - 1 || (i+1) % INTS_PER_LINE == 0 ) status = io_newline( file, io_flag, format ); } if( status == ERROR ) break; } } else { status = io_binary_data( file, io_flag, (void *) (*unsigned_chars), sizeof((*unsigned_chars)[0]), n ); } return( status ); } minc-2.2.00/volume_io/Prog_utils/print.c0000644000265600003100000002114612027132664015073 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #define MAX_PRINT_STACK 100 typedef void (*print_function_type) ( STRING ); static print_function_type print_function[MAX_PRINT_STACK] = { NULL }; static int top_of_stack = 0; static print_function_type print_error_function[MAX_PRINT_STACK] = { NULL }; static int top_of_error_stack = 0; /* ----------------------------- MNI Header ----------------------------------- @NAME : set_print_function @INPUT : function @OUTPUT : @RETURNS : @DESCRIPTION: Sets the output function. If you use the function print() everywhere, in place of printf, then by default it uses printf to send output to stdout. However, you can call the set_print_function() to tell it to use a different output function, e.g. output to a GL or X window. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_print_function( void (*function) ( STRING ) ) { print_function[top_of_stack] = function; } /* ----------------------------- MNI Header ----------------------------------- @NAME : push_print_function @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Save the current print function, so, for instance, you can print to stdout temporarily. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void push_print_function( void ) { if( top_of_stack < MAX_PRINT_STACK - 1 ) { ++top_of_stack; print_function[top_of_stack] = NULL; } else handle_internal_error( "Stack overflow in push_print_function" ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : pop_print_function @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Restore the print function. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void pop_print_function( void ) { if( top_of_stack > 0 ) --top_of_stack; else handle_internal_error( "Stack underflow in pop_print_function" ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : print @INPUT : exactly same arguments as printf @OUTPUT : @RETURNS : @DESCRIPTION: prints the arguments to a temporary string buffer, then either printf's the or calls the user installed function to output the string. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ /* VARARGS */ VIOAPI void print( STRING format, ... ) { va_list ap; char print_buffer[EXTREMELY_LARGE_STRING_SIZE]; va_start( ap, format ); (void) vsprintf( print_buffer, format, ap ); va_end( ap ); if( print_function[top_of_stack] == NULL ) (void) printf( "%s", print_buffer ); else (*(print_function[top_of_stack])) ( print_buffer ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_print_error_function @INPUT : function @OUTPUT : @RETURNS : @DESCRIPTION: Sets the output function. If you use the function print_error() everywhere, in place of printf, then by default it uses printf to send output to stderr. However, you can call the set_print_error_function() to tell it to use a different output function, e.g. output to a GL or X window. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_print_error_function( void (*function) ( char [] ) ) { print_error_function[top_of_error_stack] = function; } /* ----------------------------- MNI Header ----------------------------------- @NAME : push_print_error_function @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Save the current print error function, so, for instance, you can print to stdout temporarily. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void push_print_error_function( void ) { if( top_of_error_stack < MAX_PRINT_STACK - 1 ) { ++top_of_error_stack; print_error_function[top_of_error_stack] = NULL; } else handle_internal_error( "Stack overflow in push_print_error_function" ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : pop_print_error_function @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Restore the print_error function. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void pop_print_error_function( void ) { if( top_of_error_stack > 0 ) --top_of_error_stack; else handle_internal_error( "Stack underflow in pop_print_error_function" ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : print_error @INPUT : exactly same arguments as printf @OUTPUT : @RETURNS : @DESCRIPTION: prints the arguments to a temporary string buffer, then either fprintf's to stderr or calls the user installed function to output the string. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ /* VARARGS */ VIOAPI void print_error( char format[], ... ) { va_list ap; char print_buffer[EXTREMELY_LARGE_STRING_SIZE]; va_start( ap, format ); (void) vsprintf( print_buffer, format, ap ); va_end( ap ); if( print_error_function[top_of_error_stack] == NULL ) (void) fprintf( stderr, "%s", print_buffer ); else (*(print_error_function[top_of_error_stack])) ( print_buffer ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : handle_internal_error @INPUT : str @OUTPUT : @RETURNS : @DESCRIPTION: Prints the error string and tries to get users permission to abort. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void handle_internal_error( char str[] ) { print_error( "Internal error: %s\n", str ); abort_if_allowed(); } /* ----------------------------- MNI Header ----------------------------------- @NAME : abort_if_allowed @INPUT : @OUTPUT : @RETURNS : @DESCRIPTION: Checks if the user wants to abort. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void abort_if_allowed( void ) { char ch; if( ENV_EXISTS( "ABORT_FLAG" ) ) { print_error( "Do you wish to abort (y/n): " ); do { ch = (char) getchar(); } while( ch != 'y' && ch != 'n' ); while( getchar() != '\n' ) { } if( ch == 'y' ) { abort(); } } } minc-2.2.00/volume_io/Prog_utils/progress.c0000644000265600003100000002433712027132664015610 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #define FIRST_MESSAGE_THRESHOLD 5.0 #define ONE_LINE_THRESHOLD 160.0 #define LINE_LENGTH 77 #define MIN_UPDATE_RATE 20.0 /* seconds */ #define UPDATE_RATE_FACTOR 0.05 #define RATIO_FOR_LINEAR 0.5 #define DOUBLE_THRESHOLD 0.01 #define HALF_THRESHOLD 0.5 static void show_one_line_progress( progress_struct *progress, int current_step ); static void show_multi_line_progress( progress_struct *progress, int current_step, Real time_so_far, Real est_total_time ); /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_progress_report @INPUT : one_line_only - whether line of dots is desired : n_steps : title @OUTPUT : progress - structure is filled in @RETURNS : @DESCRIPTION: Initializes the progress report, which is either a line of dots : crossing the screen, or if the progress is too slow, a line : every 20 seconds or so indicating the amount of time left. : If one_line_only is true, then it is always a single line of dots. : n_steps is the total number of items or times through the loop. : If it is really fast, no messages at all are displayed. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void initialize_progress_report( progress_struct *progress, BOOLEAN one_line_only, int n_steps, STRING title ) { progress->force_one_line = one_line_only; progress->first_msg_displayed = FALSE; progress->one_line_flag = TRUE; progress->n_steps = n_steps; progress->title = create_string( title ); progress->start_time = current_realtime_seconds(); progress->previous_time = progress->start_time; progress->last_check_time = progress->start_time; progress->last_check_step = 0; progress->next_check_step = 1; progress->check_every = 1; progress->update_rate = MIN_UPDATE_RATE; progress->sum_xy = 0.0; progress->sum_xx = 0.0; progress->n_dots_so_far = 0; progress->total_n_dots = LINE_LENGTH - string_length( progress->title ); if( progress->total_n_dots < 1 ) progress->total_n_dots = 2; } /* ----------------------------- MNI Header ----------------------------------- @NAME : update_progress_report @INPUT : progress : current_step (an integer between 1 and n_steps) @OUTPUT : @RETURNS : @DESCRIPTION: Checks the current time and determines if it is time to output : a progress message. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : Sep. 1, 1995 D. MacDonald - changed update rate to be relative to time so far ---------------------------------------------------------------------------- */ VIOAPI void update_progress_report( progress_struct *progress, int current_step ) { Real current_time, constant, n_seconds_per; Real time_so_far, est_total_time; if( current_step < 1 || current_step < progress->next_check_step ) return; if( current_step > progress->n_steps ) current_step = progress->n_steps; current_time = current_realtime_seconds(); n_seconds_per = (Real) progress->check_every * (current_time - progress->last_check_time) / (Real) (current_step - progress->last_check_step); if( n_seconds_per < DOUBLE_THRESHOLD ) progress->check_every *= 2; else if( n_seconds_per > HALF_THRESHOLD && progress->check_every > 1 ) progress->check_every /= 2; progress->last_check_time = current_time; progress->last_check_step = current_step; progress->next_check_step = current_step + progress->check_every; if( progress->next_check_step > progress->n_steps ) progress->next_check_step = progress->n_steps; time_so_far = current_time - progress->start_time; progress->sum_xy = RATIO_FOR_LINEAR * progress->sum_xy + (Real) current_step * time_so_far; progress->sum_xx = RATIO_FOR_LINEAR * progress->sum_xx + (Real) current_step * (Real) current_step; if( time_so_far > FIRST_MESSAGE_THRESHOLD ) { constant = progress->sum_xy / progress->sum_xx; est_total_time = (Real) progress->n_steps * constant; if( est_total_time <= time_so_far ) { est_total_time = time_so_far * (Real) progress->n_steps / (Real) current_step; } if( progress->force_one_line || (progress->one_line_flag && est_total_time < ONE_LINE_THRESHOLD) ) { show_one_line_progress( progress, current_step ); progress->first_msg_displayed = TRUE; } else { if( progress->first_msg_displayed && progress->one_line_flag ) print( "\n" ); progress->one_line_flag = FALSE; if( current_time - progress->previous_time >= progress->update_rate) { show_multi_line_progress( progress, current_step, time_so_far, est_total_time ); progress->first_msg_displayed = TRUE; progress->previous_time = current_time; progress->update_rate = (current_time - progress->start_time) * UPDATE_RATE_FACTOR; if( progress->update_rate < MIN_UPDATE_RATE ) progress->update_rate = MIN_UPDATE_RATE; } } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : show_one_line_progress @INPUT : progress : current_step @OUTPUT : @RETURNS : @DESCRIPTION: Given the current_step, and the total number, ensures that the : number of dots on the line is representative. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void show_one_line_progress( progress_struct *progress, int current_step ) { int i, n_dots; n_dots = ROUND( (Real) current_step / (Real) progress->n_steps * (Real) progress->total_n_dots ); if( n_dots > progress->total_n_dots ) handle_internal_error( "show_one_line_progress" ); if( n_dots > progress->n_dots_so_far ) { if( progress->n_dots_so_far == 0 ) { print( "%s: ", progress->title ); } for_less( i, progress->n_dots_so_far, n_dots ) { print( "." ); } (void) flush_file( stdout ); progress->n_dots_so_far = n_dots; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : show_multi_line_progress @INPUT : progress : current_step : time_so_far : est_total_time @OUTPUT : @RETURNS : @DESCRIPTION: Displays report about time so far, estimated time left, etc. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void show_multi_line_progress( progress_struct *progress, int current_step, Real time_so_far, Real est_total_time ) { int percent_done; STRING time_so_far_str, est_total_time_str; percent_done = ROUND( 100.0 * (Real) current_step / (Real) progress->n_steps ); time_so_far_str = format_time( "%g %s", time_so_far ); est_total_time_str = format_time( "%g %s", est_total_time ); print( "%s: %3d%% done. (%d/%d) Time: %s out of approx %s\n", progress->title, percent_done, current_step, progress->n_steps, time_so_far_str, est_total_time_str ); delete_string( time_so_far_str ); delete_string( est_total_time_str ); (void) flush_file( stdout ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : terminate_progress_report @INPUT : progress @OUTPUT : @RETURNS : @DESCRIPTION: Terminates the progress report. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void terminate_progress_report( progress_struct *progress ) { Real total_time; STRING time_str; if( progress->first_msg_displayed ) { if( progress->one_line_flag ) { show_one_line_progress( progress, progress->n_steps ); print( "\n" ); } else { total_time = current_realtime_seconds() - progress->start_time; time_str = format_time( "%g %s", total_time ); print( "%s: DONE in %s\n", progress->title, time_str ); delete_string( time_str ); } } delete_string( progress->title ); } minc-2.2.00/volume_io/Prog_utils/string.c0000644000265600003100000001736312027132664015253 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include static const STRING empty_string = ""; VIOAPI STRING alloc_string( int length ) { STRING str; ALLOC( str, length+1 ); return( str ); } VIOAPI STRING create_string( STRING initial ) { STRING str; if( initial == NULL ) initial = empty_string; str = alloc_string( string_length(initial) ); (void) strcpy( str, initial ); return( str ); } VIOAPI void delete_string( STRING string ) { if( string != NULL ) FREE( string ); } VIOAPI STRING concat_strings( STRING str1, STRING str2 ) { STRING str; if( str1 == NULL ) str1 = empty_string; if( str2 == NULL ) str2 = empty_string; ALLOC( str, string_length(str1) + string_length(str2) + 1 ); (void) strcpy( str, str1 ); (void) strcat( str, str2 ); return( str ); } VIOAPI void replace_string( STRING *string, STRING new_string ) { delete_string( *string ); *string = new_string; } VIOAPI void concat_char_to_string( STRING *string, char ch ) { int len; len = string_length( *string ); if( *string == NULL ) *string = alloc_string( 1 ); else SET_ARRAY_SIZE( *string, len+1, len+2, 1 ); (*string)[len] = ch; (*string)[len+1] = END_OF_STRING; } VIOAPI void concat_to_string( STRING *string, STRING str2 ) { STRING new_string; new_string = concat_strings( *string, str2 ); replace_string( string, new_string ); } VIOAPI int string_length( STRING string ) { if( string == NULL ) return( 0 ); else return( (int) strlen( string ) ); } VIOAPI BOOLEAN equal_strings( STRING str1, STRING str2 ) { if( str1 == NULL ) str1 = empty_string; if( str2 == NULL ) str2 = empty_string; return( strcmp( str1, str2 ) == 0 ); } VIOAPI BOOLEAN is_lower_case( char ch ) { return( ch >= 'a' && ch <= 'z' ); } VIOAPI BOOLEAN is_upper_case( char ch ) { return( ch >= 'A' && ch <= 'Z' ); } VIOAPI char get_lower_case( char ch ) { if( is_upper_case( ch ) ) return( (char) ((ch)+'a'-'A') ); else return( ch ); } VIOAPI char get_upper_case( char ch ) { if( is_lower_case( ch ) ) return( (char) ((ch)+'A'-'a') ); else return( ch ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : string_ends_in @INPUT : string : ending @OUTPUT : @RETURNS : TRUE if string ends in "ending" @DESCRIPTION: Checks if the string ends in ending, e.g., : string_ends_in( "main.c", ".c" ) returns true. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN string_ends_in( STRING string, STRING ending ) { int len_string, len_ending; BOOLEAN ending_present; len_string = string_length( string ); len_ending = string_length( ending ); if( len_ending > len_string ) ending_present = FALSE; else ending_present = equal_strings( &string[len_string-len_ending], ending); return( ending_present ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : strip_outer_blanks @INPUT : str @OUTPUT : stripped @RETURNS : @DESCRIPTION: Creates a new string which is the original str without any : leading or trailing blanks. Output argument may be the same pointer as input. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING strip_outer_blanks( STRING str ) { STRING stripped; int i, first_non_blank, last_non_blank, len; len = string_length( str ); /* --- skip leading blanks */ first_non_blank = 0; while( first_non_blank < len && str[first_non_blank] == ' ' ) { ++first_non_blank; } /* --- skip trailing blanks */ last_non_blank = len-1; while( last_non_blank >= 0 && str[last_non_blank] == ' ' ) { --last_non_blank; } /* --- now copy string, without leading or trailing blanks */ if( first_non_blank > last_non_blank ) last_non_blank = first_non_blank - 1; stripped = alloc_string( last_non_blank - first_non_blank + 1 ); for_inclusive( i, first_non_blank, last_non_blank ) stripped[i-first_non_blank] = str[i]; stripped[last_non_blank - first_non_blank + 1] = END_OF_STRING; return( stripped ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : find_character @INPUT : string : ch @OUTPUT : @RETURNS : index of ch within string or -1 @DESCRIPTION: Finds the index of the given character within the string. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int find_character( STRING string, char ch ) { int i; if( string == NULL ) return( -1 ); i = 0; while( string[i] != END_OF_STRING ) { if( string[i] == ch ) return( i ); ++i; } return( -1 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : make_string_upper_case @INPUT : string @OUTPUT : string @RETURNS : @DESCRIPTION: Converts every lower case character in string to upper case. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void make_string_upper_case( STRING string ) { int i, len; len = string_length( string ); for_less( i, 0, len ) { string[i] = get_upper_case( string[i] ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : blank_string @INPUT : string @OUTPUT : @RETURNS : TRUE if string is blank @DESCRIPTION: Checks to see if the string is blank; only contains space, tabs, and newlines. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN blank_string( STRING string ) { int i; BOOLEAN blank; if( string == NULL ) string = empty_string; blank = TRUE; i = 0; while( string[i] != END_OF_STRING ) { if( string[i] != ' ' && string[i] != '\t' && string[i] != '\n' ) { blank = FALSE; break; } ++i; } return( blank ); } minc-2.2.00/volume_io/Prog_utils/time.c0000644000265600003100000001716512027132664014703 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #if HAVE_UNISTD_H #include #endif #ifndef CLK_TCK #define CLK_TCK CLOCKS_PER_SEC #endif /* ----------------------------- MNI Header ----------------------------------- @NAME : get_clock_ticks_per_second @INPUT : @OUTPUT : @RETURNS : number clock ticks per second @DESCRIPTION: Returns the number of clock ticks per second in a system independent fashion @METHOD : @GLOBALS : @CALLS : @CREATED : Jul 3, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Real get_clock_ticks_per_second( void ) { static BOOLEAN initialized = FALSE; static Real clock_ticks_per_second; if( !initialized ) { initialized = TRUE; #if HAVE_SYSCONF clock_ticks_per_second = (Real) sysconf( _SC_CLK_TCK ); #else clock_ticks_per_second = (Real) CLK_TCK; #endif } return( clock_ticks_per_second ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : current_cpu_seconds @INPUT : @OUTPUT : @RETURNS : # seconds @DESCRIPTION: Returns the number of cpu seconds used by the program to date. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real current_cpu_seconds( void ) { static BOOLEAN first_call = TRUE; static clock_t first; clock_t current; Real secs; if (first_call) { first_call = FALSE; first = clock(); secs = (Real) first / get_clock_ticks_per_second(); } else { current = clock(); secs = (Real) (current - first) / get_clock_ticks_per_second(); } return (secs); } /* ----------------------------- MNI Header ----------------------------------- @NAME : current_realtime_seconds @INPUT : @OUTPUT : @RETURNS : # seconds @DESCRIPTION: Returns the number of seconds since the first invocation of this : function. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real current_realtime_seconds( void ) { static BOOLEAN first_call = TRUE; static time_t first; time_t current; Real secs; if( first_call ) { first_call = FALSE; first = time(NULL); secs = 0.0; } else { current = time(NULL); secs = (double) (current - first); } return( secs ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : format_time @INPUT : format : seconds @OUTPUT : str @RETURNS : @DESCRIPTION: Decides what time unit to use and displays the seconds value : in str, using format. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING format_time( STRING format, Real seconds ) { int i; static char *units[] = { "us", "ms", "sec", "min", "hrs", "days", "years" }; static Real scales[] = { 1000.0, 1000.0, 60.0, 60.0, 24.0, 365.0 }; char buffer[EXTREMELY_LARGE_STRING_SIZE]; BOOLEAN negative; negative = seconds < 0.0; if( negative ) seconds = -seconds; seconds *= 1.0e6; for_less( i, 0, SIZEOF_STATIC_ARRAY(units)-1 ) { if( seconds > 2.0 * scales[i] ) { seconds /= scales[i]; } else { break; } } seconds = (Real) ROUND( 10.0 * seconds ) / 10.0; if( negative ) seconds = -seconds; (void) sprintf( buffer, format, seconds, units[i] ); return( create_string( buffer ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : print_time @INPUT : format : seconds @OUTPUT : @RETURNS : @DESCRIPTION: Prints out the time in suitable units. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void print_time( STRING format, Real seconds ) { STRING str; str = format_time( format, seconds ); print( "%s", str ); delete_string( str ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_clock_time @INPUT : @OUTPUT : time_str @RETURNS : @DESCRIPTION: Stores the current time of day in the "time_str". @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING get_clock_time( void ) { time_t clock_time; struct tm *time_tm; char *str; (void) time( &clock_time ); time_tm = localtime( &clock_time ); str = asctime( time_tm ); return( create_string( str ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : sleep_program @INPUT : seconds @OUTPUT : @RETURNS : @DESCRIPTION: Make the program sleep for the specified number of seconds. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void sleep_program( Real seconds ) { #if HAVE_SELECT struct timeval timeout; timeout.tv_sec = (long) seconds; timeout.tv_usec = (long) (1.0e6 * (seconds - (Real) timeout.tv_sec) + 0.5); (void) select( 0, NULL, NULL, NULL, &timeout ); #else sleep((unsigned int) seconds); #endif } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_date @INPUT : @OUTPUT : date_str @RETURNS : @DESCRIPTION: Fills in the date into the string. @METHOD : @GLOBALS : @CALLS : @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING get_date( void ) { time_t clock_time; struct tm *time_tm; char *str; (void) time( &clock_time ); time_tm = localtime( &clock_time ); str = asctime( time_tm ); return( create_string( str ) ); } minc-2.2.00/volume_io/Volumes/0000755000265600003100000000000012030114722013137 500000000000000minc-2.2.00/volume_io/Volumes/evaluate.c0000644000265600003100000010515212027132664015050 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_voxel_to_value @INPUT : volume voxel @OUTPUT : @RETURNS : real value @DESCRIPTION: Converts a voxel value to a real value. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real convert_voxel_to_value( Volume volume, Real voxel ) { if( volume->real_range_set ) return( volume->real_value_scale * voxel + volume->real_value_translation ); else return( voxel ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_value_to_voxel @INPUT : volume value @OUTPUT : @RETURNS : voxel value @DESCRIPTION: Converts a real value to a voxel value. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real convert_value_to_voxel( Volume volume, Real value ) { if( volume->real_range_set ) return( (value - volume->real_value_translation) / volume->real_value_scale ); else return( value ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_voxel_value @INPUT : volume v0 voxel indices v1 v2 v3 v4 @OUTPUT : @RETURNS : Voxel value @DESCRIPTION: Returns the voxel at the specified voxel index. @METHOD : @GLOBALS : @CALLS : @CREATED : Mar. 20, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_volume_voxel_value( Volume volume, int v0, int v1, int v2, int v3, int v4 ) { Real voxel; GET_VOXEL_TYPED( voxel, (Real), volume, v0, v1, v2, v3, v4 ); return( voxel ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_real_value @INPUT : volume v0 voxel indices v1 v2 v3 v4 @OUTPUT : @RETURNS : Real value @DESCRIPTION: Returns the volume real value at the specified voxel index. @METHOD : @GLOBALS : @CALLS : @CREATED : Mar. 20, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_volume_real_value( Volume volume, int v0, int v1, int v2, int v3, int v4 ) { Real voxel, value; voxel = get_volume_voxel_value( volume, v0, v1, v2, v3, v4 ); value = convert_voxel_to_value( volume, voxel ); return( value ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_voxel_value @INPUT : volume v0 voxel indices v1 v2 v3 v4 voxel @OUTPUT : @RETURNS : @DESCRIPTION: Sets the voxel at the specified voxel index. @METHOD : @GLOBALS : @CALLS : @CREATED : Mar. 20, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_voxel_value( Volume volume, int v0, int v1, int v2, int v3, int v4, Real voxel ) { SET_VOXEL( volume, v0, v1, v2, v3, v4, voxel ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_real_value @INPUT : volume v0 voxel indices v1 v2 v3 v4 value @OUTPUT : @RETURNS : @DESCRIPTION: Sets the volume real value at the specified voxel index. @METHOD : @GLOBALS : @CALLS : @CREATED : Mar. 20, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_real_value( Volume volume, int v0, int v1, int v2, int v3, int v4, Real value ) { Real voxel; Data_types data_type; voxel = convert_value_to_voxel( volume, value ); data_type = get_volume_data_type( volume ); if( data_type != FLOAT && data_type != DOUBLE ) { voxel = (Real) ROUND( voxel ); } set_volume_voxel_value( volume, v0, v1, v2, v3, v4, voxel ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : trilinear_interpolate @INPUT : volume voxel outside_value @OUTPUT : value derivs @RETURNS : @DESCRIPTION: Computes the trilinear interpolation of the 8 coeficients, passing the value back in the 'value' parameter. If the derivs parameter is not null, then the 3 derivatives are also computed and passed back. @METHOD : @GLOBALS : @CALLS : @CREATED : Mar. 20, 1995 David MacDonald @MODIFIED : Jan. 8, 1996 D. MacDonald - now check for outside volume is done inside this procedure ---------------------------------------------------------------------------- */ static void trilinear_interpolate( Volume volume, Real voxel[], Real outside_value, Real *value, Real derivs[] ) { int c, i, j, k, *sizes, dx, dy, dz; Real x, y, z, u, v, w; Real coefs[8]; Real du00, du01, du10, du11, c00, c01, c10, c11, c0, c1, du0, du1; Real dv0, dv1, dw, scale_factor; sizes = &volume->array.sizes[0]; x = voxel[0]; y = voxel[1]; z = voxel[2]; if( x >= 0.0 && x < (Real) sizes[0]-1.0 && y >= 0.0 && y < (Real) sizes[1]-1.0 && z >= 0.0 && z < (Real) sizes[2]-1.0 ) { i = (int) x; j = (int) y; k = (int) z; GET_VOXEL_3D_TYPED( coefs[0], (Real), volume, i , j , k ); GET_VOXEL_3D_TYPED( coefs[1], (Real), volume, i , j , k+1 ); GET_VOXEL_3D_TYPED( coefs[2], (Real), volume, i , j+1, k ); GET_VOXEL_3D_TYPED( coefs[3], (Real), volume, i , j+1, k+1 ); GET_VOXEL_3D_TYPED( coefs[4], (Real), volume, i+1, j , k ); GET_VOXEL_3D_TYPED( coefs[5], (Real), volume, i+1, j , k+1 ); GET_VOXEL_3D_TYPED( coefs[6], (Real), volume, i+1, j+1, k ); GET_VOXEL_3D_TYPED( coefs[7], (Real), volume, i+1, j+1, k+1 ); } else { outside_value = convert_value_to_voxel( volume, outside_value ); i = FLOOR( x ); j = FLOOR( y ); k = FLOOR( z ); c = 0; for_less( dx, 0, 2 ) for_less( dy, 0, 2 ) for_less( dz, 0, 2 ) { if( i + dx >= 0 && i + dx < sizes[0] && j + dy >= 0 && j + dy < sizes[1] && k + dz >= 0 && k + dz < sizes[2] ) { GET_VOXEL_3D_TYPED( coefs[c], (Real), volume, i+dx, j+dy, k+dz); } else coefs[c] = outside_value; ++c; } } u = x - (Real) i; v = y - (Real) j; w = z - (Real) k; /*--- get the 4 differences in the u direction */ du00 = coefs[4] - coefs[0]; du01 = coefs[5] - coefs[1]; du10 = coefs[6] - coefs[2]; du11 = coefs[7] - coefs[3]; /*--- reduce to a 2D problem, by interpolating in the u direction */ c00 = coefs[0] + u * du00; c01 = coefs[1] + u * du01; c10 = coefs[2] + u * du10; c11 = coefs[3] + u * du11; /*--- get the 2 differences in the v direction for the 2D problem */ dv0 = c10 - c00; dv1 = c11 - c01; /*--- reduce 2D to a 1D problem, by interpolating in the v direction */ c0 = c00 + v * dv0; c1 = c01 + v * dv1; /*--- get the 1 difference in the w direction for the 1D problem */ dw = c1 - c0; /*--- if the value is desired, interpolate in 1D to get the value */ if( value != NULL ) { *value = convert_voxel_to_value( volume, c0 + w * dw ); } /*--- if the derivatives are desired, compute them */ if( derivs != NULL ) { if( volume->real_range_set ) scale_factor = volume->real_value_scale; else scale_factor = 1.0; /*--- reduce the 2D u derivs to 1D */ du0 = INTERPOLATE( v, du00, du10 ); du1 = INTERPOLATE( v, du01, du11 ); /*--- interpolate the 1D problems in w, or for Z deriv, just use dw */ derivs[X] = scale_factor * INTERPOLATE( w, du0, du1 ); derivs[Y] = scale_factor * INTERPOLATE( w, dv0, dv1 ); derivs[Z] = scale_factor * dw; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : interpolate_volume @INPUT : n_dims - number of dimensions to interpolate parameters[] - 0 to 1 parameters for each dim n_values - number of values to interpolate degree - degree of interpolation, 4 == cubic coefs - [degree*degree*degree... *n_values] coeficients @OUTPUT : values - pass back values first_deriv - pass first derivs [n_values][n_dims] second_deriv - pass back values [n_values][n_dims][n_dims] @RETURNS : @DESCRIPTION: Computes the interpolation of the box specified by coefs and its derivatives, if necessary. @METHOD : @GLOBALS : @CALLS : @CREATED : Mar. 20, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define MAX_DERIV_SIZE 100 static void interpolate_volume( int n_dims, Real parameters[], int n_values, int degree, Real coefs[], Real values[], Real **first_deriv, Real ***second_deriv ) { int v, d, d2, n_derivs, derivs_per_value, mult, mult2; Real fixed_size_derivs[MAX_DERIV_SIZE]; Real *derivs; /*--- determine how many derivatives should be computed */ if( second_deriv != NULL ) n_derivs = 2; else if( first_deriv != NULL ) n_derivs = 1; else n_derivs = 0; /*--- compute the total number of values, 1st and 2nd derivatives per val*/ derivs_per_value = 1; for_less( d, 0, n_dims ) derivs_per_value *= 1 + n_derivs; /*--- make storage for the spline routines to place the answers */ if( n_values * derivs_per_value <= MAX_DERIV_SIZE ) { derivs = fixed_size_derivs; } else { ALLOC( derivs, n_values * derivs_per_value ); } /*--- evaluate the interpolating spline */ evaluate_interpolating_spline( n_dims, parameters, degree, n_values, coefs, n_derivs, derivs ); /*--- derivs is now a one dimensional array representing derivs[n_values][1+n_derivs][1+n_derivs]..., where derivs[0][0][0][0]... = the interpolated value for 1st comp, derivs[1][0][0][0]... = the interpolated value for 2nd comp, derivs[n_values-1][0][0][0]... = interpolated value for last, derivs[0][1][0][0]... = derivative of 1st comp wrt x derivs[0][0][1][0]... = derivative of 1st comp wrt y derivs[1][1][0][0]... = derivative of 2nd comp wrt x, etc. */ if( values != NULL ) { for_less( v, 0, n_values ) values[v] = derivs[v*derivs_per_value]; } /*--- fill in the first derivatives, if required */ if( first_deriv != NULL ) { mult = 1; for_down( d, n_dims-1, 0 ) { for_less( v, 0, n_values ) first_deriv[v][d] = derivs[mult + v*derivs_per_value]; mult *= 1 + n_derivs; } } /*--- fill in the second derivatives, if required */ if( second_deriv != NULL ) { mult = 1; for_down( d, n_dims-1, 0 ) { for_less( v, 0, n_values ) second_deriv[v][d][d] = derivs[2*mult + v*derivs_per_value]; mult *= 1 + n_derivs; } mult = 1; for_down( d, n_dims-1, 0 ) { mult2 = 1; for_down( d2, n_dims-1, d+1 ) { for_less( v, 0, n_values ) { second_deriv[v][d][d2] = derivs[mult+mult2+v*derivs_per_value]; second_deriv[v][d2][d] = derivs[mult+mult2+v*derivs_per_value]; } mult2 *= 1 + n_derivs; } mult *= 1 + n_derivs; } } if( n_values * derivs_per_value > MAX_DERIV_SIZE ) { FREE( derivs ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : extract_coefficients @INPUT : volume start end inc @OUTPUT : coefs @RETURNS : @DESCRIPTION: Extracts the coefficients from a volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Jun 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void extract_coefficients( Volume volume, int start[], int end[], Real coefs[], int inc[] ) { int inc0, inc1, inc2, inc3, inc4; int ind; int start0, start1, start2, start3, start4; int end0, end1, end2, end3, end4, n_dims; int v0, v1, v2, v3, v4; /*--- for speed, use non-array variables for the loops */ start0 = start[0]; start1 = start[1]; start2 = start[2]; start3 = start[3]; start4 = start[4]; end0 = end[0]; end1 = end[1]; end2 = end[2]; end3 = end[3]; end4 = end[4]; inc0 = inc[0]; inc1 = inc[1]; inc2 = inc[2]; inc3 = inc[3]; inc4 = inc[4]; /*--- adjust the inc stride for stepping through coefs to account for the additions of the inner loops */ n_dims = get_volume_n_dimensions(volume); if( n_dims >= 2 ) inc0 -= inc1 * (end1 - start1); if( n_dims >= 3 ) inc1 -= inc2 * (end2 - start2); if( n_dims >= 4 ) inc2 -= inc3 * (end3 - start3); if( n_dims >= 5 ) inc3 -= inc4 * (end4 - start4); /*--- get the coefs[] from the volume. For speed, do each dimension separately */ ind = 0; switch( n_dims ) { case 1: for_less( v0, start0, end0 ) { GET_VALUE_1D_TYPED( coefs[ind], (Real), volume, v0 ); ind += inc0; } break; case 2: for_less( v0, start0, end0 ) { for_less( v1, start1, end1 ) { GET_VALUE_2D_TYPED( coefs[ind], (Real), volume, v0, v1 ); ind += inc1; } ind += inc0; } break; case 3: for_less( v0, start0, end0 ) { for_less( v1, start1, end1 ) { for_less( v2, start2, end2 ) { GET_VALUE_3D_TYPED( coefs[ind], (Real), volume, v0, v1, v2); ind += inc2; } ind += inc1; } ind += inc0; } break; case 4: for_less( v0, start0, end0 ) { for_less( v1, start1, end1 ) { for_less( v2, start2, end2 ) { for_less( v3, start3, end3 ) { GET_VALUE_4D_TYPED( coefs[ind], (Real), volume, v0, v1, v2, v3 ); ind += inc3; } ind += inc2; } ind += inc1; } ind += inc0; } break; case 5: for_less( v0, start0, end0 ) { for_less( v1, start1, end1 ) { for_less( v2, start2, end2 ) { for_less( v3, start3, end3 ) { for_less( v4, start4, end4 ) { GET_VALUE_5D_TYPED( coefs[ind], (Real), volume, v0, v1, v2, v3, v4 ); ind += inc4; } ind += inc3; } ind += inc2; } ind += inc1; } ind += inc0; } break; } } static Real interpolation_tolerance = 0.0; /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_interpolation_tolerance @INPUT : tolerance @OUTPUT : @RETURNS : @DESCRIPTION: Sets the tolerance which defines how close to a voxel centre we must be in order to just pass back the voxel value, rather than interpolating. @METHOD : @GLOBALS : @CALLS : @CREATED : Apr. 11, 1996 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_interpolation_tolerance( Real tolerance ) { interpolation_tolerance = tolerance; } /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_volume @INPUT : volume voxel interpolating_dimensions - whether each dimension is interpolated degrees_continuity use_linear_at_edge outside_value @OUTPUT : values first_deriv second_deriv @RETURNS : @DESCRIPTION: Takes a voxel space position and evaluates the value within the volume by nearest_neighbour, linear, quadratic, or cubic interpolation. degrees_continuity == 2 corresponds to cubic, 1 for quadratic, etc. If first_deriv is not a null pointer, then the first derivatives are passed back. Similarly for the second_deriv. If use_linear_at_edge is TRUE, then near the boundaries, either linear or nearest neighbour interpolation is used, even if cubic is specified by the degrees_continuity. If use_linear_at_edge is FALSE, then the 'outside_value' is used to provide coefficients for outside the volume, and the degree specified by degrees_continuity is used. Each dimension may or may not be interpolated, specified by the interpolating_dimensions parameter. For instance, a 4D volume of x,y,z,RGB may be interpolated in 3D (x,y,z) for each of the 3 RGB components, with one call to evaluate_volume. @CREATED : Mar 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ #define MAX_COEF_SPACE 1000 VIOAPI int evaluate_volume( Volume volume, Real voxel[], BOOLEAN interpolating_dimensions[], int degrees_continuity, BOOLEAN use_linear_at_edge, Real outside_value, Real values[], Real **first_deriv, Real ***second_deriv ) { int inc[MAX_DIMENSIONS]; int start_index, spline_degree; int next_d; int n, v, d, dim, n_values, sizes[MAX_DIMENSIONS], n_dims; int start[MAX_DIMENSIONS], n_interp_dims; int end[MAX_DIMENSIONS]; int interp_dims[MAX_DIMENSIONS]; int n_coefs; Real fraction[MAX_DIMENSIONS], bound, *coefs, pos; Real fixed_size_coefs[MAX_COEF_SPACE]; BOOLEAN fully_inside, fully_outside, on_grid_point; n_dims = get_volume_n_dimensions(volume); /*--- check for the common case trilinear interpolation of 1 value */ if( n_dims == 3 && degrees_continuity == 0 && second_deriv == NULL && (interpolating_dimensions == NULL || interpolating_dimensions[0] && interpolating_dimensions[1] && interpolating_dimensions[2]) ) { Real *deriv; if( first_deriv == NULL ) deriv = NULL; else deriv = first_deriv[0]; trilinear_interpolate( volume, voxel, outside_value, &values[0], deriv ); return( 1 ); } /*--- check if the degrees continuity is between nearest neighbour and cubic */ if( degrees_continuity < -1 || degrees_continuity > 2 ) { print_error( "Warning: evaluate_volume(), degrees invalid: %d\n", degrees_continuity ); degrees_continuity = 0; } get_volume_sizes( volume, sizes ); /*--- check if we are near a voxel centre, if so just use nearest neighbour and avoid the expensive interpolation, unless we need derivatives */ if( interpolation_tolerance > 0.0 && first_deriv == NULL && second_deriv == NULL ) { on_grid_point = TRUE; for_less( d, 0, n_dims ) { if( interpolating_dimensions == NULL || interpolating_dimensions[d]) { pos = (Real) ROUND( voxel[d] ); if( voxel[d] < pos - interpolation_tolerance || voxel[d] > pos + interpolation_tolerance ) { on_grid_point = FALSE; break; } } } if( on_grid_point ) degrees_continuity = -1; } bound = (Real) degrees_continuity / 2.0; /*--- if we must use linear interpolation near the boundaries, then check if we are near the boundaries, and adjust the degrees_continuity accordingly */ if( use_linear_at_edge && degrees_continuity >= 0 ) { for_less( d, 0, n_dims ) { if( interpolating_dimensions == NULL || interpolating_dimensions[d]) { while( degrees_continuity >= 0 && (voxel[d] < bound || voxel[d] > (Real) sizes[d] - 1.0 - bound || bound == (Real) sizes[d] - 1.0 - bound ) ) { --degrees_continuity; if( degrees_continuity == 1 ) degrees_continuity = 0; bound = (Real) degrees_continuity / 2.0; } } } } /*--- now check which dimensions are being interpolated. Also, compute how many values must be interpolated, which are all the values not in the interpolated dimensions */ n_interp_dims = 0; n_values = 1; n_coefs = 1; spline_degree = degrees_continuity + 2; fully_inside = TRUE; fully_outside = FALSE; for_less( d, 0, n_dims ) { if( interpolating_dimensions == NULL || interpolating_dimensions[d]) { interp_dims[n_interp_dims] = d; pos = voxel[d] - bound; start[d] = FLOOR( pos ); fraction[n_interp_dims] = pos - (Real) start[d]; if( voxel[d] == (Real) sizes[d] - 1.0 - bound ) { --start[d]; fraction[n_interp_dims] = 1.0; } end[d] = start[d] + spline_degree; n_coefs *= spline_degree; if( start[d] < 0 || end[d] > sizes[d] ) { fully_inside = FALSE; if( end[d] <= 0 || start[d] >= sizes[d] ) { fully_outside = TRUE; break; } } ++n_interp_dims; } else n_values *= sizes[d]; } /*--- check if the first derivatives are uncomputable */ if( first_deriv != NULL && (fully_outside || degrees_continuity < 0) ) { for_less( v, 0, n_values ) for_less( d, 0, n_interp_dims ) first_deriv[v][d] = 0.0; } /*--- check if the second derivatives are uncomputable */ if( second_deriv != NULL && (fully_outside || degrees_continuity < 1) ) { for_less( v, 0, n_values ) for_less( d, 0, n_interp_dims ) for_less( dim, 0, n_interp_dims ) second_deriv[v][d][dim] = 0.0; } /*--- check if the values are uncomputable, i.e., outside volume */ if( fully_outside ) { if( values != NULL ) { for_less( v, 0, n_values ) values[v] = outside_value; } return( n_values ); } /*--- add the non-interpolated dimensions to the list of dimensions, in order, after the interpolated dimensions */ n = 0; for_less( d, 0, n_dims ) { if( interpolating_dimensions != NULL && !interpolating_dimensions[d] ) { interp_dims[n_interp_dims+n] = d; start[d] = 0; end[d] = sizes[d]; ++n; } } /*--- make room for the coeficients */ if( n_values * n_coefs > MAX_COEF_SPACE ) { ALLOC( coefs, n_values * n_coefs ); } else coefs = fixed_size_coefs; /*--- figure out the offset within coefs. If we are inside, the offset is zero, since all coefs must be filled in. If we are partially inside, set the offset to the first coef within the volume. */ if( !fully_inside ) { /*--- compute the increments in the coefs[] array for each dimension, in order to simulate a multidimensional array with a single dim array, coefs */ inc[interp_dims[n_dims-1]] = 1; for_down( d, n_dims-2, 0 ) { next_d = interp_dims[d+1]; inc[interp_dims[d]] = inc[next_d] * (end[next_d] - start[next_d]); } start_index = 0; for_less( d, 0, n_dims ) { if( start[d] < 0 ) { start_index += -start[d] * inc[d]; start[d] = 0; } if( end[d] > sizes[d] ) end[d] = sizes[d]; } for_less( v, 0, n_values * n_coefs ) coefs[v] = outside_value; /*--- get the necessary coeficients from the volume */ extract_coefficients( volume, start, end, &coefs[start_index], inc ); } else { /*--- get the necessary coeficients from the volume */ for_less( d, n_dims, MAX_DIMENSIONS ) { start[d] = 0; end[d] = 0; } get_volume_value_hyperslab( volume, start[0], start[1], start[2], start[3], start[4], end[0] - start[0], end[1] - start[1], end[2] - start[2], end[3] - start[3], end[4] - start[4], coefs ); } /*--- now that we have the coeficients, do the interpolation */ switch( degrees_continuity ) { case -1: /*--- nearest neighbour interpolation */ for_less( v, 0, n_values ) values[v] = coefs[v]; break; case 0: case 1: case 2: interpolate_volume( n_interp_dims, fraction, n_values, spline_degree, coefs, values, first_deriv, second_deriv ); break; } if( n_values * n_coefs > MAX_COEF_SPACE ) { FREE( coefs ); } return( n_values ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : evaluate_volume_in_world @INPUT : volume x y z degrees_continuity - 0 = linear, 2 = cubic use_linear_at_edge outside_value @OUTPUT : values deriv_x deriv_y deriv_z deriv_xx deriv_xy deriv_xz deriv_yy deriv_yz deriv_zz @RETURNS : @DESCRIPTION: Takes a world space position and evaluates the value within the volume. If deriv_x is not a null pointer, then the 3 derivatives are passed back. If deriv_xx is not null, then the 6 second derivatives are passed back. If the volume is 3D, then only one value, and one derivative per deriv_x,etc. is passed back. If the volume has more than 3 dimensions, say 5 dimensions, with dimensions 3 and 4 being the non-spatial dimensions, then there will be sizes[3] * sizes[4] values passed back. The derivatives are converted to world space. @CREATED : Mar 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void evaluate_volume_in_world( Volume volume, Real x, Real y, Real z, int degrees_continuity, BOOLEAN use_linear_at_edge, Real outside_value, Real values[], Real deriv_x[], Real deriv_y[], Real deriv_z[], Real deriv_xx[], Real deriv_xy[], Real deriv_xz[], Real deriv_yy[], Real deriv_yz[], Real deriv_zz[] ) { Real ignore; Real voxel[MAX_DIMENSIONS]; Real **first_deriv, ***second_deriv; Real t[N_DIMENSIONS][MAX_DIMENSIONS]; int c, d, dim, v, n_values, n_dims, axis; int sizes[MAX_DIMENSIONS], dims_interpolated[N_DIMENSIONS]; BOOLEAN interpolating_dimensions[MAX_DIMENSIONS]; /*--- convert the world space to a voxel coordinate */ convert_world_to_voxel( volume, x, y, z, voxel ); get_volume_sizes( volume, sizes ); /*--- initialize all dimensions to not being interpolated */ n_dims = get_volume_n_dimensions( volume ); for_less( d, 0, n_dims ) interpolating_dimensions[d] = FALSE; /*--- set each spatial dimension to being interpolated */ for_less( d, 0, N_DIMENSIONS ) { axis = volume->spatial_axes[d]; if( axis < 0 ) { // print_error( // "evaluate_volume_in_world(): must have 3 spatial axes.\n" ); // return; } else { interpolating_dimensions[axis] = TRUE; } } /*--- compute the number of values, the product of the sizes of the non-interpolating dimensions */ n_values = 1; for_less( d, 0, n_dims ) { if( !interpolating_dimensions[d] ) n_values *= sizes[d]; } /*--- make room for the first derivative, if necessary */ if( deriv_x != NULL ) { ALLOC2D( first_deriv, n_values, N_DIMENSIONS ); } else first_deriv = NULL; /*--- make room for the second derivative, if necessary */ if( deriv_xx != NULL ) { ALLOC3D( second_deriv, n_values, N_DIMENSIONS, N_DIMENSIONS ); } else second_deriv = NULL; /*--- evaluate the volume and derivatives in voxel space */ n_values = evaluate_volume( volume, voxel, interpolating_dimensions, degrees_continuity, use_linear_at_edge, outside_value, values, first_deriv, second_deriv ); /*--- if the derivative is desired, convert the voxel derivative to world space */ if( deriv_x != NULL || deriv_xx != NULL ) { /*--- figure out the dimensions interpolated, in order */ dim = 0; for_less( d, 0, n_dims ) { if( interpolating_dimensions[d] ) { dims_interpolated[dim] = d; ++dim; } } } if( deriv_x != NULL ) { for_less( v, 0, n_values ) /*--- convert the deriv of each value */ { /*--- get the voxel coordinates of the first derivative */ for_less( c, 0, N_DIMENSIONS ) voxel[dims_interpolated[c]] = first_deriv[v][c]; /*--- convert the voxel-space derivative to a world derivative */ convert_voxel_normal_vector_to_world( volume, voxel, &deriv_x[v], &deriv_y[v], &deriv_z[v] ); } FREE2D( first_deriv ); } /*--- if the derivative is desired, convert the voxel derivative to world space */ if( deriv_xx != (Real *) 0 ) { for_less( v, 0, n_values ) /*--- convert the deriv of each value */ { /*--- get the voxel coordinates of the first derivative */ for_less( dim, 0, N_DIMENSIONS ) { for_less( c, 0, N_DIMENSIONS ) voxel[dims_interpolated[c]] = second_deriv[v][dim][c]; /*--- convert the voxel-space derivative to a world derivative*/ convert_voxel_normal_vector_to_world( volume, voxel, &t[X][dims_interpolated[dim]], &t[Y][dims_interpolated[dim]], &t[Z][dims_interpolated[dim]] ); } /*--- now convert the results to world */ convert_voxel_normal_vector_to_world( volume, t[X], &deriv_xx[v], &ignore, &ignore ); convert_voxel_normal_vector_to_world( volume, t[Y], &deriv_xy[v], &deriv_yy[v], &ignore ); convert_voxel_normal_vector_to_world( volume, t[Z], &deriv_xz[v], &deriv_yz[v], &deriv_zz[v] ); } FREE3D( second_deriv ); } } minc-2.2.00/volume_io/Volumes/get_hyperslab.c0000644000265600003100000011447712027132664016104 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include VIOAPI void convert_voxels_to_values( Volume volume, int n_voxels, Real voxels[], Real values[] ) { int v; Real scale, trans; if( !volume->real_range_set ) { if( voxels != values ) { for_less( v, 0, n_voxels ) values[v] = voxels[v]; } return; } scale = volume->real_value_scale; trans = volume->real_value_translation; for_less( v, 0, n_voxels ) values[v] = scale * voxels[v] + trans; } VIOAPI void get_volume_value_hyperslab( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { switch( get_volume_n_dimensions(volume) ) { case 1: get_volume_value_hyperslab_1d( volume, v0, n0, values ); break; case 2: get_volume_value_hyperslab_2d( volume, v0, v1, n0, n1, values ); break; case 3: get_volume_value_hyperslab_3d( volume, v0, v1, v2, n0, n1, n2, values ); break; case 4: get_volume_value_hyperslab_4d( volume, v0, v1, v2, v3, n0, n1, n2, n3, values ); break; case 5: get_volume_value_hyperslab_5d( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, values ); break; } } VIOAPI void get_volume_value_hyperslab_5d( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { get_volume_voxel_hyperslab_5d( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, values ); convert_voxels_to_values( volume, n0 * n1 * n2 * n3 * n4, values, values ); } VIOAPI void get_volume_value_hyperslab_4d( Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, Real values[] ) { get_volume_voxel_hyperslab_4d( volume, v0, v1, v2, v3, n0, n1, n2, n3, values ); convert_voxels_to_values( volume, n0 * n1 * n2 * n3, values, values ); } VIOAPI void get_volume_value_hyperslab_3d( Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, Real values[] ) { get_volume_voxel_hyperslab_3d( volume, v0, v1, v2, n0, n1, n2, values ); convert_voxels_to_values( volume, n0 * n1 * n2, values, values ); } VIOAPI void get_volume_value_hyperslab_2d( Volume volume, int v0, int v1, int n0, int n1, Real values[] ) { get_volume_voxel_hyperslab_2d( volume, v0, v1, n0, n1, values ); convert_voxels_to_values( volume, n0 * n1, values, values ); } VIOAPI void get_volume_value_hyperslab_1d( Volume volume, int v0, int n0, Real values[] ) { get_volume_voxel_hyperslab_1d( volume, v0, n0, values ); convert_voxels_to_values( volume, n0, values, values ); } static void slow_get_volume_voxel_hyperslab( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { int i0, i1, i2, i3, i4, n_dims; n_dims = get_volume_n_dimensions( volume ); if( n_dims < 5 ) n4 = 1; if( n_dims < 4 ) n3 = 1; if( n_dims < 3 ) n2 = 1; if( n_dims < 2 ) n1 = 1; if( n_dims < 1 ) n0 = 1; for_less( i0, 0, n0 ) for_less( i1, 0, n1 ) for_less( i2, 0, n2 ) for_less( i3, 0, n3 ) for_less( i4, 0, n4 ) { *values = get_volume_voxel_value( volume, v0 + i0, v1 + i1, v2 + i2, v3 + i3, v4 + i4 ); ++values; } } static Real *int_to_real_conversion = NULL; static void check_real_conversion_lookup( void ) { Real min_value1, max_value1, min_value2, max_value2; long i, long_min, long_max; if( int_to_real_conversion != NULL ) return; get_type_range( UNSIGNED_SHORT, &min_value1, &max_value1 ); get_type_range( SIGNED_SHORT, &min_value2, &max_value2 ); long_min = (long) MIN( min_value1, min_value2 ); long_max = (long) MAX( max_value1, max_value2 ); ALLOC( int_to_real_conversion, long_max - long_min + 1 ); #ifndef NO_DEBUG_ALLOC (void) unrecord_ptr_alloc_check( int_to_real_conversion, __FILE__, __LINE__ ); #endif int_to_real_conversion -= long_min; for_inclusive( i, long_min, long_max ) int_to_real_conversion[i] = (Real) i; } VIOAPI void get_voxel_values_5d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1, step2, step3, step4; int i0, i1, i2, i3, i4; int n0, n1, n2, n3, n4; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; n0 = counts[0]; n1 = counts[1]; n2 = counts[2]; n3 = counts[3]; n4 = counts[4]; step0 = steps[0]; step1 = steps[1]; step2 = steps[2]; step3 = steps[3]; step4 = steps[4]; step0 -= n1 * step1; step1 -= n2 * step2; step2 -= n3 * step3; step3 -= n4 * step4; check_real_conversion_lookup(); switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = int_to_real_conversion[ (long) *unsigned_byte_ptr]; ++values; unsigned_byte_ptr += step4; } unsigned_byte_ptr += step3; } unsigned_byte_ptr += step2; } unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = int_to_real_conversion[ (long) *signed_byte_ptr]; ++values; signed_byte_ptr += step4; } signed_byte_ptr += step3; } signed_byte_ptr += step2; } signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = int_to_real_conversion[ (long) *unsigned_short_ptr]; ++values; unsigned_short_ptr += step4; } unsigned_short_ptr += step3; } unsigned_short_ptr += step2; } unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = int_to_real_conversion[ (long) *signed_short_ptr]; ++values; signed_short_ptr += step4; } signed_short_ptr += step3; } signed_short_ptr += step2; } signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = (Real) *unsigned_int_ptr; ++values; unsigned_int_ptr += step4; } unsigned_int_ptr += step3; } unsigned_int_ptr += step2; } unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = (Real) *signed_int_ptr; ++values; signed_int_ptr += step4; } signed_int_ptr += step3; } signed_int_ptr += step2; } signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = (Real) *float_ptr; ++values; float_ptr += step4; } float_ptr += step3; } float_ptr += step2; } float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *values = (Real) *double_ptr; ++values; double_ptr += step4; } double_ptr += step3; } double_ptr += step2; } double_ptr += step1; } double_ptr += step0; } break; } } VIOAPI void get_voxel_values_4d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1, step2, step3; int i0, i1, i2, i3; int n0, n1, n2, n3; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; n0 = counts[0]; n1 = counts[1]; n2 = counts[2]; n3 = counts[3]; step0 = steps[0]; step1 = steps[1]; step2 = steps[2]; step3 = steps[3]; step0 -= n1 * step1; step1 -= n2 * step2; step2 -= n3 * step3; check_real_conversion_lookup(); switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = int_to_real_conversion[ (long) *unsigned_byte_ptr]; ++values; unsigned_byte_ptr += step3; } unsigned_byte_ptr += step2; } unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = int_to_real_conversion[(long) *signed_byte_ptr]; ++values; signed_byte_ptr += step3; } signed_byte_ptr += step2; } signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = int_to_real_conversion[ (long) *unsigned_short_ptr]; ++values; unsigned_short_ptr += step3; } unsigned_short_ptr += step2; } unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = int_to_real_conversion[ (long) *signed_short_ptr]; ++values; signed_short_ptr += step3; } signed_short_ptr += step2; } signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = (Real) *unsigned_int_ptr; ++values; unsigned_int_ptr += step3; } unsigned_int_ptr += step2; } unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = (Real) *signed_int_ptr; ++values; signed_int_ptr += step3; } signed_int_ptr += step2; } signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = (Real) *float_ptr; ++values; float_ptr += step3; } float_ptr += step2; } float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *values = (Real) *double_ptr; ++values; double_ptr += step3; } double_ptr += step2; } double_ptr += step1; } double_ptr += step0; } break; } } VIOAPI void get_voxel_values_3d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1, step2; int i0, i1, i2; int n0, n1, n2; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; check_real_conversion_lookup(); n0 = counts[0]; n1 = counts[1]; n2 = counts[2]; step0 = steps[0]; step1 = steps[1]; step2 = steps[2]; /*--- special case, for speed */ if( data_type == UNSIGNED_BYTE && n0 == 2 && n1 == 2 && n2 == 2 && step2 == 1 ) { step0 -= step1 + 1; step1 -= 1; ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; values[0] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; ++unsigned_byte_ptr; values[1] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; unsigned_byte_ptr += step1; values[2] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; ++unsigned_byte_ptr; values[3] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; unsigned_byte_ptr += step0; values[4] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; ++unsigned_byte_ptr; values[5] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; unsigned_byte_ptr += step1; values[6] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; ++unsigned_byte_ptr; values[7] = int_to_real_conversion[(unsigned long) *unsigned_byte_ptr]; return; } step0 -= n1 * step1; step1 -= n2 * step2; switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = int_to_real_conversion[(long) *unsigned_byte_ptr]; ++values; unsigned_byte_ptr += step2; } unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = int_to_real_conversion[(long) *signed_byte_ptr]; ++values; signed_byte_ptr += step2; } signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = int_to_real_conversion[(long) *unsigned_short_ptr]; ++values; unsigned_short_ptr += step2; } unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = int_to_real_conversion[(long) *signed_short_ptr]; ++values; signed_short_ptr += step2; } signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = (Real) *unsigned_int_ptr; ++values; unsigned_int_ptr += step2; } unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = (Real) *signed_int_ptr; ++values; signed_int_ptr += step2; } signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = (Real) *float_ptr; ++values; float_ptr += step2; } float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *values = (Real) *double_ptr; ++values; double_ptr += step2; } double_ptr += step1; } double_ptr += step0; } break; } } VIOAPI void get_voxel_values_2d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1; int i0, i1; int n0, n1; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; n0 = counts[0]; n1 = counts[1]; step0 = steps[0]; step1 = steps[1]; step0 -= n1 * step1; check_real_conversion_lookup(); switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = int_to_real_conversion[(long) *unsigned_byte_ptr]; ++values; unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = int_to_real_conversion[(long) *signed_byte_ptr]; ++values; signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = int_to_real_conversion[(long) *unsigned_short_ptr]; ++values; unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = int_to_real_conversion[(long) *signed_short_ptr]; ++values; signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = (Real) *unsigned_int_ptr; ++values; unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = (Real) *signed_int_ptr; ++values; signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = (Real) *float_ptr; ++values; float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *values = (Real) *double_ptr; ++values; double_ptr += step1; } double_ptr += step0; } break; } } VIOAPI void get_voxel_values_1d( Data_types data_type, void *void_ptr, int step0, int n0, Real values[] ) { int i0; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; check_real_conversion_lookup(); switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = int_to_real_conversion[(long) *unsigned_byte_ptr]; ++values; unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = int_to_real_conversion[(long) *signed_byte_ptr]; ++values; signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = int_to_real_conversion[(long) *unsigned_short_ptr]; ++values; unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = int_to_real_conversion[(long) *signed_short_ptr]; ++values; signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = (Real) *unsigned_int_ptr; ++values; unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = (Real) *signed_int_ptr; ++values; signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = (Real) *float_ptr; ++values; float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { *values = (Real) *double_ptr; ++values; double_ptr += step0; } break; } } static void get_voxel_values( Volume volume, void *void_ptr, int n_dims, int steps[], int counts[], Real values[] ) { Data_types data_type; data_type = get_volume_data_type( volume ); switch( n_dims ) { case 0: get_voxel_values_1d( data_type, void_ptr, 1, 1, values ); break; case 1: get_voxel_values_1d( data_type, void_ptr, steps[0], counts[0], values ); break; case 2: get_voxel_values_2d( data_type, void_ptr, steps, counts, values ); break; case 3: get_voxel_values_3d( data_type, void_ptr, steps, counts, values ); break; case 4: get_voxel_values_4d( data_type, void_ptr, steps, counts, values ); break; case 5: get_voxel_values_5d( data_type, void_ptr, steps, counts, values ); break; } } VIOAPI void get_volume_voxel_hyperslab_5d( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_get_volume_voxel_hyperslab( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_5D( void_ptr, volume->array, v0, v1, v2, v3, v4 ) stride = 1; dim = 5; if( n4 > 1 ) { --dim; counts[dim] = n4; steps[dim] = stride; } stride *= sizes[4]; if( n3 > 1 ) { --dim; counts[dim] = n3; steps[dim] = stride; } stride *= sizes[3]; if( n2 > 1 ) { --dim; counts[dim] = n2; steps[dim] = stride; } stride *= sizes[2]; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } get_voxel_values( volume, void_ptr, 5 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void get_volume_voxel_hyperslab_4d( Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_get_volume_voxel_hyperslab( volume, v0, v1, v2, v3, 0, n0, n1, n2, n3, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_4D( void_ptr, volume->array, v0, v1, v2, v3 ) stride = 1; dim = 4; if( n3 > 1 ) { --dim; counts[dim] = n3; steps[dim] = stride; } stride *= sizes[3]; if( n2 > 1 ) { --dim; counts[dim] = n2; steps[dim] = stride; } stride *= sizes[2]; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } get_voxel_values( volume, void_ptr, 4 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void get_volume_voxel_hyperslab_3d( Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_get_volume_voxel_hyperslab( volume, v0, v1, v2, 0, 0, n0, n1, n2, 0, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_3D( void_ptr, volume->array, v0, v1, v2 ) stride = 1; dim = 3; if( n2 > 1 ) { --dim; counts[dim] = n2; steps[dim] = stride; } stride *= sizes[2]; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } get_voxel_values( volume, void_ptr, 3 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void get_volume_voxel_hyperslab_2d( Volume volume, int v0, int v1, int n0, int n1, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_get_volume_voxel_hyperslab( volume, v0, v1, 0, 0, 0, n0, n1, 0, 0, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_2D( void_ptr, volume->array, v0, v1 ) stride = 1; dim = 2; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } get_voxel_values( volume, void_ptr, 2 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void get_volume_voxel_hyperslab_1d( Volume volume, int v0, int n0, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim; void *void_ptr; if( volume->is_cached_volume ) { slow_get_volume_voxel_hyperslab( volume, v0, 0, 0, 0, 0, n0, 0, 0, 0, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_1D( void_ptr, volume->array, v0 ) dim = 1; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = 1; } get_voxel_values( volume, void_ptr, 1 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void get_volume_voxel_hyperslab( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real voxels[] ) { switch( get_volume_n_dimensions(volume) ) { case 1: get_volume_voxel_hyperslab_1d( volume, v0, n0, voxels ); break; case 2: get_volume_voxel_hyperslab_2d( volume, v0, v1, n0, n1, voxels ); break; case 3: get_volume_voxel_hyperslab_3d( volume, v0, v1, v2, n0, n1, n2, voxels ); break; case 4: get_volume_voxel_hyperslab_4d( volume, v0, v1, v2, v3, n0, n1, n2, n3, voxels ); break; case 5: get_volume_voxel_hyperslab_5d( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, voxels ); break; } } minc-2.2.00/volume_io/Volumes/input_free.c0000644000265600003100000004734512027132664015413 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #define DEFAULT_SUFFIX "fre" #define NUM_BYTE_VALUES 256 static Status input_slice( volume_input_struct *volume_input ); /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_free_format_input @INPUT : @OUTPUT : volume volume_input @RETURNS : OK if successful @DESCRIPTION: Initializes loading a free format file by reading the header. If the file contains short, but the convert_to_byte flag is set in volume_input, then the file is converted to bytes on input. This function assumes that volume->filename has been assigned. @CREATED : David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - now uses volume starts ---------------------------------------------------------------------------- */ VIOAPI Status initialize_free_format_input( STRING filename, Volume volume, volume_input_struct *volume_input ) { Status status, file_status; STRING volume_filename, abs_volume_filename, slice_filename; int sizes[N_DIMENSIONS]; int c, volume_byte_offset, int_size; int n_bytes_per_voxel, min_value, max_value, i; int n_slices, n_voxels_in_slice; long slice; nc_type desired_data_type; int value; char ch; Real file_separations[MAX_DIMENSIONS]; Real volume_separations[MAX_DIMENSIONS]; Real trans[N_DIMENSIONS]; FILE *file; BOOLEAN axis_valid; int axis; status = OK; file_status = open_file_with_default_suffix( filename, DEFAULT_SUFFIX, READ_FILE, ASCII_FORMAT, &file ); status = file_status; abs_volume_filename = NULL; /* read the line containing: n_bytes_per_voxel */ if( status == OK ) status = input_int( file, &n_bytes_per_voxel ); /* input the 3 translation values used for the voxel_to_world_transform */ if( status == OK && (input_real( file, &trans[X] ) != OK || input_real( file, &trans[Y] ) != OK || input_real( file, &trans[Z] ) != OK) ) { print_error( "Error reading x,y,z translations from %s.\n", filename ); status = ERROR; } if( status == OK ) { /* decide what type of data is in image file */ if( n_bytes_per_voxel == 1 ) volume_input->file_data_type = UNSIGNED_BYTE; else if( n_bytes_per_voxel == 2 ) volume_input->file_data_type = UNSIGNED_SHORT; else { print_error( "Must be either 1 or 2 bytes per voxel.\n" ); status = ERROR; } /* decide how to store data in memory */ if( get_volume_data_type(volume) == NO_DATA_TYPE ) desired_data_type = NC_BYTE; else desired_data_type = volume->nc_data_type; } /* read 3 lines, 1 for each axis: number_voxels +/-voxel_separation x|y|z where the x, y, or z is used to indicate the ordering of the axes within the file, with the 3rd one being the fastest varying index. negative voxel separation means flip on display */ if( volume->spatial_axes[X] < 0 || volume->spatial_axes[Y] < 0 || volume->spatial_axes[Z] < 0 ) { print_error( "warning initialize_free_format_input: setting spatial axes to XYZ.\n"); volume->spatial_axes[X] = 0; volume->spatial_axes[Y] = 1; volume->spatial_axes[Z] = 2; } if( status == OK ) for_less( axis, 0, N_DIMENSIONS ) { status = ERROR; if( input_int( file, &int_size ) != OK ) break; volume_input->sizes_in_file[axis] = (long) int_size; if( input_real( file, &file_separations[axis] ) != OK ) break; if( input_nonwhite_character( file, &ch ) != OK ) break; axis_valid = TRUE; switch( ch ) { case 'x': case 'X': volume_input->axis_index_from_file[axis] = volume->spatial_axes[X]; break; case 'y': case 'Y': volume_input->axis_index_from_file[axis] = volume->spatial_axes[Y]; break; case 'z': case 'Z': volume_input->axis_index_from_file[axis] = volume->spatial_axes[Z]; break; default: axis_valid = FALSE; break; } if( !axis_valid ) { print_error( "Invalid axis.\n" ); break; } status = OK; } for_less( c, 0, N_DIMENSIONS ) { volume->spatial_axes[c] = c; volume->direction_cosines[c][X] = 0.0; volume->direction_cosines[c][Y] = 0.0; volume->direction_cosines[c][Z] = 0.0; volume->direction_cosines[c][c] = 1.0; } if( status == OK && (volume_input->axis_index_from_file[X] == volume_input->axis_index_from_file[Y] || volume_input->axis_index_from_file[X] == volume_input->axis_index_from_file[Z] || volume_input->axis_index_from_file[Y] == volume_input->axis_index_from_file[Z]) ) { print_error( "Two axis indices are equal.\n" ); status = ERROR; } volume_input->directory = extract_directory( filename ); if( status == OK ) if( volume_input->sizes_in_file[0] <= 0 ) { n_slices = 0; while( input_string( file, &slice_filename, (char) ' ' )==OK) { SET_ARRAY_SIZE( volume_input->slice_filenames, n_slices, n_slices+1, DEFAULT_CHUNK_SIZE ); volume_input->slice_filenames[n_slices] = slice_filename; SET_ARRAY_SIZE( volume_input->slice_byte_offsets, n_slices, n_slices+1, DEFAULT_CHUNK_SIZE ); if( input_int( file, &volume_input->slice_byte_offsets[n_slices] ) != OK ) { volume_input->slice_byte_offsets[n_slices] = 0; } ++n_slices; } volume_input->sizes_in_file[0] = (long) n_slices; volume_input->one_file_per_slice = TRUE; } else { volume_input->one_file_per_slice = FALSE; status = input_string( file, &volume_filename, (char) ' ' ); abs_volume_filename = get_absolute_filename( volume_filename, volume_input->directory ); delete_string( volume_filename ); if( input_int( file, &volume_byte_offset ) != OK ) volume_byte_offset = 0; } if( status == OK ) status = close_file( file ); /* record the information in the volume struct */ if( status == OK ) { for_less( axis, 0, N_DIMENSIONS ) { sizes[volume_input->axis_index_from_file[axis]] = (int) volume_input->sizes_in_file[axis]; volume_separations[volume_input->axis_index_from_file[axis]] = file_separations[axis]; if( volume_separations[axis] < 0.0 ) { trans[axis] += -volume_separations[axis] * (Real) (sizes[axis]-1); } } set_volume_separations( volume, volume_separations ); set_volume_starts( volume, trans ); } set_volume_type( volume, desired_data_type, FALSE, 0.0, 0.0 ); set_volume_sizes( volume, sizes ); /* allocate the slice buffer */ n_voxels_in_slice = (int) volume_input->sizes_in_file[1] * (int) volume_input->sizes_in_file[2]; if( status == OK ) switch( volume_input->file_data_type ) { case UNSIGNED_BYTE: ALLOC( volume_input->byte_slice_buffer, n_voxels_in_slice ); break; case UNSIGNED_SHORT: ALLOC( volume_input->short_slice_buffer, n_voxels_in_slice ); break; default: handle_internal_error( "initialize_free_format_input" ); break; } /* if the data must be converted to byte, read the entire image file simply to find the max and min values, and set the value_scale and value_translation */ if( status == OK && get_volume_data_type(volume) != volume_input->file_data_type ) { if( status == OK && !volume_input->one_file_per_slice ) { status = open_file( abs_volume_filename, READ_FILE, BINARY_FORMAT, &volume_input->volume_file ); if( status == OK ) status = set_file_position( file, (long) volume_byte_offset ); } min_value = 0; max_value = 0; volume_input->slice_index = 0; for_less( slice, 0, volume_input->sizes_in_file[0] ) { (void) input_slice( volume_input ); for_less( i, 0, n_voxels_in_slice ) { value = (int) volume_input->short_slice_buffer[i]; if( slice == 0 && i == 0 || value < min_value ) min_value = value; if( slice == 0 && i == 0 || value > max_value ) max_value = value; } } set_volume_voxel_range( volume, (Real) min_value, (Real) max_value ); if( status == OK && !volume_input->one_file_per_slice ) status = close_file( volume_input->volume_file ); } if( status == OK && !volume_input->one_file_per_slice ) { status = open_file( abs_volume_filename, READ_FILE, BINARY_FORMAT, &volume_input->volume_file ); delete_string( abs_volume_filename ); if( status == OK ) status = set_file_position( file, (long) volume_byte_offset ); } volume_input->slice_index = 0; delete_string( abs_volume_filename ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_free_format_input @INPUT : volume_input @OUTPUT : @RETURNS : @DESCRIPTION: Frees the slice buffer and closes the image file. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void delete_free_format_input( volume_input_struct *volume_input ) { long slice; if( volume_input->file_data_type == UNSIGNED_BYTE ) { FREE( volume_input->byte_slice_buffer ); } else { FREE( volume_input->short_slice_buffer ); } delete_string( volume_input->directory ); if( volume_input->one_file_per_slice ) { for_less( slice, 0, volume_input->sizes_in_file[0] ) delete_string( volume_input->slice_filenames[slice] ); FREE( volume_input->slice_filenames ); FREE( volume_input->slice_byte_offsets ); } else { (void) close_file( volume_input->volume_file ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_slice @INPUT : volume volume_input @OUTPUT : @RETURNS : OK if success @DESCRIPTION: Reads the next slice from the volume. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status input_slice( volume_input_struct *volume_input ) { Status status; FILE *file; STRING slice_filename; status = OK; if( (long) volume_input->slice_index < volume_input->sizes_in_file[0] ) { if( volume_input->one_file_per_slice ) { slice_filename = get_absolute_filename( volume_input->slice_filenames[volume_input->slice_index], volume_input->directory ); status = open_file( slice_filename, READ_FILE, BINARY_FORMAT, &file ); delete_string( slice_filename ); if( status == OK ) status = set_file_position( file, (long) (volume_input->slice_byte_offsets [volume_input->slice_index]) ); } else file = volume_input->volume_file; if( status == OK ) switch( volume_input->file_data_type ) { case UNSIGNED_BYTE: status = io_binary_data( file, READ_FILE, (void *) volume_input->byte_slice_buffer, sizeof(volume_input->byte_slice_buffer[0]), (int) volume_input->sizes_in_file[1] * (int) volume_input->sizes_in_file[2] ); break; case UNSIGNED_SHORT: status = io_binary_data( file, READ_FILE, (void *) volume_input->short_slice_buffer, sizeof(volume_input->short_slice_buffer[0]), (int) volume_input->sizes_in_file[1] * (int) volume_input->sizes_in_file[2] ); break; default: handle_internal_error( "input_slice" ); break; } if( status == OK && volume_input->one_file_per_slice ) { status = close_file( file ); } ++volume_input->slice_index; } else status = ERROR; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_more_free_format_file @INPUT : volume volume_input @OUTPUT : fraction_done @RETURNS : TRUE if more to input after this call @DESCRIPTION: Reads in one more slice from the image file. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN input_more_free_format_file( Volume volume, volume_input_struct *volume_input, Real *fraction_done ) { Real min_value, max_value, value; int x, y, z, sizes[MAX_DIMENSIONS]; long i; Status status; BOOLEAN more_to_do, scaling_flag; Real value_translation, value_scale; Real original_min_voxel, original_max_voxel; int *inner_index, indices[MAX_DIMENSIONS]; unsigned char *byte_buffer_ptr; unsigned short *short_buffer_ptr; if( (long) volume_input->slice_index < volume_input->sizes_in_file[0] ) { if( !volume_is_alloced( volume ) ) { alloc_volume_data( volume ); if( !volume_is_alloced( volume ) ) return( FALSE ); } status = input_slice( volume_input ); scaling_flag = FALSE; if( get_volume_data_type(volume) != volume_input->file_data_type ) { scaling_flag = TRUE; get_volume_voxel_range( volume, &original_min_voxel, &original_max_voxel ); value_translation = original_min_voxel; value_scale = (original_max_voxel - original_min_voxel) / (Real) (NUM_BYTE_VALUES - 1); } inner_index = &indices[volume_input->axis_index_from_file[2]]; indices[volume_input->axis_index_from_file[0]] = volume_input->slice_index-1; if( status == OK ) switch( volume_input->file_data_type ) { case UNSIGNED_BYTE: byte_buffer_ptr = volume_input->byte_slice_buffer; for_less( i, 0, volume_input->sizes_in_file[1] ) { indices[volume_input->axis_index_from_file[1]] = (int) i; for_less( *inner_index, 0, (int) volume_input->sizes_in_file[2] ) { if( scaling_flag ) { value = ((Real) (*byte_buffer_ptr) - value_translation)/ value_scale; if( value < 0.0 ) value = 0.0; else if( value > 255.0 ) value = 255.0; } else value = (Real) (*byte_buffer_ptr); set_volume_voxel_value( volume, indices[X], indices[Y], indices[Z], 0, 0, value ); ++byte_buffer_ptr; } } break; case UNSIGNED_SHORT: short_buffer_ptr = volume_input->short_slice_buffer; for_less( i, 0, volume_input->sizes_in_file[1] ) { indices[volume_input->axis_index_from_file[1]] = (int) i; for_less( *inner_index, 0, (int) volume_input->sizes_in_file[2]) { if( scaling_flag ) { value = ((Real) (*short_buffer_ptr) - value_translation) / value_scale; } else value = (Real) (*short_buffer_ptr); set_volume_voxel_value( volume, indices[X], indices[Y], indices[Z], 0, 0, value ); ++short_buffer_ptr; } } break; default: handle_internal_error( "input_more_free_format_file" ); break; } } get_volume_sizes( volume, sizes ); *fraction_done = (Real) volume_input->slice_index / (Real) sizes[volume_input->axis_index_from_file[0]]; more_to_do = TRUE; if( volume_input->slice_index == sizes[volume_input->axis_index_from_file[0]] ) { more_to_do = FALSE; min_value = get_volume_voxel_value( volume, 0, 0, 0, 0, 0 ); max_value = min_value; for_less( x, 0, sizes[X] ) { for_less( y, 0, sizes[Y] ) { for_less( z, 0, sizes[Z] ) { value = get_volume_voxel_value( volume, x, y, z, 0,0); if( value < min_value ) min_value = value; else if( value > max_value ) max_value = value; } } } set_volume_voxel_range( volume, min_value, max_value ); if( get_volume_data_type(volume) != volume_input->file_data_type ) { set_volume_real_range( volume, original_min_voxel, original_max_voxel ); } } return( more_to_do ); } minc-2.2.00/volume_io/Volumes/input_mnc.c0000644000265600003100000014520012027132664015234 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #define INVALID_AXIS -1 static BOOLEAN match_dimension_names( int n_volume_dims, STRING volume_dimension_names[], int n_file_dims, STRING file_dimension_names[], int to_volume_index[] ); /* ----------------------------- MNI Header ----------------------------------- @NAME : get_minc_file_n_dimensions @INPUT : filename @OUTPUT : @RETURNS : n_dims @DESCRIPTION: Returns the number of dimensions in the minc file. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 4, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_minc_file_n_dimensions( STRING filename ) { int cdfid, img_var, n_dims; int dim_vars[MAX_VAR_DIMS]; nc_type file_datatype; STRING expanded; ncopts = NC_VERBOSE; expanded = expand_filename( filename ); cdfid = miopen( expanded, NC_NOWRITE ); if( cdfid == MI_ERROR ) { print_error( "Error opening %s\n", expanded ); delete_string( expanded ); return( -1 ); } delete_string( expanded ); img_var = ncvarid( cdfid, MIimage ); ncvarinq( cdfid, img_var, (char *) NULL, &file_datatype, &n_dims, dim_vars, (int *) NULL ); (void) miclose( cdfid ); return( n_dims ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_minc_input_from_minc_id @INPUT : minc_id volume options @OUTPUT : @RETURNS : Minc_file @DESCRIPTION: Initializes input of volumes from an already opened MINC file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Nov. 15, 1996 D. MacDonald - added handling of space type @MODIFIED : May 20, 1997 D. MacDonald - removed float arithmetic in transformations and made volumes store starts/steps/dircos ---------------------------------------------------------------------------- */ VIOAPI Minc_file initialize_minc_input_from_minc_id( int minc_id, Volume volume, minc_input_options *options ) { minc_file_struct *file; int dim_vars[MAX_VAR_DIMS], n_vol_dims; int i, slab_size, prev_sizes[MAX_VAR_DIMS]; nc_type prev_nc_type; BOOLEAN different; BOOLEAN range_specified; double valid_range[2]; long long_size; BOOLEAN converted_sign, space_type_consensus; nc_type converted_type; char signed_flag[MI_MAX_ATTSTR_LEN+1], *ptr; char dim_name[MI_MAX_ATTSTR_LEN+1]; char prev_space_type[MI_MAX_ATTSTR_LEN+1]; char space_type[MI_MAX_ATTSTR_LEN+1]; nc_type file_datatype; int sizes[MAX_VAR_DIMS]; double file_separations[MAX_VAR_DIMS]; Real volume_separations[MAX_VAR_DIMS]; Real volume_starts[MAX_VAR_DIMS]; Real voxel_zero; double start_position[MAX_VAR_DIMS]; double dir_cosines[MAX_VAR_DIMS][MI_NUM_SPACE_DIMS]; double tmp_cosines[MI_NUM_SPACE_DIMS]; BOOLEAN spatial_dim_flags[MAX_VAR_DIMS]; double real_min, real_max; int d, dimvar, which_valid_axis, axis; int spatial_axis_indices[MAX_VAR_DIMS]; minc_input_options default_options; BOOLEAN no_volume_data_type; char spacing_type[MI_MAX_ATTSTR_LEN+1]; double *irr_starts[MAX_VAR_DIMS]; double *irr_widths[MAX_VAR_DIMS]; ALLOC( file, 1 ); file->cdfid = minc_id; file->file_is_being_read = TRUE; file->volume = volume; if( options == (minc_input_options *) NULL ) { set_default_minc_input_options( &default_options ); set_default_minc_input_options( &file->original_input_options ); options = &default_options; } else file->original_input_options = *options; get_volume_sizes( volume, prev_sizes ); prev_nc_type = volume->nc_data_type; /* --- find the image variable */ file->img_var = ncvarid( file->cdfid, MIimage ); ncvarinq( file->cdfid, file->img_var, (char *) NULL, &file_datatype, &file->n_file_dimensions, dim_vars, (int *) NULL ); for_less( d, 0, file->n_file_dimensions ) { (void) ncdiminq( file->cdfid, dim_vars[d], dim_name, &long_size ); file->dim_names[d] = create_string( dim_name ); file->sizes_in_file[d] = long_size; } file->converting_to_colour = FALSE; if( equal_strings( file->dim_names[file->n_file_dimensions-1], MIvector_dimension ) ) { if( options->convert_vector_to_colour_flag && file->sizes_in_file[file->n_file_dimensions-1] >= (long) options->dimension_size_for_colour_data && file->sizes_in_file[file->n_file_dimensions-1] <= (long) options->max_dimension_size_for_colour_data ) { for_less( i, 0, 4 ) { file->rgba_indices[i] = options->rgba_indices[i]; if( (long) options->rgba_indices[i] >= file->sizes_in_file[file->n_file_dimensions-1] ) { file->rgba_indices[i] = -1; if( i != 3 ) print_error( "Warning: rgba indices out of range.\n" ); } } set_volume_type( volume, NC_INT, FALSE, 0.0, 0.0 ); set_rgb_volume_flag( volume, TRUE ); file->converting_to_colour = TRUE; delete_string( file->dim_names[file->n_file_dimensions-1] ); --file->n_file_dimensions; } else if( options->convert_vector_to_scalar_flag ) { delete_string( file->dim_names[file->n_file_dimensions-1] ); --file->n_file_dimensions; } } n_vol_dims = get_volume_n_dimensions( volume ); if( file->n_file_dimensions < n_vol_dims ) { print_error( "Error: MINC file has only %d dims, volume requires %d.\n", file->n_file_dimensions, n_vol_dims ); FREE( file ); return( (Minc_file) 0 ); } else if( file->n_file_dimensions > MAX_VAR_DIMS ) { print_error( "Error: MINC file has %d dims, can only handle %d.\n", file->n_file_dimensions, MAX_VAR_DIMS ); FREE( file ); return( (Minc_file) NULL ); } /* --- match the dimension names of the volume with those in the file */ if( !match_dimension_names( get_volume_n_dimensions(volume), volume->dimension_names, file->n_file_dimensions, file->dim_names, file->to_volume_index ) ) { print_error( "Error: dimension names did not match: \n" ); print_error( "\n" ); print_error( "Requested:\n" ); for_less( d, 0, n_vol_dims ) print_error( "%d: %s\n", d+1, volume->dimension_names[d] ); print_error( "\n" ); print_error( "In File:\n" ); for_less( d, 0, file->n_file_dimensions ) print_error( "%d: %s\n", d+1, file->dim_names[d] ); FREE( file ); return( (Minc_file) NULL ); } for_less( d, 0, n_vol_dims ) file->to_file_index[d] = INVALID_AXIS; for_less( d, 0, file->n_file_dimensions ) { if( file->to_volume_index[d] != INVALID_AXIS ) file->to_file_index[file->to_volume_index[d]] = d; } file->n_volumes_in_file = 1; /* --- find the spatial axes (x,y,z) */ which_valid_axis = 0; for_less( d, 0, N_DIMENSIONS ) { volume->spatial_axes[d] = INVALID_AXIS; file->spatial_axes[d] = INVALID_AXIS; } for_less( d, 0, file->n_file_dimensions ) { if( convert_dim_name_to_spatial_axis( file->dim_names[d], &axis ) ) { spatial_axis_indices[d] = axis; file->spatial_axes[axis] = d; } else spatial_axis_indices[d] = INVALID_AXIS; spatial_dim_flags[d] = (spatial_axis_indices[d] != INVALID_AXIS); if( file->to_volume_index[d] != INVALID_AXIS ) { file->valid_file_axes[which_valid_axis] = d; if( spatial_dim_flags[d] ) { volume->spatial_axes[spatial_axis_indices[d]] = file->to_volume_index[d]; } ++which_valid_axis; } } /* --- get the spatial axis info, slice separation, start pos, etc. */ prev_space_type[0] = (char) 0; space_type_consensus = TRUE; for_less( d, 0, file->n_file_dimensions ) { file_separations[d] = 1.0; start_position[d] = 0.0; irr_starts[d] = NULL; irr_widths[d] = NULL; if( spatial_dim_flags[d] ) { dir_cosines[d][0] = 0.0; dir_cosines[d][1] = 0.0; dir_cosines[d][2] = 0.0; dir_cosines[d][spatial_axis_indices[d]] = 1.0; } dimvar = ncvarid( file->cdfid, file->dim_names[d] ); if( dimvar != MI_ERROR ) { (void) miattget1( file->cdfid, dimvar, MIstep, NC_DOUBLE, (void *) (&file_separations[d]) ); if( spatial_dim_flags[d] ) { if( miattget1( file->cdfid, dimvar, MIstart, NC_DOUBLE, (void *) (&start_position[d]) ) == MI_ERROR ) start_position[d] = 0.0; if( miattget( file->cdfid, dimvar, MIdirection_cosines, NC_DOUBLE, MI_NUM_SPACE_DIMS, (void *) tmp_cosines, (int *) NULL ) != MI_ERROR ) { dir_cosines[d][0] = tmp_cosines[0]; dir_cosines[d][1] = tmp_cosines[1]; dir_cosines[d][2] = tmp_cosines[2]; } ptr = miattgetstr( file->cdfid, dimvar, MIspacetype, MI_MAX_ATTSTR_LEN+1, space_type ); if( ptr != NULL ) { if( string_length( prev_space_type ) > 0 && string_length( space_type ) > 0 && !equal_strings( prev_space_type, space_type ) ) { space_type_consensus = FALSE; } if( string_length( space_type ) > 0 ) (void) strcpy( prev_space_type, space_type ); } } else if (!strcmp(MItime, file->dim_names[d])) { /* For the moment this is implemented for time dimensions * only. */ miattgetstr(file->cdfid, dimvar, MIspacing, MI_MAX_ATTSTR_LEN+1, spacing_type); if (!strcmp(spacing_type, MI_IRREGULAR)) { long start[1]; long count[1]; int i; irr_starts[d] = malloc(sizeof(Real) * file->sizes_in_file[d]); irr_widths[d] = malloc(sizeof(Real) * file->sizes_in_file[d]); start[0] = 0; count[0] = file->sizes_in_file[d]; mivarget(file->cdfid, dimvar, start, count, NC_DOUBLE, MI_SIGNED, irr_starts[d]); dimvar = ncvarid(file->cdfid, MItime_width); if (dimvar < 0) { for (i = 0; i < count[0]; i++) { irr_widths[d][i] = file_separations[d]; } } else { mivarget(file->cdfid, dimvar, start, count, NC_DOUBLE, MI_SIGNED, irr_widths[d]); } } else { if( miattget1(file->cdfid, dimvar, MIstart, NC_DOUBLE, (void *) (&start_position[d]) ) == MI_ERROR ) start_position[d] = 0.0; } } } if( file->to_volume_index[d] == INVALID_AXIS ) { file->n_volumes_in_file *= (int) file->sizes_in_file[d]; } else { sizes[file->to_volume_index[d]] = (int) file->sizes_in_file[d]; volume_separations[file->to_volume_index[d]] = file_separations[d]; if( file->to_volume_index[d] != INVALID_AXIS ) { volume_starts[file->to_volume_index[d]] = start_position[d]; set_volume_direction_unit_cosine( volume, file->to_volume_index[d], dir_cosines[d] ); } } } /* --- create the world transform stored in the volume */ set_volume_separations( volume, volume_separations ); set_volume_starts( volume, volume_starts ); if( space_type_consensus ) set_volume_space_type( volume, prev_space_type ); /* --- create the file world transform */ compute_world_transform( file->spatial_axes, file_separations, dir_cosines, start_position, &file->voxel_to_world_transform ); /* --- decide on type conversion */ if( file->converting_to_colour ) { converted_type = NC_FLOAT; converted_sign = FALSE; } else { no_volume_data_type = (get_volume_data_type(volume) == NO_DATA_TYPE); if( no_volume_data_type ) /* --- use type of file */ { if( miattgetstr( file->cdfid, file->img_var, MIsigntype, MI_MAX_ATTSTR_LEN, signed_flag ) != NULL ) { converted_sign = equal_strings( signed_flag, MI_SIGNED ); } else converted_sign = file_datatype != NC_BYTE; converted_type = file_datatype; set_volume_type( volume, converted_type, converted_sign, 0.0, 0.0 ); } else /* --- use specified type */ { converted_type = get_volume_nc_data_type( volume, &converted_sign ); } } set_volume_sizes( volume, sizes ); for_less( d, 0, file->n_file_dimensions ) { if (file->to_volume_index[d] == INVALID_AXIS) { continue; } if (irr_starts[d] != NULL) { set_volume_irregular_starts(volume, file->to_volume_index[d], file->sizes_in_file[d], irr_starts[d]); FREE( irr_starts[d] ); } if (irr_widths[d] != NULL) { set_volume_irregular_widths(volume, file->to_volume_index[d], file->sizes_in_file[d], irr_widths[d]); FREE( irr_widths[d] ); } } /* --- create the image conversion variable */ file->minc_icv = miicv_create(); (void) miicv_setint( file->minc_icv, MI_ICV_TYPE, (int) converted_type ); (void) miicv_setstr( file->minc_icv, MI_ICV_SIGN, converted_sign ? MI_SIGNED : MI_UNSIGNED ); (void) miicv_setint( file->minc_icv, MI_ICV_DO_NORM, TRUE ); (void) miicv_setint( file->minc_icv, MI_ICV_DO_FILLVALUE, TRUE ); get_volume_voxel_range( volume, &valid_range[0], &valid_range[1] ); range_specified = (valid_range[0] < valid_range[1]); valid_range[0] = 0.0; valid_range[1] = 0.0; if( file->converting_to_colour ) { valid_range[0] = 0.0; valid_range[1] = 2.0 * (double) (1ul << 31ul) - 1.0; set_volume_voxel_range( volume, valid_range[0], valid_range[1] ); } else if( no_volume_data_type ) { if (miget_valid_range( file->cdfid, file->img_var, valid_range) == MI_ERROR) { valid_range[0] = valid_range[1] = 0.0; } } if( !file->converting_to_colour && (no_volume_data_type || !range_specified) ) { set_volume_voxel_range( volume, valid_range[0], valid_range[1] ); } if( !file->converting_to_colour ) { get_volume_voxel_range( volume, &valid_range[0], &valid_range[1] ); (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MIN, valid_range[0]); (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MAX, valid_range[1]); } else { (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MIN, 0.0 ); (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MAX, 1.0 ); } if (options->user_real_range[0] < options->user_real_range[1]) { (void) miicv_setint( file->minc_icv, MI_ICV_USER_NORM, TRUE ); (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MIN, options->user_real_range[0] ); (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MAX, options->user_real_range[1] ); } if( options->convert_vector_to_scalar_flag && !file->converting_to_colour ) { (void) miicv_setint( file->minc_icv, MI_ICV_DO_DIM_CONV, TRUE ); (void) miicv_setint( file->minc_icv, MI_ICV_DO_SCALAR, TRUE ); (void) miicv_setint( file->minc_icv, MI_ICV_XDIM_DIR, FALSE ); (void) miicv_setint( file->minc_icv, MI_ICV_YDIM_DIR, FALSE ); (void) miicv_setint( file->minc_icv, MI_ICV_ZDIM_DIR, FALSE ); (void) miicv_setint( file->minc_icv, MI_ICV_KEEP_ASPECT, FALSE ); } (void) miicv_attach( file->minc_icv, file->cdfid, file->img_var ); /* --- compute the mapping to real values */ (void) miicv_inqdbl( file->minc_icv, MI_ICV_NORM_MIN, &real_min ); (void) miicv_inqdbl( file->minc_icv, MI_ICV_NORM_MAX, &real_max ); if( !file->converting_to_colour ) set_volume_real_range( volume, real_min, real_max ); /* --- if promoting invalid values to zero, then we need to detach and reattach in order to change the fillvalue in the icv */ if( options->promote_invalid_to_zero_flag ) { (void) miicv_detach( file->minc_icv ); if( !file->converting_to_colour ) { if( real_min == real_max ) voxel_zero = valid_range[0]; else if( real_min > 0.0 ) voxel_zero = valid_range[0]; else if( real_max < 0.0 ) voxel_zero = valid_range[1]; else { voxel_zero = valid_range[0] + (valid_range[1] - valid_range[0]) * (0.0 - real_min) / (real_max - real_min); } (void) miicv_setdbl( file->minc_icv, MI_ICV_FILLVALUE, voxel_zero ); } else (void) miicv_setdbl( file->minc_icv, MI_ICV_FILLVALUE, 0.0 ); (void) miicv_attach( file->minc_icv, file->cdfid, file->img_var ); } for_less( d, 0, file->n_file_dimensions ) file->indices[d] = 0; file->end_volume_flag = FALSE; ncopts = NC_VERBOSE | NC_FATAL; /* --- decide how many full dimensions to read in at a time to max out the read/write buffer and make it like the chunking dimensions for compression */ file->n_slab_dims = 0; slab_size = 1; int unit_size = get_type_size( get_volume_data_type(volume) ); int full_dim = 1; for( d = file->n_file_dimensions-1; d >= 0; d-- ) { if( file->to_volume_index[d] != INVALID_AXIS ) { if( MI_MAX_VAR_BUFFER_SIZE > file->sizes_in_file[d] * slab_size * unit_size && full_dim ) { slab_size *= file->sizes_in_file[d]; file->n_slab_dims++; /* integral number of complete dimensions */ } else { slab_size *= MIN( file->sizes_in_file[d], (size_t)( MI_MAX_VAR_BUFFER_SIZE / ( slab_size * unit_size ) ) ); full_dim = 0; } } } /* --- decide whether the volume data must be freed (if it changed size) */ different = FALSE; for_less( d, 0, n_vol_dims ) { if( sizes[d] != prev_sizes[d] ) different = TRUE; } if( prev_nc_type != converted_type ) different = TRUE; if( different && volume_is_alloced( volume ) && !volume_is_cached(volume) ) free_volume_data( volume ); return( file ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_minc_input @INPUT : filename volume @OUTPUT : @RETURNS : Minc_file @DESCRIPTION: Initializes the input of a MINC file, passing back a MINC file pointer. It assumes that the volume has been created, with the desired type, or MI_ORIGINAL_TYPE type if it is desired to use whatever type is in the file. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Minc_file initialize_minc_input( STRING filename, Volume volume, minc_input_options *options ) { Minc_file file; int minc_id; STRING expanded; ncopts = 0; expanded = expand_filename( filename ); minc_id = miopen( expanded, NC_NOWRITE ); if( minc_id == MI_ERROR ) { print_error( "Error: opening MINC file \"%s\".\n", expanded ); return( (Minc_file) 0 ); } file = initialize_minc_input_from_minc_id( minc_id, volume, options ); if( file == (Minc_file) NULL ) (void) miclose( minc_id ); else file->filename = create_string( expanded ); delete_string( expanded ); return( file ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_n_input_volumes @INPUT : file @OUTPUT : @RETURNS : number of input volumes @DESCRIPTION: After initializing the file input with a specified volume, the user calls this function to decide how many volumes are stored in the file. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_n_input_volumes( Minc_file file ) { return( file->n_volumes_in_file ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : close_minc_input @INPUT : file @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Closes the minc input file. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status close_minc_input( Minc_file file ) { int d; if( file == (Minc_file) NULL ) { print_error( "close_minc_input(): NULL file.\n" ); return( ERROR ); } (void) miclose( file->cdfid ); (void) miicv_free( file->minc_icv ); for_less( d, 0, file->n_file_dimensions ) delete_string( file->dim_names[d] ); delete_string( file->filename ); delete_general_transform( &file->voxel_to_world_transform ); FREE( file ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_minc_hyperslab @INPUT : file data_type n_array_dims array_sizes array_data_ptr to_array start count @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Inputs a hyperslab from the file into the array pointer. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_minc_hyperslab( Minc_file file, Data_types data_type, int n_array_dims, int array_sizes[], void *array_data_ptr, int to_array[], int start[], int count[] ) { Status status; int ind, expected_ind, file_ind, d, i, dim; int size0, size1, size2, size3, size4; int n_tmp_dims, n_file_dims; void *void_ptr; BOOLEAN direct_to_array, non_full_size_found; int tmp_ind, tmp_sizes[MAX_VAR_DIMS]; int vol1_indices[MAX_DIMENSIONS]; int v[MAX_DIMENSIONS], voxel[MAX_DIMENSIONS]; long used_start[MAX_VAR_DIMS], used_count[MAX_VAR_DIMS]; Real rgb[4]; Colour colour; multidim_array buffer_array, rgb_array; n_file_dims = file->n_file_dimensions; direct_to_array = TRUE; expected_ind = n_array_dims-1; tmp_ind = n_file_dims-1; non_full_size_found = FALSE; for_less( ind, 0, n_array_dims ) vol1_indices[ind] = -1; /*--- check if the hyperslab is a continuous chunk of memory in the array */ for( file_ind = n_file_dims-1; file_ind >= 0; --file_ind ) { used_start[file_ind] = (long) start[file_ind]; used_count[file_ind] = (long) count[file_ind]; ind = to_array[file_ind]; if( ind != INVALID_AXIS ) { if( !non_full_size_found && (long) count[file_ind] < file->sizes_in_file[file_ind] ) non_full_size_found = TRUE; else if( non_full_size_found && count[file_ind] > 1 ) direct_to_array = FALSE; if( count[file_ind] > 1 && ind != expected_ind ) direct_to_array = FALSE; if( count[file_ind] != 1 || file->sizes_in_file[file_ind] == 1 ) { tmp_sizes[tmp_ind] = count[file_ind]; vol1_indices[tmp_ind] = ind; --tmp_ind; } --expected_ind; } } if( !direct_to_array || file->converting_to_colour ) { /*--- make a temporary buffer array, so that there is a continuous chunk */ n_tmp_dims = n_file_dims - tmp_ind - 1; for_less( dim, 0, n_tmp_dims ) { tmp_sizes[dim] = tmp_sizes[dim+tmp_ind+1]; vol1_indices[dim] = vol1_indices[dim+tmp_ind+1]; } create_multidim_array( &buffer_array, n_tmp_dims, tmp_sizes, data_type); if( file->converting_to_colour ) { used_start[n_file_dims] = 0; used_count[n_file_dims] = file->sizes_in_file[n_file_dims]; tmp_sizes[n_tmp_dims] = (int) used_count[n_file_dims]; create_multidim_array( &rgb_array, n_tmp_dims+1, tmp_sizes, FLOAT ); GET_MULTIDIM_PTR( void_ptr, rgb_array, 0, 0, 0, 0, 0 ); } else { GET_MULTIDIM_PTR( void_ptr, buffer_array, 0, 0, 0, 0, 0 ); } } else { void_ptr = array_data_ptr; } if( miicv_get( file->minc_icv, used_start, used_count, void_ptr ) == MI_ERROR ) { status = ERROR; if( file->converting_to_colour ) delete_multidim_array( &rgb_array ); if( !direct_to_array || file->converting_to_colour ) delete_multidim_array( &buffer_array ); } else status = OK; if( status == OK && (!direct_to_array || file->converting_to_colour) ) { if( file->converting_to_colour ) { for_less( dim, n_tmp_dims, MAX_DIMENSIONS ) tmp_sizes[dim] = 1; size0 = tmp_sizes[0]; size1 = tmp_sizes[1]; size2 = tmp_sizes[2]; size3 = tmp_sizes[3]; size4 = tmp_sizes[4]; for_less( v[4], 0, size4 ) for_less( v[3], 0, size3 ) for_less( v[2], 0, size2 ) for_less( v[1], 0, size1 ) for_less( v[0], 0, size0 ) { for_less( d, 0, n_tmp_dims ) voxel[d] = v[d]; for_less( i, 0, 4 ) { if( file->rgba_indices[i] < 0 ) { if( i < 3 ) rgb[i] = 0.0; else rgb[i] = 1.0; } else { voxel[n_tmp_dims] = file->rgba_indices[i]; GET_MULTIDIM( rgb[i], (Real), rgb_array, voxel[0], voxel[1], voxel[2], voxel[3], voxel[4] ); } } colour = make_rgba_Colour_0_1( rgb[0], rgb[1], rgb[2], rgb[3] ); SET_MULTIDIM( buffer_array, voxel[0], voxel[1], voxel[2], voxel[3], voxel[4], colour ); } delete_multidim_array( &rgb_array ); } GET_MULTIDIM_PTR( void_ptr, buffer_array, 0, 0, 0, 0, 0 ); copy_multidim_data_reordered( get_type_size(data_type), array_data_ptr, n_array_dims, array_sizes, void_ptr, n_tmp_dims, tmp_sizes, tmp_sizes, vol1_indices, FALSE ); delete_multidim_array( &buffer_array ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_slab @INPUT : file volume start count @OUTPUT : @RETURNS : @DESCRIPTION: Inputs a multidimensional slab from the file and copies it into the appropriate part of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void input_slab( Minc_file file, Volume volume, int to_volume[], long start[], long count[] ) { int file_ind, ind; int volume_start[MAX_VAR_DIMS]; int file_start[MAX_DIMENSIONS]; int file_count[MAX_DIMENSIONS]; int array_sizes[MAX_DIMENSIONS]; void *array_data_ptr; for_less( file_ind, 0, file->n_file_dimensions ) { file_start[file_ind] = (int) start[file_ind]; file_count[file_ind] = (int) count[file_ind]; ind = to_volume[file_ind]; if( ind != INVALID_AXIS ) volume_start[ind] = file_start[file_ind]; else volume_start[ind] = 0; } get_multidim_sizes( &volume->array, array_sizes ); GET_MULTIDIM_PTR( array_data_ptr, volume->array, volume_start[0], volume_start[1], volume_start[2], volume_start[3], volume_start[4] ); (void) input_minc_hyperslab( file, get_multidim_data_type(&volume->array), get_multidim_n_dimensions(&volume->array), array_sizes, array_data_ptr, to_volume, file_start, file_count ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_more_minc_file @INPUT : file @OUTPUT : fraction_done - amount of file read @RETURNS : TRUE if volume has more left to read @DESCRIPTION: Reads another chunk from the input file, passes back the total fraction read so far, and returns FALSE when the whole volume has been read. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN input_more_minc_file( Minc_file file, Real *fraction_done ) { int d, ind, n_done, total, n_slab; long count[MAX_VAR_DIMS]; Volume volume; BOOLEAN increment; if( file->end_volume_flag ) { print_error( "End of file in input_more_minc_file()\n" ); return( FALSE ); } volume = file->volume; if( !volume_is_alloced( volume ) ) { alloc_volume_data( volume ); if( volume->is_cached_volume ) { open_cache_volume_input_file( &volume->cache, volume, file->filename, &file->original_input_options ); } if( !volume_is_alloced( volume ) ) return( FALSE ); } if( volume->is_cached_volume ) { *fraction_done = 1.0; file->end_volume_flag = TRUE; } else { /* --- set the counts for reading, actually these will be the same every time */ for_less( ind, 0, file->n_file_dimensions ) count[ind] = 1; n_slab = 0; for( d = file->n_file_dimensions-1; d >= 0 && n_slab < file->n_slab_dims; --d ) { if( file->to_volume_index[d] != INVALID_AXIS ) { count[d] = file->sizes_in_file[d]; ++n_slab; } } input_slab( file, volume, file->to_volume_index, file->indices, count ); /* --- advance to next slab */ increment = TRUE; n_slab = 0; total = 1; n_done = 0; for( d = file->n_file_dimensions-1; d >= 0; --d ) { if( n_slab >= file->n_slab_dims && file->to_volume_index[d] != INVALID_AXIS ) { if( increment ) { ++file->indices[d]; if( file->indices[d] < file->sizes_in_file[d] ) increment = FALSE; else file->indices[d] = 0; } n_done += total * (int) file->indices[d]; total *= (int) file->sizes_in_file[d]; } if( file->to_volume_index[d] != INVALID_AXIS ) ++n_slab; } if( increment ) { *fraction_done = 1.0; file->end_volume_flag = TRUE; } else { *fraction_done = (Real) n_done / (Real) total; } } return( !file->end_volume_flag ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : advance_input_volume @INPUT : file @OUTPUT : @RETURNS : TRUE if more volumes to read @DESCRIPTION: Advances the file indices to prepare for reading the next volume from the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN advance_input_volume( Minc_file file ) { int ind, c, axis; Real voxel[MAX_DIMENSIONS], world_space[N_DIMENSIONS]; Real vol_world_space[N_DIMENSIONS]; Transform offset; General_transform offset_transform, new_transform; ind = file->n_file_dimensions-1; while( ind >= 0 ) { if( file->to_volume_index[ind] == INVALID_AXIS ) { ++file->indices[ind]; if( file->indices[ind] < file->sizes_in_file[ind] ) break; file->indices[ind] = 0; } --ind; } if( ind >= 0 ) { file->end_volume_flag = FALSE; for_less( ind, 0, get_volume_n_dimensions( file->volume ) ) file->indices[file->valid_file_axes[ind]] = 0; /*--- update the volume's voxel-to-world transform */ for_less( c, 0, N_DIMENSIONS ) { axis = file->spatial_axes[c]; if( axis != INVALID_AXIS ) voxel[c] = (Real) file->indices[axis]; else voxel[c] = 0.0; } general_transform_point( &file->voxel_to_world_transform, voxel[0], voxel[1], voxel[2], &world_space[X], &world_space[Y], &world_space[Z]); for_less( c, 0, get_volume_n_dimensions(file->volume) ) voxel[c] = 0.0; convert_voxel_to_world( file->volume, voxel, &vol_world_space[X], &vol_world_space[Y], &vol_world_space[Z]); make_identity_transform( &offset ); for_less( c, 0, N_DIMENSIONS ) Transform_elem(offset,c,3) = world_space[c] - vol_world_space[c]; create_linear_transform( &offset_transform, &offset ); concat_general_transforms( get_voxel_to_world_transform(file->volume), &offset_transform, &new_transform ); set_voxel_to_world_transform( file->volume, &new_transform ); delete_general_transform( &offset_transform ); /*--- update the volume if it is cached */ if( file->volume->is_cached_volume ) set_cache_volume_file_offset( &file->volume->cache, file->volume, file->indices ); } else file->end_volume_flag = TRUE; return( file->end_volume_flag ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : reset_input_volume @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Rewinds the file indices to start inputting volumes from the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void reset_input_volume( Minc_file file ) { int d; for_less( d, 0, file->n_file_dimensions ) file->indices[d] = 0; file->end_volume_flag = FALSE; set_cache_volume_file_offset( &file->volume->cache, file->volume, file->indices ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : match_dimension_names @INPUT : n_volume_dims volume_dimension_names n_file_dims file_dimension_names @OUTPUT : to_volume_index @RETURNS : TRUE if match found @DESCRIPTION: Attempts to match all the volume dimensions with the file dimensions. This is done in 3 passes. In the first pass, exact matches are found. In the second pass, volume dimensions of "any_spatial_dimension" are matched. On the final pass, volume dimension names which are empty strings are matched to any remaining file dimensions. If a dimension matches on "any_spatial_dimension" or empty string, then the name from the file is copied to the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Oct. 22, 1995 D. MacDonald - copies the name from the file to the volume ---------------------------------------------------------------------------- */ static BOOLEAN match_dimension_names( int n_volume_dims, STRING volume_dimension_names[], int n_file_dims, STRING file_dimension_names[], int to_volume_index[] ) { int i, j, iteration, n_matches, dummy; int to_file_index[MAX_DIMENSIONS]; BOOLEAN match; BOOLEAN volume_dim_found[MAX_DIMENSIONS]; n_matches = 0; for_less( i, 0, n_file_dims ) to_volume_index[i] = INVALID_AXIS; for_less( i, 0, n_volume_dims ) { volume_dim_found[i] = FALSE; to_file_index[i] = -1; } for_less( iteration, 0, 3 ) { for( i = n_volume_dims-1; i >= 0; --i ) { if( !volume_dim_found[i] ) { for( j = n_file_dims-1; j >= 0; --j ) { if( to_volume_index[j] == INVALID_AXIS ) { switch( iteration ) { case 0: match = equal_strings( volume_dimension_names[i], file_dimension_names[j] ); break; case 1: match = equal_strings( volume_dimension_names[i], ANY_SPATIAL_DIMENSION ) && convert_dim_name_to_spatial_axis( file_dimension_names[j], &dummy ); break; case 2: match = string_length(volume_dimension_names[i]) == 0; break; } if( match ) { to_volume_index[j] = i; to_file_index[i] = j; volume_dim_found[i] = TRUE; ++n_matches; break; } } } } } } if( n_matches == n_volume_dims ) { for_less( i, 0, n_volume_dims ) { if( equal_strings( volume_dimension_names[i], ANY_SPATIAL_DIMENSION ) || string_length(volume_dimension_names[i]) == 0 ) { replace_string( &volume_dimension_names[i], create_string( file_dimension_names[to_file_index[i]] ) ); } } } return( n_matches == n_volume_dims ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_minc_file_id @INPUT : file @OUTPUT : @RETURNS : minc file id @DESCRIPTION: Returns the minc file id to allow user to perform MINC calls on this file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_minc_file_id( Minc_file file ) { return( file->cdfid ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_default_minc_input_options @INPUT : @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the default minc input options. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_default_minc_input_options( minc_input_options *options ) { static int default_rgba_indices[4] = { 0, 1, 2, 3 }; set_minc_input_promote_invalid_to_zero_flag( options, TRUE ); set_minc_input_vector_to_scalar_flag( options, TRUE ); set_minc_input_vector_to_colour_flag( options, FALSE ); set_minc_input_colour_dimension_size( options, 3 ); set_minc_input_colour_max_dimension_size( options, 4 ); set_minc_input_colour_indices( options, default_rgba_indices ); set_minc_input_user_real_range(options, 0.0, 0.0); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_promote_invalid_to_zero_flag @INPUT : flag @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the invalid promotion flag of the input options. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Oct. 25, 1996 D. MacDonald - changed to promote to 0, used to be min_valid ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_promote_invalid_to_zero_flag( minc_input_options *options, BOOLEAN flag ) { options->promote_invalid_to_zero_flag = flag; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_promote_invalid_to_zero_flag @INPUT : flag @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the invalid promotion flag of the input options. Maintained for functional interface backward compatibility. Programmers should now be calling set_minc_input_promote_invalid_to_zero_flag. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Oct. 25, 1996 D. MacDonald - replaced with above function ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_promote_invalid_to_min_flag( minc_input_options *options, BOOLEAN flag ) { set_minc_input_promote_invalid_to_zero_flag( options, flag ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_vector_to_scalar_flag @INPUT : flag @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the vector conversion flag of the input options. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_vector_to_scalar_flag( minc_input_options *options, BOOLEAN flag ) { options->convert_vector_to_scalar_flag = flag; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_vector_to_colour_flag @INPUT : flag @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the colour conversion flag of the input options. Any volume with a vector dimension of length 3 will be converted to a 32 bit colour. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_vector_to_colour_flag( minc_input_options *options, BOOLEAN flag ) { options->convert_vector_to_colour_flag = flag; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_colour_dimension_size @INPUT : size @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the required number of vector components in a file that contains colour data. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_colour_dimension_size( minc_input_options *options, int size ) { if( size > 0 ) options->dimension_size_for_colour_data = size; else { print_error( "Warning: set_minc_input_colour_dimension_size:\n" ); print_error( " illegal size: %d\n", size ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_colour_max_dimension_size @INPUT : size @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the maximum number of vector components in a file that contains colour data. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_colour_max_dimension_size( minc_input_options *options, int size ) { if( size > 0 ) options->max_dimension_size_for_colour_data = size; else { print_error( "Warning: set_minc_input_colour_max_dimension_size:\n" ); print_error( " illegal size: %d\n", size ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_colour_indices @INPUT : indices @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the indices of the red, green, blue, and alpha in files that contain colours as the vector dimension. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_colour_indices( minc_input_options *options, int indices[4] ) { int i; for_less( i, 0, 4 ) options->rgba_indices[i] = indices[i]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_input_user_real_range @INPUT : minimum, maximum - real range for scaling of input @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the user-defined real range for scaling input when the Volume type is integer. The max must be greater than the min for this option to take effect. Setting this will force the Volume to have a particular real range, rather than using the full range of the input file. @METHOD : @GLOBALS : @CALLS : @CREATED : 2001 Peter Neelin @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_input_user_real_range( minc_input_options *options, double minimum, double maximum ) { options->user_real_range[0] = minimum; options->user_real_range[1] = maximum; } minc-2.2.00/volume_io/Volumes/input_volume.c0000644000265600003100000002253412027132664015772 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #define FREE_ENDING "fre" /* ----------------------------- MNI Header ----------------------------------- @NAME : start_volume_input @INPUT : filename - file to input dim_names - names of dimensions, or null convert_to_byte_flag - whether to convert volume data to byte @OUTPUT : volume - the volume data input_info - information for use while inputting @RETURNS : OK if successful @DESCRIPTION: Opens the file and reads the header, but does not read any volume data yet. Allocates the data also. Note: if you wish to modify the volume file input routines, then look at the new_C_dev/Include/volume.h for the description of Volum and volume_input_struct. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status start_volume_input( STRING filename, int n_dimensions, STRING dim_names[], nc_type volume_nc_data_type, BOOLEAN volume_signed_flag, Real volume_voxel_min, Real volume_voxel_max, BOOLEAN create_volume_flag, Volume *volume, minc_input_options *options, volume_input_struct *input_info ) { Status status; int d; STRING expanded_filename; status = OK; if( create_volume_flag || *volume == (Volume) NULL ) { if( n_dimensions < 1 || n_dimensions > MAX_DIMENSIONS ) n_dimensions = get_minc_file_n_dimensions( filename ); if( n_dimensions < 1 ) return( ERROR ); if( dim_names == (STRING *) NULL ) dim_names = get_default_dim_names( n_dimensions ); *volume = create_volume( n_dimensions, dim_names, volume_nc_data_type, volume_signed_flag, volume_voxel_min, volume_voxel_max ); } else if( n_dimensions != get_volume_n_dimensions( *volume ) && volume_is_alloced( *volume ) ) free_volume_data( *volume ); expanded_filename = expand_filename( filename ); if( !filename_extension_matches( expanded_filename, FREE_ENDING ) ) input_info->file_format = MNC_FORMAT; else input_info->file_format = FREE_FORMAT; switch( input_info->file_format ) { case MNC_FORMAT: if( !file_exists( expanded_filename ) ) { (void) file_exists_as_compressed( expanded_filename, &expanded_filename ); } input_info->minc_file = initialize_minc_input( expanded_filename, *volume, options ); if( input_info->minc_file == (Minc_file) NULL ) status = ERROR; else { for_less( d, 0, MAX_DIMENSIONS ) input_info->axis_index_from_file[d] = d; } break; case FREE_FORMAT: status = initialize_free_format_input( expanded_filename, *volume, input_info ); break; } if( status != OK && create_volume_flag ) delete_volume( *volume ); delete_string( expanded_filename ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_volume_input @INPUT : input_info @OUTPUT : @RETURNS : @DESCRIPTION: Frees up any memory allocated for the volume input, i.e., any temporary_buffer. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void delete_volume_input( volume_input_struct *input_info ) { switch( input_info->file_format ) { case MNC_FORMAT: (void) close_minc_input( input_info->minc_file ); break; case FREE_FORMAT: delete_free_format_input( input_info ); break; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_more_of_volume @INPUT : volume input_info @OUTPUT : fraction_done - number between 0 and 1 @RETURNS : TRUE - if there is remains more to input after this call @DESCRIPTION: Reads in more of the volume file. This routine is provided, rather than a read_entire_volume(), so that programs can multiprocess loading with other tasks. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN input_more_of_volume( Volume volume, volume_input_struct *input_info, Real *fraction_done ) { BOOLEAN more_to_do; switch( input_info->file_format ) { case MNC_FORMAT: more_to_do = input_more_minc_file( input_info->minc_file, fraction_done ); break; case FREE_FORMAT: more_to_do = input_more_free_format_file( volume, input_info, fraction_done ); break; } return( more_to_do ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : cancel_volume_input @INPUT : volume input_info @OUTPUT : @RETURNS : @DESCRIPTION: Cancels loading the volume. Merely deletes the volume, then deletes the input buffer. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void cancel_volume_input( Volume volume, volume_input_struct *input_info ) { delete_volume( volume ); delete_volume_input( input_info ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : input_volume @INPUT : filename dim_names convert_to_byte_flag @OUTPUT : volume @RETURNS : OK if loaded alright @DESCRIPTION: Inputs the entire volume. @CREATED : David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status input_volume( STRING filename, int n_dimensions, STRING dim_names[], nc_type volume_nc_data_type, BOOLEAN volume_signed_flag, Real volume_voxel_min, Real volume_voxel_max, BOOLEAN create_volume_flag, Volume *volume, minc_input_options *options ) { Status status; Real amount_done; volume_input_struct input_info; progress_struct progress; static const int FACTOR = 1000; status = start_volume_input( filename, n_dimensions, dim_names, volume_nc_data_type, volume_signed_flag, volume_voxel_min, volume_voxel_max, create_volume_flag, volume, options, &input_info ); if( status == OK ) { initialize_progress_report( &progress, FALSE, FACTOR, "Reading Volume"); while( input_more_of_volume( *volume, &input_info, &amount_done ) ) { update_progress_report( &progress, ROUND( (Real) FACTOR * amount_done)); } terminate_progress_report( &progress ); delete_volume_input( &input_info ); if( !volume_is_alloced( *volume ) ) { delete_volume( *volume ); *volume = NULL; status = ERROR; } } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_input_minc_file @INPUT : volume_input @OUTPUT : @RETURNS : Minc_file @DESCRIPTION: Returns the minc file attached to a particular volume input structure. @METHOD : @GLOBALS : @CALLS : @CREATED : Jun 15, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Minc_file get_volume_input_minc_file( volume_input_struct *volume_input ) { return( volume_input->minc_file ); } minc-2.2.00/volume_io/Volumes/multidim_arrays.c0000644000265600003100000005074012027132664016451 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include /* ----------------------------- MNI Header ----------------------------------- @NAME : create_empty_multidim_array @INPUT : n_dimensions data_type @OUTPUT : array @RETURNS : @DESCRIPTION: Creates a multidimensional array, without allocating its data. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_empty_multidim_array( multidim_array *array, int n_dimensions, Data_types data_type ) { if( n_dimensions < 1 || n_dimensions > MAX_DIMENSIONS ) { print_error( "create_empty_multidim_array(): n_dimensions (%d) not in range 1 to %d.\n", n_dimensions, MAX_DIMENSIONS ); } array->n_dimensions = n_dimensions; array->data_type = data_type; array->data = (void *) NULL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_multidim_data_type @INPUT : array @OUTPUT : @RETURNS : data type @DESCRIPTION: Returns the data type of the multidimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Data_types get_multidim_data_type( multidim_array *array ) { return( array->data_type ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_multidim_data_type @INPUT : array data_type @OUTPUT : @RETURNS : @DESCRIPTION: Sets the data type of the array. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_multidim_data_type( multidim_array *array, Data_types data_type ) { array->data_type = data_type; } /* ---------------------------------------------------------------------------- @NAME : get_type_size @INPUT : type @OUTPUT : @RETURNS : size of the type @DESCRIPTION: Returns the size of the given type. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_type_size( Data_types type ) { int size; switch( type ) { case UNSIGNED_BYTE: size = sizeof( unsigned char ); break; case SIGNED_BYTE: size = sizeof( signed char ); break; case UNSIGNED_SHORT: size = sizeof( unsigned short ); break; case SIGNED_SHORT: size = sizeof( signed short ); break; case UNSIGNED_INT: size = sizeof( unsigned int ); break; case SIGNED_INT: size = sizeof( signed int ); break; case FLOAT: size = sizeof( float ); break; case DOUBLE: size = sizeof( double ); break; } return( size ); } VIOAPI void get_type_range( Data_types type, Real *min_value, Real *max_value ) { switch( type ) { case UNSIGNED_BYTE: *min_value = 0.0; *max_value = (Real) UCHAR_MAX; break; case SIGNED_BYTE: *min_value = (Real) SCHAR_MIN; *max_value = (Real) SCHAR_MAX; break; case UNSIGNED_SHORT: *min_value = 0.0; *max_value = (Real) USHRT_MAX; break; case SIGNED_SHORT: *min_value = (Real) SHRT_MIN; *max_value = (Real) SHRT_MAX; break; case UNSIGNED_INT: *min_value = 0.0; *max_value = (Real) UINT_MAX; break; case SIGNED_INT: *min_value = (Real) INT_MIN; *max_value = (Real) INT_MAX; break; case FLOAT: *min_value = (Real) -FLT_MAX; *max_value = (Real) FLT_MAX; break; case DOUBLE: *min_value = (Real) -DBL_MAX; *max_value = (Real) DBL_MAX; break; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_multidim_sizes @INPUT : array sizes @OUTPUT : @RETURNS : @DESCRIPTION: Sets the sizes of the array. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_multidim_sizes( multidim_array *array, int sizes[] ) { int dim; for_less( dim, 0, array->n_dimensions ) array->sizes[dim] = sizes[dim]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_multidim_sizes @INPUT : array @OUTPUT : sizes @RETURNS : @DESCRIPTION: Passes back the sizes of the multidimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_multidim_sizes( multidim_array *array, int sizes[] ) { int i; for_less( i, 0, array->n_dimensions ) sizes[i] = array->sizes[i]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : multidim_array_is_alloced @INPUT : array @OUTPUT : @RETURNS : TRUE if array is allocated @DESCRIPTION: @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN multidim_array_is_alloced( multidim_array *array ) { BOOLEAN status = FALSE; void **p1, ***p2, ****p3, *****p4, ******p5; if( array == NULL ) return( FALSE ); switch( array->n_dimensions ) { case 1: p1 = (void **)&array->data; status = ( *p1 != NULL ); break; case 2: p2 = (void ***)&array->data; if( *p2 == NULL ) break; if( **p2 == NULL ) break; status = TRUE; break; case 3: p3 = (void ****)&array->data; if( *p3 == NULL ) break; if( **p3 == NULL ) break; if( ***p3 == NULL ) break; status = TRUE; break; case 4: p4 = (void *****)&array->data; if( *p4 == NULL ) break; if( **p4 == NULL ) break; if( ***p4 == NULL ) break; if( ****p4 == NULL ) break; status = TRUE; break; case 5: p5 = (void ******)&array->data; if( *p5 == NULL ) break; if( **p5 == NULL ) break; if( ***p5 == NULL ) break; if( ****p5 == NULL ) break; if( *****p5 == NULL ) break; status = TRUE; break; } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_multidim_array @INPUT : array @OUTPUT : @RETURNS : @DESCRIPTION: Allocates the data for the multidimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void alloc_multidim_array( multidim_array *array ) { int dim; size_t type_size, sizes[5]; void *p1, **p2, ***p3, ****p4, *****p5; if( multidim_array_is_alloced( array ) ) delete_multidim_array( array ); if( array->data_type == NO_DATA_TYPE ) { print_error( "Error: cannot allocate array data until size specified.\n" ); return; } for_less( dim, 0, array->n_dimensions ) sizes[dim] = (size_t) array->sizes[dim]; type_size = (size_t) get_type_size( array->data_type ); switch( array->n_dimensions ) { case 1: ASSIGN_PTR(p1) = alloc_memory_1d( sizes[0], type_size _ALLOC_SOURCE_LINE ); array->data = (void *) p1; break; case 2: ASSIGN_PTR(p2) = alloc_memory_2d( sizes[0], sizes[1], type_size _ALLOC_SOURCE_LINE); array->data = (void *) p2; break; case 3: ASSIGN_PTR(p3) = alloc_memory_3d( sizes[0], sizes[1], sizes[2], type_size _ALLOC_SOURCE_LINE ); array->data = (void *) p3; break; case 4: ASSIGN_PTR(p4) = alloc_memory_4d( sizes[0], sizes[1], sizes[2], sizes[3], type_size _ALLOC_SOURCE_LINE ); array->data = (void *) p4; break; case 5: ASSIGN_PTR(p5) = alloc_memory_5d( sizes[0], sizes[1], sizes[2], sizes[3], sizes[4], type_size _ALLOC_SOURCE_LINE ); array->data = (void *) p5; break; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_multidim_array @INPUT : array n_dimensions sizes data_type @OUTPUT : @RETURNS : @DESCRIPTION: Creates a multidimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void create_multidim_array( multidim_array *array, int n_dimensions, int sizes[], Data_types data_type ) { create_empty_multidim_array( array, n_dimensions, data_type ); set_multidim_sizes( array, sizes ); alloc_multidim_array( array ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_multidim_array @INPUT : array @OUTPUT : @RETURNS : @DESCRIPTION: Deletes the multidimensional array. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void delete_multidim_array( multidim_array *array ) { if( array->data == NULL ) { print_error( "Warning: cannot free NULL multidim data.\n" ); return; } switch( array->n_dimensions ) { case 1: free_memory_1d( (void **) &array->data _ALLOC_SOURCE_LINE ); break; case 2: free_memory_2d( (void ***) &array->data _ALLOC_SOURCE_LINE ); break; case 3: free_memory_3d( (void ****) &array->data _ALLOC_SOURCE_LINE ); break; case 4: free_memory_4d( (void *****) &array->data _ALLOC_SOURCE_LINE ); break; case 5: free_memory_5d( (void ******) &array->data _ALLOC_SOURCE_LINE ); break; } array->data = NULL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_multidim_n_dimensions @INPUT : array @OUTPUT : @RETURNS : number of dimensions @DESCRIPTION: Returns the number of dimensions of the array @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_multidim_n_dimensions( multidim_array *array ) { return( array->n_dimensions ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_multidim_data_reordered @INPUT : type_size void_dest_ptr n_dest_dims dest_sizes void_src_ptr n_src_dims src_sizes counts to_dest_index use_src_order - whether to step through arrays in the reverse order of src or dest @OUTPUT : @RETURNS : @DESCRIPTION: Copies any type of multidimensional data from the src array to the destination array. to_dest_index is a lookup that converts src indices to destination indices, to allow arbitrary reordering of array data. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : Feb. 27, 1996 D. MacDonald - made more efficient ---------------------------------------------------------------------------- */ VIOAPI void copy_multidim_data_reordered( int type_size, void *void_dest_ptr, int n_dest_dims, int dest_sizes[], void *void_src_ptr, int n_src_dims, int src_sizes[], int counts[], int to_dest_index[], BOOLEAN use_src_order ) { char *src_ptr, *dest_ptr; int d; int dest_offsets[MAX_DIMENSIONS], src_offsets[MAX_DIMENSIONS]; int dest_offset0, dest_offset1, dest_offset2, dest_offset3; int dest_offset4; int src_offset0, src_offset1, src_offset2, src_offset3; int src_offset4; int dest_steps[MAX_DIMENSIONS], src_steps[MAX_DIMENSIONS]; int dest_index; int n_transfer_dims; int src_axis[MAX_DIMENSIONS], dest_axis[MAX_DIMENSIONS]; int transfer_counts[MAX_DIMENSIONS]; int v0, v1, v2, v3, v4; int size0, size1, size2, size3, size4; BOOLEAN full_count_used; /*--- initialize dest */ dest_ptr = (char *) void_dest_ptr; dest_steps[n_dest_dims-1] = type_size; for_down( d, n_dest_dims-2, 0 ) dest_steps[d] = dest_steps[d+1] * dest_sizes[d+1]; /*--- initialize src */ src_ptr = (char *) void_src_ptr; src_steps[n_src_dims-1] = type_size; for_down( d, n_src_dims-2, 0 ) src_steps[d] = src_steps[d+1] * src_sizes[d+1]; n_transfer_dims = 0; if( getenv( "VOLUME_IO_SRC_ORDER" ) ) use_src_order = TRUE; else if( getenv( "VOLUME_IO_DEST_ORDER" ) ) use_src_order = FALSE; if( use_src_order ) { for_less( d, 0, n_src_dims ) { dest_index = to_dest_index[d]; if( dest_index >= 0 ) { src_axis[n_transfer_dims] = d; dest_axis[n_transfer_dims] = dest_index; src_offsets[n_transfer_dims] = src_steps[d]; dest_offsets[n_transfer_dims] = dest_steps[dest_index]; transfer_counts[n_transfer_dims] = counts[d]; ++n_transfer_dims; } } } else { for_less( dest_index, 0, n_dest_dims ) { for_less( d, 0, n_src_dims ) if( to_dest_index[d] == dest_index ) break; if( d < n_src_dims ) { src_axis[n_transfer_dims] = d; dest_axis[n_transfer_dims] = dest_index; src_offsets[n_transfer_dims] = src_steps[d]; dest_offsets[n_transfer_dims] = dest_steps[dest_index]; transfer_counts[n_transfer_dims] = counts[d]; ++n_transfer_dims; } } } /*--- check if we can transfer more than one at once */ full_count_used = TRUE; while( n_transfer_dims > 0 && src_axis[n_transfer_dims-1] == n_src_dims-1 && dest_axis[n_transfer_dims-1] == n_dest_dims-1 && full_count_used ) { if( transfer_counts[n_transfer_dims-1] != src_sizes[n_src_dims-1] || transfer_counts[n_transfer_dims-1] != dest_sizes[n_dest_dims-1] ) { full_count_used = FALSE; } type_size *= transfer_counts[n_transfer_dims-1]; --n_src_dims; --n_dest_dims; --n_transfer_dims; } for_less( d, 0, n_transfer_dims-1 ) { src_offsets[d] -= src_offsets[d+1] * transfer_counts[d+1]; dest_offsets[d] -= dest_offsets[d+1] * transfer_counts[d+1]; } /*--- slide the transfer dims to the last of the 5 dimensions */ for_down( d, n_transfer_dims-1, 0 ) { src_offsets[d+MAX_DIMENSIONS-n_transfer_dims] = src_offsets[d]; dest_offsets[d+MAX_DIMENSIONS-n_transfer_dims] = dest_offsets[d]; transfer_counts[d+MAX_DIMENSIONS-n_transfer_dims] = transfer_counts[d]; } for_less( d, 0, MAX_DIMENSIONS-n_transfer_dims ) { transfer_counts[d] = 1; src_offsets[d] = 0; dest_offsets[d] = 0; } size0 = transfer_counts[0]; size1 = transfer_counts[1]; size2 = transfer_counts[2]; size3 = transfer_counts[3]; size4 = transfer_counts[4]; src_offset0 = src_offsets[0]; src_offset1 = src_offsets[1]; src_offset2 = src_offsets[2]; src_offset3 = src_offsets[3]; src_offset4 = src_offsets[4]; dest_offset0 = dest_offsets[0]; dest_offset1 = dest_offsets[1]; dest_offset2 = dest_offsets[2]; dest_offset3 = dest_offsets[3]; dest_offset4 = dest_offsets[4]; for_less( v0, 0, size0 ) { for_less( v1, 0, size1 ) { for_less( v2, 0, size2 ) { for_less( v3, 0, size3 ) { for_less( v4, 0, size4 ) { (void) memcpy( dest_ptr, src_ptr, (size_t) type_size ); src_ptr += src_offset4; dest_ptr += dest_offset4; } src_ptr += src_offset3; dest_ptr += dest_offset3; } src_ptr += src_offset2; dest_ptr += dest_offset2; } src_ptr += src_offset1; dest_ptr += dest_offset1; } src_ptr += src_offset0; dest_ptr += dest_offset0; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_multidim_reordered @INPUT : dest dest_ind src src_ind counts to_dest_index @OUTPUT : @RETURNS : @DESCRIPTION: Copies data from src array to dest array, with dimension translation given by to_dest_index[]. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void copy_multidim_reordered( multidim_array *dest, int dest_ind[], multidim_array *src, int src_ind[], int counts[], int to_dest_index[] ) { int n_src_dims, n_dest_dims, type_size; int src_sizes[MAX_DIMENSIONS], dest_sizes[MAX_DIMENSIONS]; char *dest_ptr, *src_ptr; void *void_ptr; type_size = get_type_size( get_multidim_data_type(dest) ); /*--- initialize dest */ n_dest_dims = get_multidim_n_dimensions( dest ); get_multidim_sizes( dest, dest_sizes ); GET_MULTIDIM_PTR( void_ptr, *dest, dest_ind[0], dest_ind[1], dest_ind[2], dest_ind[3], dest_ind[4] ); ASSIGN_PTR( dest_ptr ) = void_ptr; /*--- initialize src */ n_src_dims = get_multidim_n_dimensions( src ); get_multidim_sizes( src, src_sizes ); GET_MULTIDIM_PTR( void_ptr, *src, src_ind[0], src_ind[1], src_ind[2], src_ind[3], src_ind[4] ); ASSIGN_PTR( src_ptr ) = void_ptr; copy_multidim_data_reordered( type_size, dest_ptr, n_dest_dims, dest_sizes, src_ptr, n_src_dims, src_sizes, counts, to_dest_index, TRUE ); } minc-2.2.00/volume_io/Volumes/output_mnc.c0000644000265600003100000016153412027132664015445 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #define INVALID_AXIS -1 #define UNITS "mm" static Status get_dimension_ordering( int n_vol_dims, STRING vol_dim_names[], int n_file_dims, STRING file_dim_names[], int to_volume[], int to_file[] ); /* ----------------------------- MNI Header ----------------------------------- @NAME : is_default_direction_cosine @INPUT : axis dir_cosines @OUTPUT : @RETURNS : TRUE if is default @DESCRIPTION: Checks to see if the cosine is the default for the axis, i.e., for x axis, is it ( 1, 0, 0 ). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static BOOLEAN is_default_direction_cosine( int axis, double dir_cosines[] ) { BOOLEAN is_default; int i; is_default = TRUE; for_less( i, 0, N_DIMENSIONS ) { if( i == axis && dir_cosines[i] != 1.0 || i != axis && dir_cosines[i] != 0.0 ) { is_default = FALSE; break; } } return( is_default ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_world_transform @INPUT : file space_type voxel_to_world_transform @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Outputs the voxel to world transformation, in terms of MINC starts, steps, and direction cosines. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 24, 1995 David MacDonald @MODIFIED : Nov. 15, 1996 D. MacDonald - added handling of space type @MODIFIED : May. 20, 1997 D. MacDonald - removed float arithmetic @MODIFIED : May 22, 1997 D. MacDonald - added use_volume_starts_and_steps ---------------------------------------------------------------------------- */ static Status output_world_transform( Minc_file file, STRING space_type, General_transform *voxel_to_world_transform, BOOLEAN use_volume_starts_and_steps_flag ) { double step[MAX_VAR_DIMS]; Real start[MAX_VAR_DIMS]; double dir_cosines[MAX_DIMENSIONS][N_DIMENSIONS]; int dim, axis, spatial_axes[N_DIMENSIONS]; /*--- set all starts/steps/dir_cosines to default */ for_less( dim, 0, file->n_file_dimensions ) { start[dim] = 0.0; step[dim] = 1.0; dir_cosines[dim][X] = 0.0; dir_cosines[dim][Y] = 0.0; dir_cosines[dim][Z] = 0.0; } /*--- if must use the volume's starts and steps */ if( use_volume_starts_and_steps_flag ) { for_less( dim, 0, file->n_file_dimensions ) { if( convert_dim_name_to_spatial_axis( file->dim_names[dim], &axis )) { if( file->to_volume_index[dim] == INVALID_AXIS ) dir_cosines[dim][axis] = 1.0; /*--- default */ else { start[dim] = file->volume->starts[file->to_volume_index[dim]]; step[dim] = file->volume->separations[file->to_volume_index[dim]]; dir_cosines[dim][X] = file->volume->direction_cosines [file->to_volume_index[dim]][X]; dir_cosines[dim][Y] = file->volume->direction_cosines [file->to_volume_index[dim]][Y]; dir_cosines[dim][Z] = file->volume->direction_cosines [file->to_volume_index[dim]][Z]; } } } } else /*--- convert the linear transform to starts/steps/dir cosines */ { if( voxel_to_world_transform == NULL || get_transform_type( voxel_to_world_transform ) != LINEAR ) { print_error( "Cannot output null or non-linear transforms. Using identity.\n"); for_less( dim, 0, file->n_file_dimensions ) { if( convert_dim_name_to_spatial_axis( file->dim_names[dim], &axis )) dir_cosines[dim][axis] = 1.0; } } else { spatial_axes[0] = INVALID_AXIS; spatial_axes[1] = INVALID_AXIS; spatial_axes[2] = INVALID_AXIS; for_less( dim, 0, file->n_file_dimensions ) { if( convert_dim_name_to_spatial_axis( file->dim_names[dim], &axis )) spatial_axes[axis] = dim; } convert_transform_to_starts_and_steps( voxel_to_world_transform, file->n_file_dimensions, NULL, spatial_axes, start, step, dir_cosines ); } } for_less( dim, 0, file->n_file_dimensions ) { if( convert_dim_name_to_spatial_axis( file->dim_names[dim], &axis ) ) { file->dim_ids[dim] = micreate_std_variable( file->cdfid, file->dim_names[dim], NC_DOUBLE, 0, NULL); if( file->dim_ids[dim] < 0 ) return( ERROR ); (void) miattputdbl( file->cdfid, file->dim_ids[dim], MIstep, step[dim]); (void) miattputdbl( file->cdfid, file->dim_ids[dim], MIstart, start[dim]); if( !is_default_direction_cosine( axis, dir_cosines[dim] ) ) { (void) ncattput( file->cdfid, file->dim_ids[dim], MIdirection_cosines, NC_DOUBLE, N_DIMENSIONS, dir_cosines[dim]); } (void) miattputstr( file->cdfid, file->dim_ids[dim], MIunits, UNITS ); if( !equal_strings( space_type, MI_UNKNOWN_SPACE ) ) { (void) miattputstr( file->cdfid, file->dim_ids[dim], MIspacetype, space_type ); } } else file->dim_ids[dim] = -1; } return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_image_variable @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Defines the image variable in the output minc file. This should be done as the last thing before ending the header definition. @METHOD : @GLOBALS : @CALLS : @CREATED : September 13, 2001 Peter Neelin @MODIFIED : ---------------------------------------------------------------------------- */ static void create_image_variable(Minc_file file) { int old_ncopts; old_ncopts = ncopts; /* Create the variable */ file->img_var_id = micreate_std_variable( file->cdfid, MIimage, file->nc_data_type, file->n_file_dimensions, file->image_dims ); /* Copy all attributes if required */ if( file->src_img_var != MI_ERROR ) { ncopts = 0; (void) micopy_all_atts( file->src_cdfid, file->src_img_var, file->cdfid, file->img_var_id ); (void) ncattdel( file->cdfid, file->img_var_id, MIvalid_max ); (void) ncattdel( file->cdfid, file->img_var_id, MIvalid_min ); (void) ncattdel( file->cdfid, file->img_var_id, MIvalid_range ); ncopts = old_ncopts; } (void) miattputstr( file->cdfid, file->img_var_id, MIcomplete, MI_FALSE ); if( file->signed_flag ) (void) miattputstr( file->cdfid, file->img_var_id, MIsigntype, MI_SIGNED ); else (void) miattputstr( file->cdfid, file->img_var_id, MIsigntype, MI_UNSIGNED ); /* --- put the valid voxel range */ if( file->valid_range[0] < file->valid_range[1] ) { (void) miset_valid_range( file->cdfid, file->img_var_id, file->valid_range); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : end_file_def @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Ends the definition of the file, calling ncendef, but first creating the image variable as the last variable in the file. This is done to allow images > 2 GB (on 64-bit machines) and to ensure that data is written right to the end of the file for backwards compatibility. @METHOD : @GLOBALS : @CALLS : @CREATED : September 13, 2001 Peter Neelin @MODIFIED : ---------------------------------------------------------------------------- */ static Status end_file_def(Minc_file file) { int ret; create_image_variable(file); ret = ncendef( file->cdfid ); return ( ret == MI_ERROR ? ERROR : OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_minc_output @INPUT : filename n_dimensions dim_names sizes file_nc_data_type file_signed_flag file_voxel_min file_voxel_max voxel_to_world_transform volume_to_attach options @OUTPUT : @RETURNS : minc file @DESCRIPTION: Creates a minc file for outputting volumes. The n_dimensions, dim_names, sizes, file_nc_data_type, file_signed_flag, file_voxel_min, file_voxel_max, and voxel_to_world_transform define the type and shape of the file. The volume_to_attach is the volume that will be output once or many times to fill up the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Nov. 15, 1996 D. MacDonald - added handling of space type @MODIFIED : Nov. 2, 1998 D. MacDonald - fixed the bug with non-global limits on multiple volumes, found by peter ---------------------------------------------------------------------------- */ VIOAPI Minc_file initialize_minc_output( STRING filename, int n_dimensions, STRING dim_names[], int sizes[], nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, General_transform *voxel_to_world_transform, Volume volume_to_attach, minc_output_options *options ) { minc_file_struct *file; int volume_sizes[MAX_DIMENSIONS]; int n_volume_dims; int d, vol_index, n_range_dims; static STRING default_dim_names[] = { MIzspace, MIyspace, MIxspace }; STRING *vol_dimension_names; minc_output_options default_options; if( options == (minc_output_options *) NULL ) { set_default_minc_output_options( &default_options ); options = &default_options; } if( dim_names == NULL ) { if( n_dimensions != 3 ) { print_error( "initialize_minc_output: " ); print_error( "can't use NULL dim_names except with 3 dimensions.\n" ); return( (Minc_file) NULL ); } dim_names = default_dim_names; } if( file_nc_data_type == MI_ORIGINAL_TYPE ) { file_nc_data_type = get_volume_nc_data_type( volume_to_attach, &file_signed_flag ); get_volume_voxel_range( volume_to_attach, &file_voxel_min, &file_voxel_max ); } else if( (file_nc_data_type == NC_FLOAT || file_nc_data_type == NC_DOUBLE) && file_voxel_min >= file_voxel_max ) { get_volume_real_range( volume_to_attach, &file_voxel_min, &file_voxel_max ); } /* --- check if dimension name correspondence between volume and file */ n_volume_dims = get_volume_n_dimensions( volume_to_attach ); if( n_volume_dims > n_dimensions ) { print_error( "initialize_minc_output:" ); print_error( " volume (%d) has more dimensions than file (%d).\n", n_volume_dims, n_dimensions ); return( (Minc_file) NULL ); } ALLOC( file, 1 ); file->file_is_being_read = FALSE; file->n_file_dimensions = n_dimensions; file->volume = volume_to_attach; file->outputting_in_order = TRUE; file->entire_file_written = FALSE; file->ignoring_because_cached = FALSE; file->src_img_var = MI_ERROR; file->filename = expand_filename( filename ); if( volume_to_attach->is_cached_volume && volume_to_attach->cache.output_file_is_open && equal_strings( volume_to_attach->cache.output_filename, file->filename)) { file->ignoring_because_cached = TRUE; flush_volume_cache( volume_to_attach ); return( file ); } /*--- find correspondence between volume dimensions and file dimensions */ vol_dimension_names = get_volume_dimension_names( volume_to_attach ); if( get_dimension_ordering( n_volume_dims, vol_dimension_names, n_dimensions, dim_names, file->to_volume_index, file->to_file_index ) != OK ) { FREE( file ); return( (Minc_file) NULL ); } delete_dimension_names( volume_to_attach, vol_dimension_names ); /*--- check if image range specified */ if( options->global_image_range[0] >= options->global_image_range[1] ) { n_range_dims = n_dimensions - 2; if( equal_strings( dim_names[n_dimensions-1], MIvector_dimension ) ) --n_range_dims; for_less( d, n_range_dims, n_dimensions ) { if( file->to_volume_index[d] == INVALID_AXIS ) { print_error( "initialize_minc_output: " ); print_error( "if outputting volumes which don't contain all image\n"); print_error( "dimensions, then must specify global image range.\n" ); FREE( file ); return( (Minc_file) NULL ); } } } /*--- check sizes match between volume and file */ get_volume_sizes( volume_to_attach, volume_sizes ); for_less( d, 0, n_dimensions ) { vol_index = file->to_volume_index[d]; if( vol_index >= 0 && volume_sizes[vol_index] != sizes[d] ) { print_error( "initialize_minc_output: " ); print_error( "volume size[%d]=%d does not match file[%d]=%d.\n", vol_index, volume_sizes[vol_index], d, sizes[d] ); return( NULL ); } } /*--- create the file */ ncopts = NC_VERBOSE; file->cdfid = micreate( file->filename, NC_CLOBBER ); if( file->cdfid == MI_ERROR ) { print_error( "Error: opening MINC file \"%s\".\n", file->filename ); return( NULL ); } /* Create the root variable */ (void) micreate_std_variable(file->cdfid, MIrootvariable, NC_INT, 0, NULL); for_less( d, 0, n_dimensions ) { file->sizes_in_file[d] = (long) sizes[d]; file->indices[d] = 0; file->dim_names[d] = create_string( dim_names[d] ); file->image_dims[d] = ncdimdef( file->cdfid, file->dim_names[d], (long) sizes[d] ); } if( output_world_transform( file, volume_to_attach->coordinate_system_name, voxel_to_world_transform, options->use_volume_starts_and_steps ) != OK ) { FREE( file ); return( NULL ); } /* * Save information for creating image variable later */ file->nc_data_type = file_nc_data_type; file->signed_flag = file_signed_flag; file->valid_range[0] = file_voxel_min; file->valid_range[1] = file_voxel_max; file->image_range[0] = options->global_image_range[0]; file->image_range[1] = options->global_image_range[1]; if( file->image_range[0] < file->image_range[1] ) { file->min_id = micreate_std_variable( file->cdfid, MIimagemin, NC_DOUBLE, 0, (int *) NULL ); file->max_id = micreate_std_variable( file->cdfid, MIimagemax, NC_DOUBLE, 0, (int *) NULL ); } else { n_range_dims = n_dimensions - 2; if( equal_strings( dim_names[n_dimensions-1], MIvector_dimension ) ) --n_range_dims; file->min_id = micreate_std_variable( file->cdfid, MIimagemin, NC_DOUBLE, n_range_dims, file->image_dims); file->max_id = micreate_std_variable( file->cdfid, MIimagemax, NC_DOUBLE, n_range_dims, file->image_dims ); } ncopts = NC_VERBOSE | NC_FATAL; file->end_def_done = FALSE; file->variables_written = FALSE; return( file ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_auxiliary_data_from_minc_file @INPUT : file filename history_string @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Copies the auxiliary data from the filename to the opened Minc file, 'file'. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status copy_auxiliary_data_from_minc_file( Minc_file file, STRING filename, STRING history_string ) { Status status; int src_cdfid; STRING expanded; if( file->ignoring_because_cached ) return( OK ); ncopts = NC_VERBOSE; expanded = expand_filename( filename ); src_cdfid = miopen( expanded, NC_NOWRITE ); if( src_cdfid == MI_ERROR ) { print_error( "Error opening %s\n", expanded ); return( ERROR ); } delete_string( expanded ); status = copy_auxiliary_data_from_open_minc_file( file, src_cdfid, history_string ); (void) miclose( src_cdfid ); ncopts = NC_VERBOSE | NC_FATAL; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_auxiliary_data_from_open_minc_file @INPUT : file src_cdfid history_string @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Copies the auxiliary data from the opened minc file specified by src_cdfid to the opened minc file specified by 'file'. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status copy_auxiliary_data_from_open_minc_file( Minc_file file, int src_cdfid, STRING history_string ) { int src_img_var, varid, n_excluded, excluded_vars[10]; int i, src_min_id, src_max_id, src_root_id; Status status; STRING excluded_list[] = { MIxspace, MIyspace, MIzspace, MItime, MItfrequency, MIxfrequency, MIyfrequency, MIzfrequency, MIvector_dimension }; if( file->ignoring_because_cached ) return( OK ); if( file->end_def_done ) { print_error( "Cannot call copy_auxiliary_data_from_open_minc_file when not in define mode\n" ); return( ERROR ); } ncopts = 0; n_excluded = 0; for_less( i, 0, SIZEOF_STATIC_ARRAY( excluded_list ) ) { if( (varid = ncvarid(src_cdfid, excluded_list[i] )) != MI_ERROR ) excluded_vars[n_excluded++] = varid; } if( (src_img_var = ncvarid(src_cdfid, MIimage )) != MI_ERROR ) excluded_vars[n_excluded++] = src_img_var; if( (src_max_id = ncvarid(src_cdfid, MIimagemax )) != MI_ERROR ) excluded_vars[n_excluded++] = src_max_id; if( (src_min_id = ncvarid(src_cdfid, MIimagemin )) != MI_ERROR ) excluded_vars[n_excluded++] = src_min_id; if( (src_root_id = ncvarid(src_cdfid, MIrootvariable )) != MI_ERROR ) excluded_vars[n_excluded++] = src_root_id; ncopts = NC_VERBOSE; (void) micopy_all_var_defs( src_cdfid, file->cdfid, n_excluded, excluded_vars ); if( src_min_id != MI_ERROR ) { (void) micopy_all_atts( src_cdfid, src_min_id, file->cdfid, file->min_id ); } if( src_max_id != MI_ERROR ) { (void) micopy_all_atts( src_cdfid, src_max_id, file->cdfid, file->max_id ); } if( src_root_id != MI_ERROR ) { (void) micopy_all_atts( src_cdfid, src_root_id, file->cdfid, ncvarid( file->cdfid, MIrootvariable) ); } status = OK; if( history_string != NULL ) status = add_minc_history( file, history_string ); if( status == OK ) { /* Set info for copying image attributes. Unset afterwards, just to be safe. */ file->src_cdfid = src_cdfid; file->src_img_var = src_img_var; status = end_file_def( file ); file->src_img_var = MI_ERROR; if( status != OK ) { print_error( "Error outputting volume: possibly disk full?\n" ); } } if( status == OK ) { file->end_def_done = TRUE; (void) micopy_all_var_values( src_cdfid, file->cdfid, n_excluded, excluded_vars ); } ncopts = NC_VERBOSE | NC_FATAL; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : add_minc_history @INPUT : file history_string @OUTPUT : @RETURNS : @DESCRIPTION: Adds the history_string to the history in the file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Nov. 2, 1998 D. MacDonald - fixed error P. Neelin found with concating to non-existent history ---------------------------------------------------------------------------- */ VIOAPI Status add_minc_history( Minc_file file, STRING history_string ) { int old_att_length; nc_type datatype; STRING new_history; if( file->ignoring_because_cached ) return( OK ); if( file->end_def_done ) { print_error( "Cannot call add_minc_history when not in define mode\n" ); return( ERROR ); } ncopts = 0; if( ncattinq(file->cdfid, NC_GLOBAL, MIhistory, &datatype, &old_att_length) == MI_ERROR || datatype != NC_CHAR ) { old_att_length = 0; } /* Allocate a string and get the old history */ new_history = alloc_string( old_att_length ); new_history[0] = (char) 0; (void) miattgetstr( file->cdfid, NC_GLOBAL, MIhistory, old_att_length+1, new_history ); /* if( new_history[old_att_length] != (char) 0 ) { print( "old_att_length %d %d\n", old_att_length, new_history[old_att_length] ); new_history[old_att_length] = (char) 0; print( "string: %d\n", new_history ); } */ /* Add the new command and put the new history. */ concat_to_string( &new_history, history_string ); ncopts = NC_VERBOSE | NC_FATAL; (void) miattputstr( file->cdfid, NC_GLOBAL, MIhistory, new_history ); delete_string( new_history ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_dimension_ordering @INPUT : n_vol_dims vol_dim_names n_file_dims file_dim_names @OUTPUT : to_volume to_file @RETURNS : OK or ERROR @DESCRIPTION: Matches dimension names between the volume and file, setting the axis conversion from file to_volume and from volume to_file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status get_dimension_ordering( int n_vol_dims, STRING vol_dim_names[], int n_file_dims, STRING file_dim_names[], int to_volume[], int to_file[] ) { Status status; int v, f, n_found; for_less( f, 0, n_file_dims ) to_volume[f] = -1; for_less( v, 0, n_vol_dims ) to_file[v] = -1; n_found = 0; for_less( v, 0, n_vol_dims ) { for_less( f, 0, n_file_dims ) { if( to_volume[f] < 0 && equal_strings( vol_dim_names[v], file_dim_names[f] ) ) { to_volume[f] = v; to_file[v] = f; ++n_found; } } } if( n_found != n_vol_dims ) { print_error( "Unsuccessful matching of volume and output dimension names.\n"); status = ERROR; } else status = OK; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_minc_output_variables @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Checks if the file variables has been put into data mode, and does so if necessary. Then it checks if the variables have been written, and does so if necessary. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status check_minc_output_variables( Minc_file file ) { int d, axis; long start_index, mindex[MAX_VAR_DIMS]; Real voxel_min, voxel_max, real_min, real_max; double dim_value; Volume volume; Status status; if( !file->end_def_done ) { /* --- Get into data mode */ ncopts = NC_VERBOSE; status = end_file_def( file ); ncopts = NC_VERBOSE | NC_FATAL; file->end_def_done = TRUE; if( status != OK ) { print_error( "Error outputting volume: possibly disk full?\n" ); return( status ); } } if( !file->variables_written ) { volume = file->volume; file->variables_written = TRUE; ncopts = NC_VERBOSE; for_less( d, 0, file->n_file_dimensions ) mindex[d] = 0; dim_value = 0.0; for_less( d, 0, file->n_file_dimensions ) { if( convert_dim_name_to_spatial_axis( file->dim_names[d], &axis ) ) { (void) mivarput1( file->cdfid, file->dim_ids[d], mindex, NC_DOUBLE, MI_SIGNED, &dim_value ); } } file->minc_icv = miicv_create(); (void) miicv_setint( file->minc_icv, MI_ICV_TYPE, (int) volume->nc_data_type); (void) miicv_setstr( file->minc_icv, MI_ICV_SIGN, volume->signed_flag ? MI_SIGNED : MI_UNSIGNED ); (void) miicv_setint( file->minc_icv, MI_ICV_DO_NORM, TRUE ); (void) miicv_setint( file->minc_icv, MI_ICV_USER_NORM, TRUE ); if( file->image_range[0] < file->image_range[1] ) { (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MIN, file->image_range[0] ); (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MAX, file->image_range[1] ); } else { get_volume_real_range( volume, &real_min, &real_max ); (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MIN, real_min ); (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MAX, real_max ); } get_volume_voxel_range( volume, &voxel_min, &voxel_max ); if( voxel_min < voxel_max ) { (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MIN, voxel_min ); (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MAX, voxel_max ); } else print_error( "Volume has invalid min and max voxel value\n" ); (void) miicv_attach( file->minc_icv, file->cdfid, file->img_var_id ); start_index = 0; if( file->image_range[0] < file->image_range[1] ) { (void) mivarput1( file->cdfid, file->min_id, &start_index, NC_DOUBLE, MI_SIGNED, &file->image_range[0] ); (void) mivarput1( file->cdfid, file->max_id, &start_index, NC_DOUBLE, MI_SIGNED, &file->image_range[1] ); } ncopts = NC_VERBOSE | NC_FATAL; } return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_output_random_order @INPUT : file @OUTPUT : @RETURNS : @DESCRIPTION: Sets the file into random order access, used by volume caching. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 26, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status set_minc_output_random_order( Minc_file file ) { Status status; status = check_minc_output_variables( file ); file->outputting_in_order = FALSE; return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_minc_hyperslab @INPUT : file data_type n_array_dims array_sizes array_data_ptr to_array file_start file_count @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Outputs a hyperslab from an array to the file. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_minc_hyperslab( Minc_file file, Data_types data_type, int n_array_dims, int array_sizes[], void *array_data_ptr, int to_array[], int file_start[], int file_count[] ) { int ind, expected_ind, file_ind, dim; int n_file_dims, n_tmp_dims; long long_file_start[MAX_DIMENSIONS]; long long_file_count[MAX_DIMENSIONS]; void *void_ptr; BOOLEAN direct_from_array, non_full_size_found; int tmp_ind, tmp_sizes[MAX_DIMENSIONS]; int array_indices[MAX_DIMENSIONS]; int array_counts[MAX_VAR_DIMS]; Status status; multidim_array buffer_array; status = check_minc_output_variables( file ); if( status != OK ) return( status ); n_file_dims = file->n_file_dimensions; expected_ind = n_array_dims-1; tmp_ind = n_file_dims-1; non_full_size_found = FALSE; for_less( ind, 0, n_array_dims ) { array_indices[ind] = -1; array_counts[ind] = 1; } direct_from_array = TRUE; /*--- determine if the hyperslab represents a consecutive chunk of memory in the array */ for( file_ind = n_file_dims-1; file_ind >= 0; --file_ind ) { long_file_start[file_ind] = (long) file_start[file_ind]; long_file_count[file_ind] = (long) file_count[file_ind]; ind = to_array[file_ind]; if( ind != INVALID_AXIS ) { array_counts[ind] = file_count[file_ind]; if( !non_full_size_found && (long) file_count[file_ind] < file->sizes_in_file[file_ind] ) non_full_size_found = TRUE; else if( non_full_size_found && file_count[file_ind] > 1 ) direct_from_array = FALSE; if( file_count[file_ind] > 1 && ind != expected_ind ) direct_from_array = FALSE; if( file_count[file_ind] != 1 || file->sizes_in_file[file_ind] == 1 ) { tmp_sizes[tmp_ind] = file_count[file_ind]; array_indices[ind] = tmp_ind; --tmp_ind; } --expected_ind; } } if( direct_from_array ) /* hyperslab is consecutive chunk of memory */ { void_ptr = array_data_ptr; } else { /*--- create a temporary array to copy hyperslab to, so that we have a consecutive chunk of memory to write from */ n_tmp_dims = n_file_dims - tmp_ind - 1; for_less( dim, 0, n_tmp_dims ) tmp_sizes[dim] = tmp_sizes[dim+tmp_ind+1]; for_less( dim, 0, n_array_dims ) array_indices[dim] -= tmp_ind + 1; create_multidim_array( &buffer_array, n_tmp_dims, tmp_sizes, data_type); GET_MULTIDIM_PTR( void_ptr, buffer_array, 0, 0, 0, 0, 0 ); /*--- copy from the array argument to the temporary array */ copy_multidim_data_reordered( get_type_size(data_type), void_ptr, n_tmp_dims, tmp_sizes, array_data_ptr, n_array_dims, array_sizes, array_counts, array_indices, TRUE ); GET_MULTIDIM_PTR( void_ptr, buffer_array, 0, 0, 0, 0, 0 ); } /*--- output the data to the file */ if( miicv_put( file->minc_icv, long_file_start, long_file_count, void_ptr ) == MI_ERROR ) status = ERROR; else status = OK; if( !direct_from_array ) delete_multidim_array( &buffer_array ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_slab @INPUT : file volume to_volume file_start file_count @OUTPUT : @RETURNS : @DESCRIPTION: Outputs the slab specified by the file start and count arrays, from the volume. The to_volume array translates axes in the file to axes in the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Sep 1, 1995 D. MacDonald - added cached volumes. ---------------------------------------------------------------------------- */ static void output_slab( Minc_file file, Volume volume, int to_volume[], long file_start[], long file_count[] ) { int dim, file_ind, ind, n_slab_dims; int to_array[MAX_DIMENSIONS]; int volume_start[MAX_DIMENSIONS]; int volume_sizes[MAX_DIMENSIONS]; int array_to_volume[MAX_DIMENSIONS]; int int_file_count[MAX_DIMENSIONS]; int int_file_start[MAX_DIMENSIONS]; int slab_sizes[MAX_DIMENSIONS]; int v[MAX_DIMENSIONS]; int size0, size1, size2, size3, size4; Real value; void *array_data_ptr; multidim_array array; for_less( file_ind, 0, file->n_file_dimensions ) { int_file_start[file_ind] = (int) file_start[file_ind]; int_file_count[file_ind] = (int) file_count[file_ind]; ind = to_volume[file_ind]; if( ind != INVALID_AXIS ) volume_start[ind] = int_file_start[file_ind]; else volume_start[ind] = 0; } if( volume->is_cached_volume ) { /*--- must make a temporary hyperslab array to contain the volume */ for_less( dim, 0, get_volume_n_dimensions(volume) ) volume_sizes[dim] = 1; for_less( dim, 0, MAX_DIMENSIONS ) array_to_volume[dim] = 0; for_less( dim, get_volume_n_dimensions(volume), MAX_DIMENSIONS ) { volume_start[dim] = 0; volume_sizes[dim] = 1; } n_slab_dims = 0; for_less( file_ind, 0, file->n_file_dimensions ) { ind = to_volume[file_ind]; if( ind != INVALID_AXIS ) { to_array[file_ind] = n_slab_dims; array_to_volume[n_slab_dims] = ind; slab_sizes[n_slab_dims] = int_file_count[file_ind]; volume_sizes[ind] = int_file_count[file_ind]; ++n_slab_dims; } else { to_array[file_ind] = INVALID_AXIS; } } create_multidim_array( &array, n_slab_dims, slab_sizes, get_volume_data_type(volume) ); /*--- copy from the cached volume to the temporary array */ size0 = volume_sizes[0]; size1 = volume_sizes[1]; size2 = volume_sizes[2]; size3 = volume_sizes[3]; size4 = volume_sizes[4]; for_less( v[0], 0, size0 ) for_less( v[1], 0, size1 ) for_less( v[2], 0, size2 ) for_less( v[3], 0, size3 ) for_less( v[4], 0, size4 ) { value = get_volume_voxel_value( volume, volume_start[0] + v[0], volume_start[1] + v[1], volume_start[2] + v[2], volume_start[3] + v[3], volume_start[4] + v[4] ); SET_MULTIDIM( array, v[array_to_volume[0]], v[array_to_volume[1]], v[array_to_volume[2]], v[array_to_volume[3]], v[array_to_volume[4]], value ); } /*--- output the temporary array */ GET_MULTIDIM_PTR( array_data_ptr, array, 0, 0, 0, 0, 0 ); (void) output_minc_hyperslab( file, get_volume_data_type(volume), n_slab_dims, slab_sizes, array_data_ptr, to_array, int_file_start, int_file_count); delete_multidim_array( &array ); } else { GET_MULTIDIM_PTR( array_data_ptr, volume->array, volume_start[0], volume_start[1], volume_start[2], volume_start[3], volume_start[4] ); get_volume_sizes( volume, volume_sizes ); (void) output_minc_hyperslab( file, get_volume_data_type(volume), get_volume_n_dimensions(volume), volume_sizes, array_data_ptr, to_volume, int_file_start, int_file_count ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_the_volume @INPUT : file volume volume_count file_start @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Outputs the volume to the file in the given position. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status output_the_volume( Minc_file file, Volume volume, int volume_count[], long file_start[] ) { Status status; int d, n_volume_dims, sizes[MAX_DIMENSIONS]; int slab_size, n_slab, this_count; int vol_index, step, n_steps, n_range_dims; int to_volume_index[MAX_VAR_DIMS]; int to_file_index[MAX_DIMENSIONS]; long file_indices[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS]; Real real_min, real_max; STRING *vol_dimension_names; BOOLEAN increment; progress_struct progress; status = check_minc_output_variables( file ); if( status != OK ) return( status ); /* --- check if dimension name correspondence between volume and file */ n_volume_dims = get_volume_n_dimensions( volume ); if( n_volume_dims > file->n_file_dimensions ) { print_error( "output_volume_to_minc_file_position:" ); print_error( " volume (%d) has more dimensions than file (%d).\n", n_volume_dims, file->n_file_dimensions ); return( ERROR ); } /*--- find correspondence between volume dimensions and file dimensions */ vol_dimension_names = get_volume_dimension_names( volume ); status = get_dimension_ordering( n_volume_dims, vol_dimension_names, file->n_file_dimensions, file->dim_names, to_volume_index, to_file_index ); delete_dimension_names( volume, vol_dimension_names ); if( status != OK ) return( ERROR ); /*--- check sizes match between volume and file */ get_volume_sizes( volume, sizes ); for_less( d, 0, file->n_file_dimensions ) { vol_index = to_volume_index[d]; if( vol_index >= 0 ) { if( volume_count[vol_index] < 0 || volume_count[vol_index] > sizes[vol_index] ) { print_error( "output_the_volume: invalid volume count.\n" ); print_error( " count[%d] = %d\n", vol_index, volume_count[vol_index] ); return( ERROR ); } this_count = volume_count[vol_index]; } else { this_count = 1; } if( file_start[d] < 0 || file_start[d] + (long) this_count > file->sizes_in_file[d] ) { print_error( "output_the_volume: invalid minc file position.\n" ); print_error( " start[%d] = %d count[%d] = %d\n", d, file_start[d], d, this_count ); return( ERROR ); } } /*--- if per slice image ranges, output the ranges corresponding to this volume */ if( file->image_range[0] >= file->image_range[1] ) { long n_ranges, range_start[MAX_VAR_DIMS], range_count[MAX_VAR_DIMS]; long r; double *image_range; n_range_dims = file->n_file_dimensions - 2; if( equal_strings( file->dim_names[file->n_file_dimensions-1], MIvector_dimension ) ) --n_range_dims; n_ranges = 1; for_less( d, 0, n_range_dims ) { vol_index = to_volume_index[d]; if( vol_index == INVALID_AXIS ) { range_count[d] = 1; range_start[d] = file_start[d]; } else { n_ranges *= (long) volume_count[vol_index]; range_count[d] = (long) volume_count[vol_index]; range_start[d] = 0; } } get_volume_real_range( volume, &real_min, &real_max ); ALLOC( image_range, n_ranges ); for_less( r, 0, n_ranges ) image_range[r] = real_min; (void) mivarput( file->cdfid, file->min_id, range_start, range_count, NC_DOUBLE, MI_UNSIGNED, (void *) image_range ); for_less( r, 0, n_ranges ) image_range[r] = real_max; (void) mivarput( file->cdfid, file->max_id, range_start, range_count, NC_DOUBLE, MI_UNSIGNED, (void *) image_range ); FREE( image_range ); } /* --- determine which contiguous blocks of volume to output to max out the read/write buffer and make it like the chunking dimensions for compression (for efficiency) */ file->n_slab_dims = 0; slab_size = 1; n_steps = 1; int unit_size = get_type_size( get_volume_data_type(volume) ); for( d = file->n_file_dimensions-1; d >= 0; d-- ) { count[d] = 1; file_indices[d] = file_start[d]; if( to_volume_index[d] != INVALID_AXIS ) { if( MI_MAX_VAR_BUFFER_SIZE > volume_count[to_volume_index[d]] * slab_size * unit_size && n_steps == 1 ) { count[d] = volume_count[to_volume_index[d]]; file->n_slab_dims++; /* integral number of complete dimensions */ } else { count[d] = MIN( volume_count[to_volume_index[d]], (size_t)( MI_MAX_VAR_BUFFER_SIZE / ( slab_size * unit_size ) ) ); n_steps *= (int)( ( volume_count[to_volume_index[d]] + count[d] - 1 ) / count[d] ); } slab_size *= count[d]; } } if( file->n_slab_dims == 0 ) { fprintf( stderr, "Error: You seem to be processing a minc file\n" ); fprintf( stderr, "with no valid axes. Please check your volume.\n" ); exit(1); } /*--- now write entire volume in contiguous chunks (possibly only 1 req'd)*/ step = 0; initialize_progress_report( &progress, FALSE, n_steps,"Outputting Volume" ); increment = FALSE; while( !increment ) { /*--- set the indices of the file slab to write */ long local_count[MAX_VAR_DIMS]; for( d = 0; d < file->n_file_dimensions; d++ ) { vol_index = to_volume_index[d]; local_count[d] = MIN( volume_count[vol_index] - file_indices[d], count[d] ); } output_slab( file, volume, to_volume_index, file_indices, local_count ); /*--- increment the file index dimensions which correspond for the next slab to write to output */ increment = TRUE; d = file->n_file_dimensions-1; n_slab = 0; while( increment && d >= 0 ) { vol_index = to_volume_index[d]; if( vol_index != INVALID_AXIS && n_slab >= file->n_slab_dims ) { file_indices[d] += local_count[d]; if( file_indices[d] < file_start[d] + (long) volume_count[vol_index] ) { increment = FALSE; } else { file_indices[d] = file_start[d]; } } if( vol_index != INVALID_AXIS ) ++n_slab; --d; } ++step; if( n_steps > 1 ) update_progress_report( &progress, step ); } terminate_progress_report( &progress ); if( step != n_steps ) { fprintf( stderr, "Error: Your output minc file may be incomplete\n" ); fprintf( stderr, "(wrote only %d out of %d buffers)\n", step, n_steps ); exit(1); } return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_volume_to_minc_file_position @INPUT : file volume volume_count file_start @OUTPUT : Outputs the volume to the specified file position. @RETURNS : @DESCRIPTION: @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_volume_to_minc_file_position( Minc_file file, Volume volume, int volume_count[], long file_start[] ) { if( file->ignoring_because_cached ) return( OK ); file->outputting_in_order = FALSE; return( output_the_volume( file, volume, volume_count, file_start ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_minc_volume @INPUT : file @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Outputs the attached volume to the MINC file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_minc_volume( Minc_file file ) { int d, volume_count[MAX_DIMENSIONS]; BOOLEAN increment; if( file->ignoring_because_cached ) return( OK ); /*--- check number of volumes written */ d = 0; while( d < file->n_file_dimensions && file->to_volume_index[d] != INVALID_AXIS ) ++d; if( d < file->n_file_dimensions && file->indices[d] >= file->sizes_in_file[d] ) { print_error( "output_minc_volume: attempted to write too many subvolumes.\n"); return( ERROR ); } get_volume_sizes( file->volume, volume_count ); if( output_the_volume( file, file->volume, volume_count, file->indices ) != OK ) return( ERROR ); /*--- increment the file index dimensions which do not correspond to volume dimensions */ increment = TRUE; d = file->n_file_dimensions-1; while( increment && d >= 0 ) { if( file->to_volume_index[d] == INVALID_AXIS ) { ++file->indices[d]; if( file->indices[d] < file->sizes_in_file[d] ) increment = FALSE; else file->indices[d] = 0; } --d; } if( increment ) file->entire_file_written = TRUE; return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : close_minc_output @INPUT : file @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Closes the MINC file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status close_minc_output( Minc_file file ) { int d; if( file == (Minc_file) NULL ) { print_error( "close_minc_output(): NULL file.\n" ); return( ERROR ); } if( !file->ignoring_because_cached ) { if( file->outputting_in_order && !file->entire_file_written ) { print_error( "Warning: the MINC file has been " ); print_error( "closed without writing part of it.\n"); } (void) miattputstr( file->cdfid, file->img_var_id, MIcomplete, MI_TRUE); (void) miclose( file->cdfid ); (void) miicv_free( file->minc_icv ); for_less( d, 0, file->n_file_dimensions ) delete_string( file->dim_names[d] ); } delete_string( file->filename ); FREE( file ); return( OK ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_default_minc_output_options @INPUT : @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the minc output options to the default. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - added use_volume_starts_and_steps ---------------------------------------------------------------------------- */ VIOAPI void set_default_minc_output_options( minc_output_options *options ) { int dim; for_less( dim, 0, MAX_DIMENSIONS ) options->dimension_names[dim] = NULL; options->global_image_range[0] = 0.0; options->global_image_range[1] = -1.0; options->use_volume_starts_and_steps = FALSE; options->use_starts_set = FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_minc_output_options @INPUT : src @OUTPUT : dest @RETURNS : @DESCRIPTION: Copies the minc output options to a new structure. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 12, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void copy_minc_output_options( minc_output_options *src, minc_output_options *dest ) { int dim; if( src == NULL ) set_default_minc_output_options( dest ); else { *dest = *src; for_less( dim, 0, MAX_DIMENSIONS ) { if( src->dimension_names[dim] != NULL ) dest->dimension_names[dim] = create_string( src->dimension_names[dim] ); } } } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_minc_output_options @INPUT : options @OUTPUT : @RETURNS : @DESCRIPTION: Deletes the minc output options. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void delete_minc_output_options( minc_output_options *options ) { int i; for_less( i, 0, MAX_DIMENSIONS ) delete_string( options->dimension_names[i] ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_output_dimensions_order @INPUT : n_dimensions dimension_names @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the dimension ordering of the minc output options. This option is used by output_volume, but not by initialize_minc_output. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_output_dimensions_order( minc_output_options *options, int n_dimensions, STRING dimension_names[] ) { int i; for_less( i, 0, n_dimensions ) { replace_string( &options->dimension_names[i], create_string(dimension_names[i]) ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_output_real_range @INPUT : real_min real_max @OUTPUT : options @RETURNS : @DESCRIPTION: Sets the global real range of the entire file, unless real_min >= real_max. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_output_real_range( minc_output_options *options, Real real_min, Real real_max ) { options->global_image_range[0] = real_min; options->global_image_range[1] = real_max; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_minc_output_use_volume_starts_and_steps_flag @INPUT : options flag @OUTPUT : @RETURNS : @DESCRIPTION: Tells MINC output to use the exact starts and steps stored in the volume, not the voxel-to-world-transform. This avoids round-off errors in converting to transform on input, then from transform on output. @METHOD : @GLOBALS : @CALLS : @CREATED : May. 22, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_minc_output_use_volume_starts_and_steps_flag( minc_output_options *options, BOOLEAN flag ) { options->use_volume_starts_and_steps = flag; options->use_starts_set = TRUE; } minc-2.2.00/volume_io/Volumes/output_volume.c0000644000265600003100000003302212027132664016165 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include /* ----------------------------- MNI Header ----------------------------------- @NAME : get_file_dimension_names @INPUT : filename n_dims @OUTPUT : dim_names @RETURNS : OK or ERROR @DESCRIPTION: Gets the names of the dimensions from the specified file. dim_names is an array of STRINGS, where the array has been allocated, but not each string. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status get_file_dimension_names( STRING filename, int *n_dims, STRING *dim_names[] ) { int i; Status status; volume_input_struct volume_input; Volume tmp_volume; status = start_volume_input( filename, -1, File_order_dimension_names, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &tmp_volume, (minc_input_options *) NULL, &volume_input ); if( status == OK ) { *n_dims = get_volume_n_dimensions( tmp_volume ); ALLOC( *dim_names, *n_dims ); for_less( i, 0, *n_dims ) { (*dim_names)[i] = create_string( volume_input.minc_file->dim_names[i]); } delete_volume_input( &volume_input ); delete_volume( tmp_volume ); } return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_output_dim_names @INPUT : volume original_filename options @OUTPUT : file_sizes @RETURNS : array of names @DESCRIPTION: Creates an array of dimension names for file output. If the options contains a set of names, they are used. Otherwise, if the original_filename is specified (non-NULL), then the dimension names from it are used, if they contain all the dimension names in the volume. Otherwise, those from the volume are used. The file_sizes[] array is set to match the sizes in the volume cross-referenced with the dimension names. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 4, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING *create_output_dim_names( Volume volume, STRING original_filename, minc_output_options *options, int file_sizes[] ) { int n_dims, n_file_dims, dim_index; int vol_sizes[MAX_DIMENSIONS]; int i, j, n_found; STRING *file_dim_names; STRING *vol_dimension_names; STRING *dim_names; get_volume_sizes( volume, vol_sizes ); n_dims = get_volume_n_dimensions(volume); vol_dimension_names = get_volume_dimension_names( volume ); ALLOC( dim_names, n_dims ); /*--- either get the output dim name ordering from the original filename, the volume, or the options */ if( options != NULL && string_length( options->dimension_names[0] ) > 0 ) { for_less( i, 0, n_dims ) dim_names[i] = create_string( options->dimension_names[i] ); } else { if( original_filename != NULL && file_exists(original_filename) && get_file_dimension_names( original_filename, &n_file_dims, &file_dim_names ) == OK ) { /*--- extract the dimension names from the file which match those of the volume, so a 3D volume of z, y, x with a 4D file of x y z t, will generate a list of dim_names: x y z */ dim_index = 0; for_less( i, 0, n_file_dims ) { for_less( j, 0, n_dims ) { if( equal_strings( vol_dimension_names[j], file_dim_names[i] ) ) { dim_names[dim_index] = create_string( vol_dimension_names[j] ); ++dim_index; break; } } if( dim_index == n_dims ) /*--- save time */ break; } /*--- check that all volume dimensions exist in the file */ if( dim_index != n_dims ) { for_less( i, 0, dim_index ) delete_string( dim_names[i] ); for_less( i, 0, n_dims ) dim_names[i] = create_string( vol_dimension_names[i] ); } /*--- free up the file dimension names */ for_less( i, 0, n_file_dims ) delete_string( file_dim_names[i] ); FREE( file_dim_names ); } else /*--- no original file specified, use the volumes own list */ { for_less( i, 0, n_dims ) dim_names[i] = create_string( vol_dimension_names[i] ); } } /*--- check that the set of dimension names are simply a permutation of the ones in the volume */ n_found = 0; for_less( i, 0, n_dims ) { for_less( j, 0, n_dims ) { if( equal_strings( dim_names[j], vol_dimension_names[i] ) ) { file_sizes[j] = vol_sizes[i]; ++n_found; } } } /*--- act on whether the set of names was a permutation or not */ if( n_found != n_dims ) { print_error( "create_output_dim_names: dimension name mismatch.\n" ); delete_dimension_names( volume, dim_names ); dim_names = NULL; } /*--- no longer need the volume dimension names */ delete_dimension_names( volume, vol_dimension_names ); return( dim_names ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_volume_auxiliary_and_history @INPUT : minc_file filename original_filename history @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: If the original_filename is specified, Copies the auxiliary data from it. If the history is specified, adds the history line. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 24, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status copy_volume_auxiliary_and_history( Minc_file minc_file, STRING filename, STRING original_filename, STRING history ) { Status status; BOOLEAN copy_original_file_data; STRING full_filename, full_original_filename; copy_original_file_data = FALSE; if( original_filename != NULL ) { full_filename = expand_filename( filename ); full_original_filename = expand_filename( original_filename ); if( !equal_strings( full_filename, full_original_filename ) && file_exists( full_original_filename ) ) { copy_original_file_data = TRUE; } delete_string( full_filename ); delete_string( full_original_filename ); } status = OK; if( copy_original_file_data ) { status = copy_auxiliary_data_from_minc_file( minc_file, original_filename, history ); } else if( history != NULL ) status = add_minc_history( minc_file, history ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_modified_volume @INPUT : filename file_nc_data_type file_signed_flag file_voxel_min file_voxel_max volume original_filename history options @OUTPUT : @RETURNS : OK or ERROR @DESCRIPTION: Creates a Minc file and outputs the volume to it. The data type of the file is either specified by the second through fifth parameters, or by the volume, if file_nc_data_type is MI_ORIGINAL_TYPE. The volume is assumed to be derived, in some fashion, from an existing MINC file, and the auxiliary data from the existing MINC file, 'original_filename', is copied to the output file, along with the 'history' string. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - now sets use_volume_starts_and_steps flag ---------------------------------------------------------------------------- */ VIOAPI Status output_modified_volume( STRING filename, nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, Volume volume, STRING original_filename, STRING history, minc_output_options *options ) { Status status; Minc_file minc_file; int n_dims, sizes[MAX_DIMENSIONS]; Real real_min, real_max; STRING *dim_names; minc_output_options used_options; dim_names = create_output_dim_names( volume, original_filename, options, sizes ); if( dim_names == NULL ) return( ERROR ); n_dims = get_volume_n_dimensions(volume); if( options == NULL ) set_default_minc_output_options( &used_options ); else used_options = *options; if( used_options.global_image_range[0] >= used_options.global_image_range[1] ) { get_volume_real_range( volume, &real_min, &real_max ); set_minc_output_real_range( &used_options, real_min, real_max ); } /*--- if the user has not explicitly set the use_volume_starts_and_steps flag, let's set it if the transform is linear, to output the same starts as was input, and avoid round-off error */ if( !used_options.use_starts_set && !used_options.use_volume_starts_and_steps && get_transform_type(get_voxel_to_world_transform(volume)) == LINEAR ) { set_minc_output_use_volume_starts_and_steps_flag( &used_options, TRUE ); } minc_file = initialize_minc_output( filename, n_dims, dim_names, sizes, file_nc_data_type, file_signed_flag, file_voxel_min, file_voxel_max, get_voxel_to_world_transform(volume), volume, &used_options ); if( minc_file == NULL ) return( ERROR ); status = copy_volume_auxiliary_and_history( minc_file, filename, original_filename, history ); if( status == OK ) status = output_minc_volume( minc_file ); if( status == OK ) status = close_minc_output( minc_file ); delete_dimension_names( volume, dim_names ); return( status ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : output_volume @INPUT : filename file_nc_data_type file_signed_flag file_voxel_min file_voxel_max volume history options @OUTPUT : @RETURNS : @DESCRIPTION: Sames as output_modified_volume, above, but the volume is not a modification of an existing MINC file. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Status output_volume( STRING filename, nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, Volume volume, STRING history, minc_output_options *options ) { return( output_modified_volume( filename, file_nc_data_type, file_signed_flag, file_voxel_min, file_voxel_max, volume, NULL, history, options ) ); } minc-2.2.00/volume_io/Volumes/set_hyperslab.c0000644000265600003100000011210512027132664016102 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include VIOAPI void convert_values_to_voxels( Volume volume, int n_voxels, Real values[], Real voxels[] ) { int v; Real scale, trans; if( !volume->real_range_set ) { if( voxels != values ) { for_less( v, 0, n_voxels ) voxels[v] = values[v]; } return; } scale = volume->real_value_scale; trans = volume->real_value_translation; for_less( v, 0, n_voxels ) voxels[v] = (values[v] - trans) / scale; } VIOAPI void set_volume_value_hyperslab( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { switch( get_volume_n_dimensions(volume) ) { case 1: set_volume_value_hyperslab_1d( volume, v0, n0, values ); break; case 2: set_volume_value_hyperslab_2d( volume, v0, v1, n0, n1, values ); break; case 3: set_volume_value_hyperslab_3d( volume, v0, v1, v2, n0, n1, n2, values ); break; case 4: set_volume_value_hyperslab_4d( volume, v0, v1, v2, v3, n0, n1, n2, n3, values ); break; case 5: set_volume_value_hyperslab_5d( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, values ); break; } } VIOAPI void set_volume_value_hyperslab_5d( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { int size; Real *voxels; size = n0 * n1 * n2 * n3 * n4; ALLOC( voxels, size ); convert_values_to_voxels( volume, size, values, voxels ); set_volume_voxel_hyperslab_5d( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, voxels ); FREE( voxels ); } VIOAPI void set_volume_value_hyperslab_4d( Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, Real values[] ) { int size; Real *voxels; size = n0 * n1 * n2 * n3; ALLOC( voxels, size ); convert_values_to_voxels( volume, size, values, voxels ); set_volume_voxel_hyperslab_4d( volume, v0, v1, v2, v3, n0, n1, n2, n3, voxels ); FREE( voxels ); } VIOAPI void set_volume_value_hyperslab_3d( Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, Real values[] ) { int size; Real *voxels; size = n0 * n1 * n2; ALLOC( voxels, size ); convert_values_to_voxels( volume, size, values, voxels ); set_volume_voxel_hyperslab_3d( volume, v0, v1, v2, n0, n1, n2, voxels ); FREE( voxels ); } VIOAPI void set_volume_value_hyperslab_2d( Volume volume, int v0, int v1, int n0, int n1, Real values[] ) { int size; Real *voxels; size = n0 * n1; ALLOC( voxels, size ); convert_values_to_voxels( volume, size, values, voxels ); set_volume_voxel_hyperslab_2d( volume, v0, v1, n0, n1, voxels ); FREE( voxels ); } VIOAPI void set_volume_value_hyperslab_1d( Volume volume, int v0, int n0, Real values[] ) { Real *voxels; ALLOC( voxels, n0 ); convert_values_to_voxels( volume, n0, values, voxels ); set_volume_voxel_hyperslab_1d( volume, v0, n0, voxels ); FREE( voxels ); } static void slow_set_volume_voxel_hyperslab( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { int i0, i1, i2, i3, i4, n_dims; n_dims = get_volume_n_dimensions( volume ); if( n_dims < 5 ) n4 = 1; if( n_dims < 4 ) n3 = 1; if( n_dims < 3 ) n2 = 1; if( n_dims < 2 ) n1 = 1; if( n_dims < 1 ) n0 = 1; for_less( i0, 0, n0 ) for_less( i1, 0, n1 ) for_less( i2, 0, n2 ) for_less( i3, 0, n3 ) for_less( i4, 0, n4 ) { set_volume_voxel_value( volume, v0 + i0, v1 + i1, v2 + i2, v3 + i3, v4 + i4, *values ); ++values; } } static void set_voxel_values_5d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1, step2, step3, step4; int i0, i1, i2, i3, i4; int n0, n1, n2, n3, n4; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; n0 = counts[0]; n1 = counts[1]; n2 = counts[2]; n3 = counts[3]; n4 = counts[4]; step0 = steps[0]; step1 = steps[1]; step2 = steps[2]; step3 = steps[3]; step4 = steps[4]; step0 -= n1 * step1; step1 -= n2 * step2; step2 -= n3 * step3; step3 -= n4 * step4; switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *unsigned_byte_ptr = (unsigned char) floor( *values + 0.5 ); ++values; unsigned_byte_ptr += step4; } unsigned_byte_ptr += step3; } unsigned_byte_ptr += step2; } unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *signed_byte_ptr = (signed char) floor( *values + 0.5 ); ++values; signed_byte_ptr += step4; } signed_byte_ptr += step3; } signed_byte_ptr += step2; } signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *unsigned_short_ptr = (unsigned short) floor( *values + 0.5 ); ++values; unsigned_short_ptr += step4; } unsigned_short_ptr += step3; } unsigned_short_ptr += step2; } unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *signed_short_ptr = (signed short) floor( *values + 0.5 ); ++values; signed_short_ptr += step4; } signed_short_ptr += step3; } signed_short_ptr += step2; } signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *unsigned_int_ptr = (unsigned int) floor( *values + 0.5 ); ++values; unsigned_int_ptr += step4; } unsigned_int_ptr += step3; } unsigned_int_ptr += step2; } unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *signed_int_ptr = (signed int) floor( *values + 0.5 ); ++values; signed_int_ptr += step4; } signed_int_ptr += step3; } signed_int_ptr += step2; } signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *float_ptr = (float) *values; ++values; float_ptr += step4; } float_ptr += step3; } float_ptr += step2; } float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { for_less( i4, 0, n4 ) { *double_ptr = (double) *values; ++values; double_ptr += step4; } double_ptr += step3; } double_ptr += step2; } double_ptr += step1; } double_ptr += step0; } break; } } static void set_voxel_values_4d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1, step2, step3; int i0, i1, i2, i3; int n0, n1, n2, n3; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; n0 = counts[0]; n1 = counts[1]; n2 = counts[2]; n3 = counts[3]; step0 = steps[0]; step1 = steps[1]; step2 = steps[2]; step3 = steps[3]; step0 -= n1 * step1; step1 -= n2 * step2; step2 -= n3 * step3; switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *unsigned_byte_ptr = (unsigned char) floor( *values + 0.5 ); ++values; unsigned_byte_ptr += step3; } unsigned_byte_ptr += step2; } unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *signed_byte_ptr = (signed char) floor( *values + 0.5 ); ++values; signed_byte_ptr += step3; } signed_byte_ptr += step2; } signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *unsigned_short_ptr = (unsigned short) floor( *values + 0.5 ); ++values; unsigned_short_ptr += step3; } unsigned_short_ptr += step2; } unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *signed_short_ptr = (signed short) floor( *values + 0.5 ); ++values; signed_short_ptr += step3; } signed_short_ptr += step2; } signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *unsigned_int_ptr = (unsigned int) floor( *values + 0.5 ); ++values; unsigned_int_ptr += step3; } unsigned_int_ptr += step2; } unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *signed_int_ptr = (signed int) floor( *values + 0.5 ); ++values; signed_int_ptr += step3; } signed_int_ptr += step2; } signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *float_ptr = (float) *values; ++values; float_ptr += step3; } float_ptr += step2; } float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { for_less( i3, 0, n3 ) { *double_ptr = (double) *values; ++values; double_ptr += step3; } double_ptr += step2; } double_ptr += step1; } double_ptr += step0; } break; } } static void set_voxel_values_3d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1, step2; int i0, i1, i2; int n0, n1, n2; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; n0 = counts[0]; n1 = counts[1]; n2 = counts[2]; step0 = steps[0]; step1 = steps[1]; step2 = steps[2]; step0 -= n1 * step1; step1 -= n2 * step2; switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *unsigned_byte_ptr = (unsigned char) floor( *values + 0.5 ); ++values; unsigned_byte_ptr += step2; } unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *signed_byte_ptr = (signed char) floor( *values + 0.5 ); ++values; signed_byte_ptr += step2; } signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *unsigned_short_ptr = (unsigned short) floor( *values + 0.5 ); ++values; unsigned_short_ptr += step2; } unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *signed_short_ptr = (signed short) floor( *values + 0.5 ); ++values; signed_short_ptr += step2; } signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *unsigned_int_ptr = (unsigned int) floor( *values + 0.5 ); ++values; unsigned_int_ptr += step2; } unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *signed_int_ptr = (signed long) floor( *values + 0.5 ); ++values; signed_int_ptr += step2; } signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *float_ptr = (float) *values; ++values; float_ptr += step2; } float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { for_less( i2, 0, n2 ) { *double_ptr = (double) *values; ++values; double_ptr += step2; } double_ptr += step1; } double_ptr += step0; } break; } } static void set_voxel_values_2d( Data_types data_type, void *void_ptr, int steps[], int counts[], Real values[] ) { int step0, step1; int i0, i1; int n0, n1; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; n0 = counts[0]; n1 = counts[1]; step0 = steps[0]; step1 = steps[1]; step0 -= n1 * step1; switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *unsigned_byte_ptr = (unsigned char) floor( *values + 0.5 ); ++values; unsigned_byte_ptr += step1; } unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *signed_byte_ptr = (signed char) floor( *values + 0.5 ); ++values; signed_byte_ptr += step1; } signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *unsigned_short_ptr = (unsigned short) floor( *values + 0.5 ); ++values; unsigned_short_ptr += step1; } unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *signed_short_ptr = (signed short) floor( *values + 0.5 ); ++values; signed_short_ptr += step1; } signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *unsigned_int_ptr = (unsigned int) floor( *values + 0.5 ); ++values; unsigned_int_ptr += step1; } unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *signed_int_ptr = (signed int) floor( *values + 0.5 ); ++values; signed_int_ptr += step1; } signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *float_ptr = (float) *values; ++values; float_ptr += step1; } float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { for_less( i1, 0, n1 ) { *double_ptr = (double) *values; ++values; double_ptr += step1; } double_ptr += step0; } break; } } static void set_voxel_values_1d( Data_types data_type, void *void_ptr, int step0, int n0, Real values[] ) { int i0; unsigned char *unsigned_byte_ptr; signed char *signed_byte_ptr; unsigned short *unsigned_short_ptr; signed short *signed_short_ptr; unsigned int *unsigned_int_ptr; signed int *signed_int_ptr; float *float_ptr; double *double_ptr; switch( data_type ) { case UNSIGNED_BYTE: ASSIGN_PTR(unsigned_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { *unsigned_byte_ptr = (unsigned char) floor( *values + 0.5 ); ++values; unsigned_byte_ptr += step0; } break; case SIGNED_BYTE: ASSIGN_PTR(signed_byte_ptr) = void_ptr; for_less( i0, 0, n0 ) { *signed_byte_ptr = (signed char) floor( *values + 0.5 ); ++values; signed_byte_ptr += step0; } break; case UNSIGNED_SHORT: ASSIGN_PTR(unsigned_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { *unsigned_short_ptr = (unsigned short) floor( *values + 0.5 ); ++values; unsigned_short_ptr += step0; } break; case SIGNED_SHORT: ASSIGN_PTR(signed_short_ptr) = void_ptr; for_less( i0, 0, n0 ) { *signed_short_ptr = (signed short) floor( *values + 0.5 ); ++values; signed_short_ptr += step0; } break; case UNSIGNED_INT: ASSIGN_PTR(unsigned_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { *unsigned_int_ptr = (unsigned int) floor( *values + 0.5 ); ++values; unsigned_int_ptr += step0; } break; case SIGNED_INT: ASSIGN_PTR(signed_int_ptr) = void_ptr; for_less( i0, 0, n0 ) { *signed_int_ptr = (signed int) floor( *values + 0.5 ); ++values; signed_int_ptr += step0; } break; case FLOAT: ASSIGN_PTR(float_ptr) = void_ptr; for_less( i0, 0, n0 ) { *float_ptr = (float) *values; ++values; float_ptr += step0; } break; case DOUBLE: ASSIGN_PTR(double_ptr) = void_ptr; for_less( i0, 0, n0 ) { *double_ptr = (double) *values; ++values; double_ptr += step0; } break; } } static void set_voxel_values( Volume volume, void *void_ptr, int n_dims, int steps[], int counts[], Real values[] ) { Data_types data_type; data_type = get_volume_data_type( volume ); switch( n_dims ) { case 0: set_voxel_values_1d( data_type, void_ptr, 1, 1, values ); break; case 1: set_voxel_values_1d( data_type, void_ptr, steps[0], counts[0], values ); break; case 2: set_voxel_values_2d( data_type, void_ptr, steps, counts, values ); break; case 3: set_voxel_values_3d( data_type, void_ptr, steps, counts, values ); break; case 4: set_voxel_values_4d( data_type, void_ptr, steps, counts, values ); break; case 5: set_voxel_values_5d( data_type, void_ptr, steps, counts, values ); break; } } VIOAPI void set_volume_voxel_hyperslab_5d( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_set_volume_voxel_hyperslab( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_5D( void_ptr, volume->array, v0, v1, v2, v3, v4 ) stride = 1; dim = 5; if( n4 > 1 ) { --dim; counts[dim] = n4; steps[dim] = stride; } stride *= sizes[4]; if( n3 > 1 ) { --dim; counts[dim] = n3; steps[dim] = stride; } stride *= sizes[3]; if( n2 > 1 ) { --dim; counts[dim] = n2; steps[dim] = stride; } stride *= sizes[2]; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } set_voxel_values( volume, void_ptr, 5 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void set_volume_voxel_hyperslab_4d( Volume volume, int v0, int v1, int v2, int v3, int n0, int n1, int n2, int n3, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_set_volume_voxel_hyperslab( volume, v0, v1, v2, v3, 0, n0, n1, n2, n3, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_4D( void_ptr, volume->array, v0, v1, v2, v3 ) stride = 1; dim = 4; if( n3 > 1 ) { --dim; counts[dim] = n3; steps[dim] = stride; } stride *= sizes[3]; if( n2 > 1 ) { --dim; counts[dim] = n2; steps[dim] = stride; } stride *= sizes[2]; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } set_voxel_values( volume, void_ptr, 4 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void set_volume_voxel_hyperslab_3d( Volume volume, int v0, int v1, int v2, int n0, int n1, int n2, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_set_volume_voxel_hyperslab( volume, v0, v1, v2, 0, 0, n0, n1, n2, 0, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_3D( void_ptr, volume->array, v0, v1, v2 ) stride = 1; dim = 3; if( n2 > 1 ) { --dim; counts[dim] = n2; steps[dim] = stride; } stride *= sizes[2]; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } set_voxel_values( volume, void_ptr, 3 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void set_volume_voxel_hyperslab_2d( Volume volume, int v0, int v1, int n0, int n1, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim, stride; void *void_ptr; if( volume->is_cached_volume ) { slow_set_volume_voxel_hyperslab( volume, v0, v1, 0, 0, 0, n0, n1, 0, 0, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_2D( void_ptr, volume->array, v0, v1 ) stride = 1; dim = 2; if( n1 > 1 ) { --dim; counts[dim] = n1; steps[dim] = stride; } stride *= sizes[1]; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = stride; } set_voxel_values( volume, void_ptr, 2 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void set_volume_voxel_hyperslab_1d( Volume volume, int v0, int n0, Real values[] ) { int steps[MAX_DIMENSIONS]; int counts[MAX_DIMENSIONS]; int sizes[MAX_DIMENSIONS]; int dim; void *void_ptr; if( volume->is_cached_volume ) { slow_set_volume_voxel_hyperslab( volume, v0, 0, 0, 0, 0, n0, 0, 0, 0, 0, values ); return; } get_volume_sizes( volume, sizes ); GET_MULTIDIM_PTR_1D( void_ptr, volume->array, v0 ) dim = 1; if( n0 > 1 ) { --dim; counts[dim] = n0; steps[dim] = 1; } set_voxel_values( volume, void_ptr, 1 - dim, &steps[dim], &counts[dim], values ); } VIOAPI void set_volume_voxel_hyperslab( Volume volume, int v0, int v1, int v2, int v3, int v4, int n0, int n1, int n2, int n3, int n4, Real voxels[] ) { switch( get_volume_n_dimensions(volume) ) { case 1: set_volume_voxel_hyperslab_1d( volume, v0, n0, voxels ); break; case 2: set_volume_voxel_hyperslab_2d( volume, v0, v1, n0, n1, voxels ); break; case 3: set_volume_voxel_hyperslab_3d( volume, v0, v1, v2, n0, n1, n2, voxels ); break; case 4: set_volume_voxel_hyperslab_4d( volume, v0, v1, v2, v3, n0, n1, n2, n3, voxels ); break; case 5: set_volume_voxel_hyperslab_5d( volume, v0, v1, v2, v3, v4, n0, n1, n2, n3, n4, voxels ); break; } } minc-2.2.00/volume_io/Volumes/volume_cache.c0000644000265600003100000013350212027132664015674 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #define HASH_FUNCTION_CONSTANT 0.6180339887498948482 #define HASH_TABLE_SIZE_FACTOR 3 #define DEFAULT_BLOCK_SIZE 64 #define DEFAULT_CACHE_THRESHOLD -1 #define DEFAULT_MAX_BYTES_IN_CACHE 100000000 static BOOLEAN n_bytes_cache_threshold_set = FALSE; static int n_bytes_cache_threshold = DEFAULT_CACHE_THRESHOLD; static BOOLEAN default_cache_size_set = FALSE; static int default_cache_size = DEFAULT_MAX_BYTES_IN_CACHE; static Cache_block_size_hints block_size_hint = RANDOM_VOLUME_ACCESS; static BOOLEAN default_block_sizes_set = FALSE; static int default_block_sizes[MAX_DIMENSIONS] = { DEFAULT_BLOCK_SIZE, DEFAULT_BLOCK_SIZE, DEFAULT_BLOCK_SIZE, DEFAULT_BLOCK_SIZE, DEFAULT_BLOCK_SIZE }; static void alloc_volume_cache( volume_cache_struct *cache, Volume volume ); #ifdef CACHE_DEBUGGING static void initialize_cache_debug( volume_cache_struct *cache ); static void record_cache_hit( volume_cache_struct *cache ); static void record_cache_prev_hit( volume_cache_struct *cache ); static void record_cache_no_hit( volume_cache_struct *cache ); #endif /* ----------------------------- MNI Header ----------------------------------- @NAME : set_n_bytes_cache_threshold @INPUT : threshold @OUTPUT : @RETURNS : @DESCRIPTION: Sets the threshold number of bytes which decides if a volume is small enough to be held entirely in memory, or whether it should be cached. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_n_bytes_cache_threshold( int threshold ) { n_bytes_cache_threshold = threshold; n_bytes_cache_threshold_set = TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_n_bytes_cache_threshold @INPUT : @OUTPUT : @RETURNS : number of bytes @DESCRIPTION: Returns the number of bytes defining the cache threshold. If it hasn't been set, returns the program initialized value, or the value set by the environment variable. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_n_bytes_cache_threshold( void ) { int n_bytes; if( !n_bytes_cache_threshold_set ) { if( getenv( "VOLUME_CACHE_THRESHOLD" ) != NULL && sscanf( getenv( "VOLUME_CACHE_THRESHOLD" ), "%d", &n_bytes ) == 1 ) { n_bytes_cache_threshold = n_bytes; } n_bytes_cache_threshold_set = TRUE; } return( n_bytes_cache_threshold ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_default_max_bytes_in_cache @INPUT : max_bytes @OUTPUT : @RETURNS : @DESCRIPTION: Sets the default value for the maximum amount of memory in a single volume's cache. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_default_max_bytes_in_cache( int max_bytes ) { default_cache_size_set = TRUE; default_cache_size = max_bytes; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_default_max_bytes_in_cache @INPUT : @OUTPUT : @RETURNS : number of bytes @DESCRIPTION: Returns the maximum number of bytes allowed for a single volume's cache. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_default_max_bytes_in_cache( void ) { int n_bytes; if( !default_cache_size_set ) { if( getenv( "VOLUME_CACHE_SIZE" ) != NULL && sscanf( getenv( "VOLUME_CACHE_SIZE" ), "%d", &n_bytes ) == 1 ) { default_cache_size = n_bytes; } default_cache_size_set = TRUE; } return( default_cache_size ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_default_cache_block_sizes @INPUT : block_sizes @OUTPUT : @RETURNS : @DESCRIPTION: Sets the default values for the volume cache block sizes. A non-positive value will result in a block size equal to the number of voxels in that dimension of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 19, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_default_cache_block_sizes( int block_sizes[] ) { int dim; for_less( dim, 0, MAX_DIMENSIONS ) default_block_sizes[dim] = block_sizes[dim]; default_block_sizes_set = TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_cache_block_sizes_hint @INPUT : hint @OUTPUT : @RETURNS : @DESCRIPTION: Sets the hint for deciding on block sizes. This turns off the default_block_sizes_set flag, thereby overriding any previous calls to set_default_cache_block_sizes(). @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 25, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_cache_block_sizes_hint( Cache_block_size_hints hint ) { block_size_hint = hint; default_block_sizes_set = FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_default_cache_block_sizes @INPUT : @OUTPUT : block_sizes[] @RETURNS : @DESCRIPTION: Passes back the size (in voxels) of each dimension of a cache block. If it hasn't been set, returns the program initialized value, or the value set by the environment variable. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void get_default_cache_block_sizes( int n_dims, int volume_sizes[], int block_sizes[] ) { int dim, block_size; if( !default_block_sizes_set && block_size_hint == SLICE_ACCESS ) { for_less( dim, 0, n_dims - 2 ) block_sizes[dim] = 1; /*--- set the last two dimensions to be entire size of dimension */ for_less( dim, MAX( 0, n_dims - 2), MAX_DIMENSIONS ) block_sizes[dim] = -1; } else if( !default_block_sizes_set && block_size_hint == RANDOM_VOLUME_ACCESS ) { if( getenv( "VOLUME_CACHE_BLOCK_SIZE" ) == NULL || sscanf( getenv( "VOLUME_CACHE_BLOCK_SIZE" ), "%d", &block_size ) != 1 || block_size < 1 ) { block_size = DEFAULT_BLOCK_SIZE; } for_less( dim, 0, MAX_DIMENSIONS ) block_sizes[dim] = block_size; } else { for_less( dim, 0, MAX_DIMENSIONS ) block_sizes[dim] = default_block_sizes[dim]; } /*--- now change any non-positive values to the correct volume size */ for_less( dim, 0, MAX_DIMENSIONS ) { if( block_sizes[dim] <= 0 || block_sizes[dim] > volume_sizes[dim] ) block_sizes[dim] = volume_sizes[dim]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : initialize_volume_cache @INPUT : cache volume @OUTPUT : @RETURNS : @DESCRIPTION: Initializes the cache for a volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void initialize_volume_cache( volume_cache_struct *cache, Volume volume ) { int dim, n_dims, sizes[MAX_DIMENSIONS]; n_dims = get_volume_n_dimensions( volume ); cache->n_dimensions = n_dims; cache->writing_to_temp_file = FALSE; for_less( dim, 0, MAX_DIMENSIONS ) cache->file_offset[dim] = 0; cache->minc_file = NULL; cache->input_filename = NULL; cache->output_filename = NULL; cache->original_filename = NULL; cache->history = NULL; set_default_minc_output_options( &cache->options ); cache->output_file_is_open = FALSE; cache->must_read_blocks_before_use = FALSE; get_volume_sizes( volume, sizes ); get_default_cache_block_sizes( n_dims, sizes, cache->block_sizes ); cache->max_cache_bytes = get_default_max_bytes_in_cache(); alloc_volume_cache( cache, volume ); #ifdef CACHE_DEBUGGING initialize_cache_debug( cache ); #endif } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_volume_cache @INPUT : cache volume @OUTPUT : @RETURNS : @DESCRIPTION: Allocates the volume cache. Uses the current value of the volumes max cache size and block sizes to decide how much to allocate. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void alloc_volume_cache( volume_cache_struct *cache, Volume volume ) { int dim, n_dims, sizes[MAX_DIMENSIONS], block, block_size; int x, block_stride, remainder, block_index; get_volume_sizes( volume, sizes ); n_dims = get_volume_n_dimensions( volume ); /*--- count number of blocks needed per dimension */ block_size = 1; block_stride = 1; for_down( dim, n_dims - 1, 0 ) { cache->blocks_per_dim[dim] = (sizes[dim] - 1) / cache->block_sizes[dim] + 1; ALLOC( cache->lookup[dim], sizes[dim] ); for_less( x, 0, sizes[dim] ) { remainder = x % cache->block_sizes[dim]; block_index = x / cache->block_sizes[dim]; cache->lookup[dim][x].block_index_offset = block_index * block_stride; cache->lookup[dim][x].block_offset = remainder * block_size; } block_size *= cache->block_sizes[dim]; block_stride *= cache->blocks_per_dim[dim]; } cache->total_block_size = block_size; cache->max_blocks = cache->max_cache_bytes / block_size / get_type_size(get_volume_data_type(volume)); if( cache->max_blocks < 1 ) cache->max_blocks = 1; /*--- create and initialize an empty hash table */ cache->hash_table_size = cache->max_blocks * HASH_TABLE_SIZE_FACTOR; ALLOC( cache->hash_table, cache->hash_table_size ); for_less( block, 0, cache->hash_table_size ) cache->hash_table[block] = NULL; /*--- set up the initial pointers */ cache->previous_block_index = -1; cache->head = NULL; cache->tail = NULL; cache->n_blocks = 0; } VIOAPI BOOLEAN volume_cache_is_alloced( volume_cache_struct *cache ) { return( cache->hash_table != NULL ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_block_start @INPUT : cache block_index @OUTPUT : block_start[] @RETURNS : @DESCRIPTION: Computes the starting voxel indices for a block. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void get_block_start( volume_cache_struct *cache, int block_index, int block_start[] ) { int dim, block_i; for_down( dim, cache->n_dimensions-1, 0 ) { block_i = block_index % cache->blocks_per_dim[dim]; block_start[dim] = block_i * cache->block_sizes[dim]; block_index /= cache->blocks_per_dim[dim]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : write_cache_block @INPUT : cache volume block @OUTPUT : @RETURNS : @DESCRIPTION: Writes out a cache block to the appropriate position in the corresponding file. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void write_cache_block( volume_cache_struct *cache, Volume volume, cache_block_struct *block ) { Minc_file minc_file; int dim, ind, n_dims; int file_start[MAX_DIMENSIONS]; int file_count[MAX_DIMENSIONS]; int volume_sizes[MAX_DIMENSIONS]; int block_start[MAX_DIMENSIONS]; void *array_data_ptr; minc_file = (Minc_file) cache->minc_file; get_block_start( cache, block->block_index, block_start ); get_volume_sizes( volume, volume_sizes ); for_less( dim, 0, minc_file->n_file_dimensions ) { ind = minc_file->to_volume_index[dim]; if( ind >= 0 ) { file_start[dim] = cache->file_offset[dim] + block_start[ind]; file_count[dim] = MIN( volume_sizes[ind] - file_start[dim], cache->block_sizes[ind] ); } else { file_start[dim] = cache->file_offset[dim]; file_count[dim] = 0; } } GET_MULTIDIM_PTR( array_data_ptr, block->array, 0, 0, 0, 0, 0 ); n_dims = cache->n_dimensions; (void) output_minc_hyperslab( (Minc_file) cache->minc_file, get_multidim_data_type(&block->array), n_dims, cache->block_sizes, array_data_ptr, minc_file->to_volume_index, file_start, file_count ); cache->must_read_blocks_before_use = TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : flush_cache_blocks @INPUT : cache volume deleting_volume_flag @OUTPUT : @RETURNS : @DESCRIPTION: Writes out all blocks that have been modified, unless we are writing to a temporary file and the volume is being deleted. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void flush_cache_blocks( volume_cache_struct *cache, Volume volume, BOOLEAN deleting_volume_flag ) { cache_block_struct *block; /*--- don't bother flushing if deleting volume and just writing to temp */ if( cache->writing_to_temp_file && deleting_volume_flag ) return; /*--- step through linked list, freeing blocks */ block = cache->head; while( block != NULL ) { if( block->modified_flag ) { write_cache_block( cache, volume, block ); block->modified_flag = FALSE; } block = block->next_used; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : flush_volume_cache @INPUT : volume @OUTPUT : @RETURNS : @DESCRIPTION: Writes out all blocks that have been modified. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void flush_volume_cache( Volume volume ) { flush_cache_blocks( &volume->cache, volume, FALSE ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_cache_blocks @INPUT : cache volume deleting_volume_flag - TRUE if deleting the volume @OUTPUT : @RETURNS : @DESCRIPTION: Deletes all cache blocks, writing out all blocks, if the volume has been modified. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void delete_cache_blocks( volume_cache_struct *cache, Volume volume, BOOLEAN deleting_volume_flag ) { int block; cache_block_struct *current, *next; /*--- if required, write out cache blocks */ if( !cache->writing_to_temp_file || !deleting_volume_flag ) flush_cache_blocks( cache, volume, deleting_volume_flag ); /*--- step through linked list, freeing blocks */ current = cache->head; while( current != NULL ) { next = current->next_used; delete_multidim_array( ¤t->array ); FREE( current ); current = next; } /*--- initialize cache to no blocks present */ cache->n_blocks = 0; for_less( block, 0, cache->hash_table_size ) cache->hash_table[block] = NULL; cache->previous_block_index = -1; cache->head = NULL; cache->tail = NULL; } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_volume_cache @INPUT : cache volume @OUTPUT : @RETURNS : @DESCRIPTION: Deletes the volume cache. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void delete_volume_cache( volume_cache_struct *cache, Volume volume ) { int dim, n_dims; delete_cache_blocks( cache, volume, TRUE ); FREE( cache->hash_table ); cache->hash_table = NULL; n_dims = cache->n_dimensions; for_less( dim, 0, n_dims ) { FREE( cache->lookup[dim] ); } delete_string( cache->input_filename ); delete_string( cache->output_filename ); delete_string( cache->original_filename ); delete_string( cache->history ); delete_minc_output_options( &cache->options ); /*--- close the file that cache was reading from or writing to */ if( cache->minc_file != NULL ) { if( cache->output_file_is_open ) { (void) close_minc_output( (Minc_file) cache->minc_file ); } else (void) close_minc_input( (Minc_file) cache->minc_file ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_cache_block_sizes @INPUT : volume block_sizes @OUTPUT : @RETURNS : @DESCRIPTION: Changes the sizes of the cache blocks for the volume, if it is a cached volume. This flushes the cache blocks, since they have changed. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 24, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_cache_block_sizes( Volume volume, int block_sizes[] ) { volume_cache_struct *cache; int d, dim, sizes[N_DIMENSIONS]; BOOLEAN changed; if( !volume->is_cached_volume ) return; cache = &volume->cache; get_volume_sizes( volume, sizes ); changed = FALSE; for_less( d, 0, get_volume_n_dimensions(volume) ) { if( block_sizes[d] < 1 || block_sizes[d] > sizes[d] ) block_sizes[d] = sizes[d]; if( cache->block_sizes[d] != block_sizes[d] ) changed = TRUE; } /*--- if the block sizes have not changed, do nothing */ if( !changed ) return; delete_cache_blocks( cache, volume, FALSE ); FREE( cache->hash_table ); for_less( dim, 0, get_volume_n_dimensions( volume ) ) { FREE( cache->lookup[dim] ); } for_less( d, 0, get_volume_n_dimensions(volume) ) cache->block_sizes[d] = block_sizes[d]; alloc_volume_cache( cache, volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_cache_size @INPUT : volume max_memory_bytes @OUTPUT : @RETURNS : @DESCRIPTION: Changes the maximum amount of memory in the cache for this volume, if it is a cached volume. This flushes the cache, in order to reallocate the hash table to a new size. @METHOD : @GLOBALS : @CALLS : @CREATED : Oct. 24, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_cache_size( Volume volume, int max_memory_bytes ) { int dim; volume_cache_struct *cache; if( !volume->is_cached_volume ) return; cache = &volume->cache; delete_cache_blocks( cache, volume, FALSE ); FREE( cache->hash_table ); for_less( dim, 0, get_volume_n_dimensions( volume ) ) { FREE( cache->lookup[dim] ); } cache->max_cache_bytes = max_memory_bytes; alloc_volume_cache( cache, volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_cache_output_volume_parameters @INPUT : volume filename file_nc_data_type file_signed_flag file_voxel_min file_voxel_max original_filename - if non-NULL copies auxiliary info from this history options @OUTPUT : @RETURNS : @DESCRIPTION: Indicates that rather than using a temporary file for the cached volume, read and write to this file with the associated parameters (similar to output_modified_volume()). @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 4, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_cache_output_volume_parameters( Volume volume, STRING filename, nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, STRING original_filename, STRING history, minc_output_options *options ) { volume->cache.output_filename = create_string( filename ); volume->cache.file_nc_data_type = file_nc_data_type; volume->cache.file_signed_flag = file_signed_flag; volume->cache.file_voxel_min = file_voxel_min; volume->cache.file_voxel_max = file_voxel_max; volume->cache.original_filename = create_string( original_filename ); volume->cache.history = create_string( history ); copy_minc_output_options( options, &volume->cache.options ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : open_cache_volume_input_file @INPUT : cache volume filename options @OUTPUT : @RETURNS : @DESCRIPTION: Opens the volume file for reading into the cache as needed. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void open_cache_volume_input_file( volume_cache_struct *cache, Volume volume, STRING filename, minc_input_options *options ) { cache->input_filename = create_string( filename ); cache->minc_file = initialize_minc_input( filename, volume, options ); cache->must_read_blocks_before_use = TRUE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : open_cache_volume_output_file @INPUT : cache volume @OUTPUT : @RETURNS : @DESCRIPTION: Opens a volume file for reading and writing cache blocks. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Status open_cache_volume_output_file( volume_cache_struct *cache, Volume volume ) { Status status; int dim, n_dims; int out_sizes[MAX_DIMENSIONS], vol_sizes[MAX_DIMENSIONS]; Real min_value, max_value; Minc_file out_minc_file; STRING *vol_dim_names; STRING *out_dim_names, output_filename; n_dims = get_volume_n_dimensions( volume ); /*--- check if the output filename has been set */ if( string_length( cache->output_filename ) == 0 ) { cache->writing_to_temp_file = TRUE; output_filename = get_temporary_filename(); cache->file_nc_data_type = get_volume_nc_data_type( volume, &cache->file_signed_flag ); get_volume_voxel_range( volume, &cache->file_voxel_min, &cache->file_voxel_max ); ALLOC( out_dim_names, n_dims ); vol_dim_names = get_volume_dimension_names( volume ); get_volume_sizes( volume, vol_sizes ); for_less( dim, 0, n_dims ) { out_dim_names[dim] = create_string( vol_dim_names[dim] ); out_sizes[dim] = vol_sizes[dim]; } delete_dimension_names( volume, vol_dim_names ); } else { cache->writing_to_temp_file = FALSE; output_filename = create_string( cache->output_filename ); out_dim_names = create_output_dim_names( volume, cache->original_filename, &cache->options, out_sizes ); if( out_dim_names == NULL ) return( ERROR ); } get_volume_real_range( volume, &min_value, &max_value ); set_minc_output_real_range( &cache->options, min_value, max_value ); /*--- open the file for writing */ out_minc_file = initialize_minc_output( output_filename, n_dims, out_dim_names, out_sizes, cache->file_nc_data_type, cache->file_signed_flag, cache->file_voxel_min, cache->file_voxel_max, get_voxel_to_world_transform(volume), volume, &cache->options ); if( out_minc_file == NULL ) return( ERROR ); status = copy_volume_auxiliary_and_history( out_minc_file, output_filename, cache->original_filename, cache->history ); if( status != OK ) return( status ); out_minc_file->converting_to_colour = FALSE; /*--- make temp file disappear when the volume is deleted */ if( string_length( cache->output_filename ) == 0 ) remove_file( output_filename ); status = set_minc_output_random_order( out_minc_file ); if( status != OK ) return( status ); /*--- if the volume was previously reading a file, copy the volume to the output and close the input file */ if( cache->minc_file != NULL ) { (void) output_minc_volume( out_minc_file ); (void) close_minc_input( (Minc_file) cache->minc_file ); cache->must_read_blocks_before_use = TRUE; } cache->minc_file = out_minc_file; delete_dimension_names( volume, out_dim_names ); delete_string( output_filename ); return( OK ); } VIOAPI void cache_volume_range_has_changed( Volume volume ) { if( !volume->is_cached_volume ) return; if( volume->cache.minc_file == NULL && volume->cache.n_blocks == 0 ) return; /* This message is not useful. print( "Not implemented yet in cache_volume_range_has_changed()\n" ); */ } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_cache_volume_file_offset @INPUT : cache volume file_offset @OUTPUT : @RETURNS : @DESCRIPTION: Sets the offset in the file for writing volumes. Used when writing several cached volumes to a file. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_cache_volume_file_offset( volume_cache_struct *cache, Volume volume, long file_offset[] ) { BOOLEAN changed; int dim; changed = FALSE; for_less( dim, 0, MAX_DIMENSIONS ) { if( cache->file_offset[dim] != (int) file_offset[dim] ) changed = TRUE; cache->file_offset[dim] = (int) file_offset[dim]; } if( changed ) delete_cache_blocks( cache, volume, FALSE ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : read_cache_block @INPUT : cache volume block block_start @OUTPUT : @RETURNS : @DESCRIPTION: Reads one cache block. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void read_cache_block( volume_cache_struct *cache, Volume volume, cache_block_struct *block, int block_start[] ) { Minc_file minc_file; int dim, ind, n_dims; int sizes[MAX_DIMENSIONS]; int file_start[MAX_DIMENSIONS]; int file_count[MAX_DIMENSIONS]; void *array_data_ptr; minc_file = (Minc_file) cache->minc_file; get_volume_sizes( volume, sizes ); for_less( dim, 0, minc_file->n_file_dimensions ) { ind = minc_file->to_volume_index[dim]; if( ind >= 0 ) { file_start[dim] = cache->file_offset[dim] + block_start[ind]; file_count[dim] = MIN( sizes[ind] - file_start[dim], cache->block_sizes[ind] ); } else { file_start[dim] = cache->file_offset[dim]; file_count[dim] = 0; } } n_dims = cache->n_dimensions; GET_MULTIDIM_PTR( array_data_ptr, block->array, 0, 0, 0, 0, 0 ); (void) input_minc_hyperslab( (Minc_file) cache->minc_file, get_multidim_data_type(&block->array), n_dims, cache->block_sizes, array_data_ptr, minc_file->to_volume_index, file_start, file_count ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : appropriate_a_cache_block @INPUT : cache volume @OUTPUT : block @RETURNS : @DESCRIPTION: Finds an available cache block, either by allocating one, or stealing the least recently used one. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static cache_block_struct *appropriate_a_cache_block( volume_cache_struct *cache, Volume volume ) { cache_block_struct *block; /*--- if can allocate more blocks, do so */ if( cache->n_blocks < cache->max_blocks ) { ALLOC( block, 1 ); create_multidim_array( &block->array, 1, &cache->total_block_size, get_volume_data_type(volume) ); ++cache->n_blocks; } else /*--- otherwise, steal the least-recently used block */ { block = cache->tail; if( block->modified_flag ) write_cache_block( cache, volume, block ); /*--- remove from used list */ if( block->prev_used == NULL ) cache->head = block->next_used; else block->prev_used->next_used = block->next_used; if( block->next_used == NULL ) cache->tail = block->prev_used; else block->next_used->prev_used = block->prev_used; /*--- remove from hash table */ *block->prev_hash = block->next_hash; if( block->next_hash != NULL ) block->next_hash->prev_hash = block->prev_hash; } block->modified_flag = FALSE; return( block ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : hash_block_index @INPUT : key table_size @OUTPUT : @RETURNS : hash address @DESCRIPTION: Hashes a block index key into a table index, using multiplicative hashing. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static int hash_block_index( int key, int table_size ) { int index; Real v; v = (Real) key * HASH_FUNCTION_CONSTANT; index = (int) (( v - (Real) ((int) v)) * (Real) table_size); return( index ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_cache_block_for_voxel @INPUT : volume x y z t v @OUTPUT : offset @RETURNS : pointer to cache block @DESCRIPTION: Finds the cache block corresponding to a given voxel, and modifies the voxel indices to be block indices. This function gets called for every set or get voxel value, so it must be efficient. On return, offset contains the integer offset of the voxel within the cache block. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static cache_block_struct *get_cache_block_for_voxel( Volume volume, int x, int y, int z, int t, int v, int *offset ) { cache_block_struct *block; cache_lookup_struct *lookup0, *lookup1, *lookup2, *lookup3, *lookup4; int block_index; int block_start[MAX_DIMENSIONS]; int n_dims, hash_index; volume_cache_struct *cache; cache = &volume->cache; n_dims = cache->n_dimensions; switch( n_dims ) { case 1: lookup0 = &cache->lookup[0][x]; block_index = lookup0->block_index_offset; *offset = lookup0->block_offset; break; case 2: lookup0 = &cache->lookup[0][x]; lookup1 = &cache->lookup[1][y]; block_index = lookup0->block_index_offset + lookup1->block_index_offset; *offset = lookup0->block_offset + lookup1->block_offset; break; case 3: lookup0 = &cache->lookup[0][x]; lookup1 = &cache->lookup[1][y]; lookup2 = &cache->lookup[2][z]; block_index = lookup0->block_index_offset + lookup1->block_index_offset + lookup2->block_index_offset; *offset = lookup0->block_offset + lookup1->block_offset + lookup2->block_offset; break; case 4: lookup0 = &cache->lookup[0][x]; lookup1 = &cache->lookup[1][y]; lookup2 = &cache->lookup[2][z]; lookup3 = &cache->lookup[3][t]; block_index = lookup0->block_index_offset + lookup1->block_index_offset + lookup2->block_index_offset + lookup3->block_index_offset; *offset = lookup0->block_offset + lookup1->block_offset + lookup2->block_offset + lookup3->block_offset; break; case 5: lookup0 = &cache->lookup[0][x]; lookup1 = &cache->lookup[1][y]; lookup2 = &cache->lookup[2][z]; lookup3 = &cache->lookup[3][t]; lookup4 = &cache->lookup[4][v]; block_index = lookup0->block_index_offset + lookup1->block_index_offset + lookup2->block_index_offset + lookup3->block_index_offset + lookup4->block_index_offset; *offset = lookup0->block_offset + lookup1->block_offset + lookup2->block_offset + lookup3->block_offset + lookup4->block_offset; break; } /*--- if this is the same as the last access, just return the last block accessed */ if( block_index == cache->previous_block_index ) { #ifdef CACHE_DEBUGGING record_cache_prev_hit( cache ); #endif return( cache->previous_block ); } /*--- search the hash table for the block index */ hash_index = hash_block_index( block_index, cache->hash_table_size ); block = cache->hash_table[hash_index]; while( block != NULL && block->block_index != block_index ) { block = block->next_hash; } /*--- check if it was found in the hash table */ if( block == NULL ) { #ifdef CACHE_DEBUGGING record_cache_no_hit( cache ); #endif /*--- find a block to use */ block = appropriate_a_cache_block( cache, volume ); block->block_index = block_index; /*--- check if the block must be initialized from a file */ if( cache->must_read_blocks_before_use ) { get_block_start( cache, block_index, block_start ); read_cache_block( cache, volume, block, block_start ); } /*--- insert the block in cache hash table */ block->next_hash = cache->hash_table[hash_index]; if( block->next_hash != NULL ) block->next_hash->prev_hash = &block->next_hash; block->prev_hash = &cache->hash_table[hash_index]; *block->prev_hash = block; /*--- insert the block at the head of the used list */ block->prev_used = NULL; block->next_used = cache->head; if( cache->head == NULL ) cache->tail = block; else cache->head->prev_used = block; cache->head = block; } else /*--- block was found in hash table */ { #ifdef CACHE_DEBUGGING record_cache_hit( cache ); #endif /*--- move block to head of used list */ if( block != cache->head ) { block->prev_used->next_used = block->next_used; if( block->next_used != NULL ) block->next_used->prev_used = block->prev_used; else cache->tail = block->prev_used; cache->head->prev_used = block; block->prev_used = NULL; block->next_used = cache->head; cache->head = block; } /*--- move block to beginning of hash chain, so if next access to this block, we will save some time */ if( cache->hash_table[hash_index] != block ) { /*--- remove it from where it is */ *block->prev_hash = block->next_hash; if( block->next_hash != NULL ) block->next_hash->prev_hash = block->prev_hash; /*--- place it at the front of the list */ block->next_hash = cache->hash_table[hash_index]; if( block->next_hash != NULL ) block->next_hash->prev_hash = &block->next_hash; block->prev_hash = &cache->hash_table[hash_index]; *block->prev_hash = block; } } /*--- record so if next access is to same block, we save some time */ cache->previous_block = block; cache->previous_block_index = block_index; return( cache->previous_block ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_cached_volume_voxel @INPUT : volume x y z t v @OUTPUT : @RETURNS : voxel value @DESCRIPTION: Finds the voxel value for the given voxel in a cached volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_cached_volume_voxel( Volume volume, int x, int y, int z, int t, int v ) { int offset; Real value; cache_block_struct *block; if( volume->cache.minc_file == NULL ) return( get_volume_voxel_min( volume ) ); block = get_cache_block_for_voxel( volume, x, y, z, t, v, &offset ); GET_MULTIDIM_1D( value, (Real), block->array, offset ); return( value ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_cached_volume_voxel @INPUT : volume x y z t v value @OUTPUT : @RETURNS : @DESCRIPTION: Sets the voxel value for the given voxel in a cached volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_cached_volume_voxel( Volume volume, int x, int y, int z, int t, int v, Real value ) { int offset; cache_block_struct *block; if( !volume->cache.output_file_is_open ) { (void) open_cache_volume_output_file( &volume->cache, volume ); volume->cache.output_file_is_open = TRUE; } block = get_cache_block_for_voxel( volume, x, y, z, t, v, &offset ); block->modified_flag = TRUE; SET_MULTIDIM_1D( block->array, offset, value ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : cached_volume_has_been_modified @INPUT : cache @OUTPUT : @RETURNS : TRUE if the volume has been modified since creation @DESCRIPTION: Determines if the volume has been modified. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN cached_volume_has_been_modified( volume_cache_struct *cache ) { return( cache->minc_file != NULL ); } VIOAPI BOOLEAN volume_is_cached( Volume volume ) { return( volume->is_cached_volume ); } #ifndef CACHE_DEBUGGING /* ARGSUSED */ #endif VIOAPI void set_volume_cache_debugging( Volume volume, int output_every ) { #ifdef CACHE_DEBUGGING if( output_every >= 1 ) { volume->cache.debugging_on = TRUE; volume->cache.output_every = output_every; } else { volume->cache.debugging_on = FALSE; } #endif } #ifdef CACHE_DEBUGGING static void initialize_cache_debug( volume_cache_struct *cache ) { int output_every; STRING debug; debug = getenv( "VOLUME_CACHE_DEBUG" ); cache->debugging_on = (debug != NULL); if( debug == NULL || sscanf( debug, "%d", &output_every ) != 1 || output_every < 1 ) { output_every = 1000; } cache->output_every = output_every; cache->n_accesses = 0; cache->n_hits = 0; cache->n_prev_hits = 0; } static void increment_n_accesses( volume_cache_struct *cache ) { ++cache->n_accesses; if( cache->n_accesses >= cache->output_every ) { print( "Volume cache: Hit ratio: %g Prev ratio: %g\n", (Real) (cache->n_hits + cache->n_prev_hits) / (Real) cache->n_accesses, (Real) cache->n_prev_hits / (Real) cache->n_accesses ); cache->n_accesses = 0; cache->n_hits = 0; cache->n_prev_hits = 0; } } static void record_cache_hit( volume_cache_struct *cache ) { if( cache->debugging_on ) { ++cache->n_hits; increment_n_accesses( cache ); } } static void record_cache_prev_hit( volume_cache_struct *cache ) { if( cache->debugging_on ) { ++cache->n_prev_hits; increment_n_accesses( cache ); } } static void record_cache_no_hit( volume_cache_struct *cache ) { if( cache->debugging_on ) { increment_n_accesses( cache ); } } #endif minc-2.2.00/volume_io/Volumes/volumes.c0000644000265600003100000023357312027132664014745 00000000000000/* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ #include #include #include STRING XYZ_dimension_names[] = { MIxspace, MIyspace, MIzspace }; STRING File_order_dimension_names[] = { "", "", "", "", "" }; static STRING default_dimension_names[MAX_DIMENSIONS][MAX_DIMENSIONS] = { { MIxspace }, { MIyspace, MIxspace }, { MIzspace, MIyspace, MIxspace }, { "", MIzspace, MIyspace, MIxspace }, { "", "", MIzspace, MIyspace, MIxspace } }; /* ----------------------------- MNI Header ----------------------------------- @NAME : get_default_dim_names @INPUT : n_dimensions @OUTPUT : @RETURNS : list of dimension names @DESCRIPTION: Returns the list of default dimension names for the given number of dimensions. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING *get_default_dim_names( int n_dimensions ) { return( default_dimension_names[n_dimensions-1] ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_spatial_axis_to_dim_name @INPUT : axis @OUTPUT : @RETURNS : dimension name @DESCRIPTION: Returns the name of the dimension. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static STRING convert_spatial_axis_to_dim_name( int axis ) { switch( axis ) { case X: return( MIxspace ); case Y: return( MIyspace ); case Z: return( MIzspace ); default: handle_internal_error( "convert_spatial_axis_to_dim_name" ); break; } return( NULL ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_dim_name_to_spatial_axis @INPUT : dimension_name @OUTPUT : axis @RETURNS : TRUE if axis name is a spatial dimension @DESCRIPTION: Checks if the dimension name corresponds to a spatial dimension and if so, passes back the corresponding axis index. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN convert_dim_name_to_spatial_axis( STRING name, int *axis ) { *axis = -1; if( equal_strings( name, MIxspace ) ) *axis = X; else if( equal_strings( name, MIyspace ) ) *axis = Y; else if( equal_strings( name, MIzspace ) ) *axis = Z; return( *axis >= 0 ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : create_volume @INPUT : n_dimensions - number of dimensions (1-5) dimension_names - name of dimensions for use when reading file data_type - type of the data, e.g. NC_BYTE signed_flag - type is signed? min_value - min and max value to be stored max_value @OUTPUT : @RETURNS : Volume @DESCRIPTION: Creates a Volume structure, and initializes it. In order to later use the volume, you must call either set_volume_size() and alloc_volume_data(), or one of the input volume routines, which in turn calls these two. The dimension_names are used when inputting MINC files, in order to match with the dimension names in the file. Typically, use dimension names { MIzspace, MIyspace, MIxspace } to read the volume from the file in the order it is stored, or { MIxspace, MIyspace, MIzspace } to read it so you can subcript the volume in x, y, z order. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : Nov. 15, 1996 D. MacDonald - handles space type @MODIFIED : May 22, 1996 D. MacDonald - now stores starts/steps ---------------------------------------------------------------------------- */ VIOAPI Volume create_volume( int n_dimensions, STRING dimension_names[], nc_type nc_data_type, BOOLEAN signed_flag, Real voxel_min, Real voxel_max ) { int i, axis, sizes[MAX_DIMENSIONS]; Status status; STRING name; volume_struct *volume; Transform identity; status = OK; if( n_dimensions < 1 || n_dimensions > MAX_DIMENSIONS ) { print_error( "create_volume(): n_dimensions (%d) not in range 1 to %d.\n", n_dimensions, MAX_DIMENSIONS ); status = ERROR; } if( status == ERROR ) { return( (Volume) NULL ); } ALLOC( volume, 1 ); volume->is_rgba_data = FALSE; volume->is_cached_volume = FALSE; volume->real_range_set = FALSE; volume->real_value_scale = 1.0; volume->real_value_translation = 0.0; for_less( i, 0, N_DIMENSIONS ) volume->spatial_axes[i] = -1; for_less( i, 0, n_dimensions ) { volume->starts[i] = 0.0; volume->separations[i] = 1.0; volume->direction_cosines[i][X] = 0.0; volume->direction_cosines[i][Y] = 0.0; volume->direction_cosines[i][Z] = 0.0; volume->irregular_starts[i] = NULL; volume->irregular_widths[i] = NULL; sizes[i] = 0; if( dimension_names != (char **) NULL ) name = dimension_names[i]; else name = default_dimension_names[n_dimensions-1][i]; if( convert_dim_name_to_spatial_axis( name, &axis ) ) { volume->spatial_axes[axis] = i; volume->direction_cosines[i][axis] = 1.0; } volume->dimension_names[i] = create_string( name ); } create_empty_multidim_array( &volume->array, n_dimensions, NO_DATA_TYPE ); set_volume_type( volume, nc_data_type, signed_flag, voxel_min, voxel_max ); set_volume_sizes( volume, sizes ); make_identity_transform( &identity ); create_linear_transform( &volume->voxel_to_world_transform, &identity ); volume->voxel_to_world_transform_uptodate = TRUE; volume->coordinate_system_name = create_string( MI_UNKNOWN_SPACE ); return( volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_type @INPUT : volume nc_data_type signed_flag voxel_min voxel_max @OUTPUT : @RETURNS : @DESCRIPTION: Sets the data type and valid range of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_type( Volume volume, nc_type nc_data_type, BOOLEAN signed_flag, Real voxel_min, Real voxel_max ) { Data_types data_type; if( nc_data_type != MI_ORIGINAL_TYPE ) { switch( nc_data_type ) { case NC_BYTE: if( signed_flag ) data_type = SIGNED_BYTE; else data_type = UNSIGNED_BYTE; break; case NC_SHORT: if( signed_flag ) data_type = SIGNED_SHORT; else data_type = UNSIGNED_SHORT; break; case NC_INT: if( signed_flag ) data_type = SIGNED_INT; else data_type = UNSIGNED_INT; break; case NC_FLOAT: data_type = FLOAT; break; case NC_DOUBLE: data_type = DOUBLE; break; } set_multidim_data_type( &volume->array, data_type ); volume->signed_flag = signed_flag; set_volume_voxel_range( volume, voxel_min, voxel_max ); } volume->nc_data_type = nc_data_type; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_nc_data_type @INPUT : volume @OUTPUT : signed_flag @RETURNS : data type @DESCRIPTION: Returns the NETCDF data type of the volume and passes back the signed flag. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI nc_type get_volume_nc_data_type( Volume volume, BOOLEAN *signed_flag ) { if( signed_flag != (BOOLEAN *) NULL ) *signed_flag = volume->signed_flag; return( volume->nc_data_type ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_data_type @INPUT : volume @OUTPUT : @RETURNS : data type @DESCRIPTION: Returns the data type of the volume (not the NETCDF type). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Data_types get_volume_data_type( Volume volume ) { return( get_multidim_data_type( &volume->array ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_rgb_volume_flag @INPUT : volume flag @OUTPUT : @RETURNS : @DESCRIPTION: Sets the flag indicating that the volume is an RGB volume. Can only set the flag to TRUE if the volume is an unsigned long volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov 13, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_rgb_volume_flag( Volume volume, BOOLEAN flag ) { if( !flag || get_volume_data_type(volume) == UNSIGNED_INT ) volume->is_rgba_data = flag; } /* ----------------------------- MNI Header ----------------------------------- @NAME : is_an_rgb_volume @INPUT : volume @OUTPUT : @RETURNS : TRUE if it is an RGB volume @DESCRIPTION: Tests if the volume is an RGB volume. @METHOD : @GLOBALS : @CALLS : @CREATED : Jun 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN is_an_rgb_volume( Volume volume ) { return( volume->is_rgba_data ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : alloc_volume_data @INPUT : volume @OUTPUT : @RETURNS : @DESCRIPTION: Allocates the memory for the volume. Assumes that the volume type and sizes have been set. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void alloc_volume_data( Volume volume ) { unsigned long data_size; data_size = (unsigned long) get_volume_total_n_voxels( volume ) * (unsigned long) get_type_size( get_volume_data_type( volume ) ); if( get_n_bytes_cache_threshold() >= 0 && data_size > (unsigned long) get_n_bytes_cache_threshold() ) { volume->is_cached_volume = TRUE; initialize_volume_cache( &volume->cache, volume ); } else { volume->is_cached_volume = FALSE; alloc_multidim_array( &volume->array ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : volume_is_alloced @INPUT : volume @OUTPUT : @RETURNS : TRUE if the volume is allocated @DESCRIPTION: Checks if the volume data has been allocated. @METHOD : @GLOBALS : @CALLS : @CREATED : Sep. 1, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI BOOLEAN volume_is_alloced( Volume volume ) { return( volume->is_cached_volume && volume_cache_is_alloced( &volume->cache ) || !volume->is_cached_volume && multidim_array_is_alloced( &volume->array ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : free_volume_data @INPUT : volume @OUTPUT : @RETURNS : @DESCRIPTION: Frees the memory associated with the volume multidimensional data. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void free_volume_data( Volume volume ) { if( volume->is_cached_volume ) delete_volume_cache( &volume->cache, volume ); else if( volume_is_alloced( volume ) ) delete_multidim_array( &volume->array ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_volume @INPUT : volume @OUTPUT : @RETURNS : @DESCRIPTION: Frees all memory from the volume and the volume struct itself. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : Nov. 15, 1996 D. MacDonald - handles space type ---------------------------------------------------------------------------- */ VIOAPI void delete_volume( Volume volume ) { int d; if( volume == (Volume) NULL ) { print_error( "delete_volume(): cannot delete a null volume.\n" ); return; } free_volume_data( volume ); delete_general_transform( &volume->voxel_to_world_transform ); for_less( d, 0, get_volume_n_dimensions(volume) ) { delete_string( volume->dimension_names[d] ); if( volume->irregular_starts[d] ) FREE( volume->irregular_starts[d] ); if( volume->irregular_widths[d] ) FREE( volume->irregular_widths[d] ); } delete_string( volume->coordinate_system_name ); FREE( volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_n_dimensions @INPUT : volume @OUTPUT : @RETURNS : number of dimensions @DESCRIPTION: Returns the number of dimensions of the volume @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI int get_volume_n_dimensions( Volume volume ) { return( get_multidim_n_dimensions( &volume->array ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_sizes @INPUT : volume @OUTPUT : sizes @RETURNS : @DESCRIPTION: Passes back the sizes of each of the dimensions. Assumes sizes has enough room for n_dimensions integers. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_volume_sizes( Volume volume, int sizes[] ) { get_multidim_sizes( &volume->array, sizes ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_sizes @INPUT : volume sizes @OUTPUT : @RETURNS : @DESCRIPTION: Sets the sizes (number of voxels in each dimension) of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_sizes( Volume volume, int sizes[] ) { set_multidim_sizes( &volume->array, sizes ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_total_n_voxels @INPUT : volume @OUTPUT : @RETURNS : n voxels @DESCRIPTION: Returns the total number of voxels in the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI unsigned int get_volume_total_n_voxels( Volume volume ) { unsigned int n; int i, sizes[MAX_DIMENSIONS]; n = 1; get_volume_sizes( volume, sizes ); for_less( i, 0, get_volume_n_dimensions( volume ) ) n *= (unsigned int) sizes[i]; return( n ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : assign_voxel_to_world_transform @INPUT : volume transform @OUTPUT : @RETURNS : @DESCRIPTION: Updates the volume's transformation from voxel to world coords. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 D. MacDonald - created from set_voxel_to_world_transform @MODIFIED : ---------------------------------------------------------------------------- */ static void assign_voxel_to_world_transform( Volume volume, General_transform *transform ) { delete_general_transform( &volume->voxel_to_world_transform ); volume->voxel_to_world_transform = *transform; } /* ----------------------------- MNI Header ----------------------------------- @NAME : dot_vectors @INPUT : n v1 v2 @OUTPUT : @RETURNS : Dot product @DESCRIPTION: Computes the dot product of 2 n-dimensional vectors. This function should be moved to some vector routines. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static Real dot_vectors( int n, Real v1[], Real v2[] ) { int i; Real d; d = 0.0; for_less( i, 0, n ) d += v1[i] * v2[i]; return( d ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : cross_3D_vector @INPUT : v1 v2 @OUTPUT : cross @RETURNS : @DESCRIPTION: Computes the cross product of 2 n-dimensional vectors. This function should be moved to some vector routines. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void cross_3D_vector( Real v1[], Real v2[], Real cross[] ) { cross[0] = v1[1] * v2[2] - v1[2] * v2[1]; cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; cross[2] = v1[0] * v2[1] - v1[1] * v2[0]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : normalize_vector @INPUT : n v1 @OUTPUT : v1_normalized @RETURNS : @DESCRIPTION: Normalizes the length of v1 to 1, placing result in v1_normalized @METHOD : @GLOBALS : @CALLS : @CREATED : May 22, 1997 D. MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void normalize_vector( Real v1[], Real v1_normalized[] ) { int d; Real mag; mag = dot_vectors( N_DIMENSIONS, v1, v1 ); if( mag <= 0.0 ) mag = 1.0; mag = sqrt( mag ); for_less( d, 0, N_DIMENSIONS ) v1_normalized[d] = v1[d] / mag; } /* ----------------------------- MNI Header ----------------------------------- @NAME : compute_world_transform @INPUT : spatial_axes separations translation_voxel world_space_for_translation_voxel direction_cosines @OUTPUT : world_transform @RETURNS : @DESCRIPTION: Computes the linear transform from the indices of the spatial dimensions (spatial_axes), the separations, the translation (translation_voxel,world_space_for_translation_voxel) and the direction cosines. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - now uses starts/steps ---------------------------------------------------------------------------- */ VIOAPI void compute_world_transform( int spatial_axes[N_DIMENSIONS], Real separations[], Real direction_cosines[][N_DIMENSIONS], Real starts[], General_transform *world_transform ) { Transform transform; Real separations_3D[N_DIMENSIONS]; Real directions[N_DIMENSIONS][N_DIMENSIONS]; Real starts_3D[N_DIMENSIONS]; Real normal[N_DIMENSIONS]; int dim, c, a1, a2, axis, n_axes; int axis_list[N_DIMENSIONS]; /*--- find how many direction cosines are specified, and set the 3d separations and starts */ n_axes = 0; for_less( c, 0, N_DIMENSIONS ) { axis = spatial_axes[c]; if( axis >= 0 ) { separations_3D[c] = separations[axis]; starts_3D[c] = starts[axis]; directions[c][X] = direction_cosines[axis][X]; directions[c][Y] = direction_cosines[axis][Y]; directions[c][Z] = direction_cosines[axis][Z]; axis_list[n_axes] = c; ++n_axes; } else { separations_3D[c] = 1.0; starts_3D[c] = 0.0; } } if( n_axes == 0 ) { print_error( "error compute_world_transform: no axes.\n" ); return; } /*--- convert 1 or 2 axes to 3 axes */ if( n_axes == 1 ) { a1 = (axis_list[0] + 1) % N_DIMENSIONS; a2 = (axis_list[0] + 2) % N_DIMENSIONS; /*--- create an orthogonal vector */ directions[a1][X] = directions[axis_list[0]][Y] + directions[axis_list[0]][Z]; directions[a1][Y] = -directions[axis_list[0]][X] - directions[axis_list[0]][Z]; directions[a1][Z] = directions[axis_list[0]][Y] - directions[axis_list[0]][X]; cross_3D_vector( directions[axis_list[0]], directions[a1], directions[a2] ); normalize_vector( directions[a1], directions[a1] ); normalize_vector( directions[a2], directions[a2] ); } else if( n_axes == 2 ) { a2 = N_DIMENSIONS - axis_list[0] - axis_list[1]; cross_3D_vector( directions[axis_list[0]], directions[axis_list[1]], directions[a2] ); normalize_vector( directions[a2], directions[a2] ); } /*--- check to make sure that 3 axes are not a singular system */ for_less( dim, 0, N_DIMENSIONS ) { cross_3D_vector( directions[dim], directions[(dim+1)%N_DIMENSIONS], normal ); if( normal[0] == 0.0 && normal[1] == 0.0 && normal[2] == 0.0 ) break; } if( dim < N_DIMENSIONS ) { directions[0][0] = 1.0; directions[0][1] = 0.0; directions[0][2] = 0.0; directions[1][0] = 0.0; directions[1][1] = 1.0; directions[1][2] = 0.0; directions[2][0] = 0.0; directions[2][1] = 0.0; directions[2][2] = 1.0; } /*--- make the linear transformation */ make_identity_transform( &transform ); for_less( c, 0, N_DIMENSIONS ) { for_less( dim, 0, N_DIMENSIONS ) { Transform_elem(transform,dim,c) = directions[c][dim] * separations_3D[c]; Transform_elem(transform,dim,3) += directions[c][dim] * starts_3D[c]; } } create_linear_transform( world_transform, &transform ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : check_recompute_world_transform @INPUT : volume @OUTPUT : @RETURNS : @DESCRIPTION: Recompute the voxel to world transform. Called when one of the attributes affecting this is changed. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 20, 1997 D. MacDonald - now checks update flag ---------------------------------------------------------------------------- */ static void check_recompute_world_transform( Volume volume ) { General_transform world_transform; if( !volume->voxel_to_world_transform_uptodate ) { volume->voxel_to_world_transform_uptodate = TRUE; compute_world_transform( volume->spatial_axes, volume->separations, volume->direction_cosines, volume->starts, &world_transform ); assign_voxel_to_world_transform( volume, &world_transform ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_transform_origin_to_starts @INPUT : origin n_volume_dimensions spatial_axes dir_cosines @OUTPUT : starts @RETURNS : @DESCRIPTION: Converts a transform origin into starts (multiples of the dir_cosines). dir_cosines need not be mutually orthogonal @METHOD : @GLOBALS : @CALLS : @CREATED : May. 22, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ static void convert_transform_origin_to_starts( Real origin[], int n_volume_dimensions, int spatial_axes[], Real dir_cosines[][N_DIMENSIONS], Real starts[] ) { int axis, dim, which[N_DIMENSIONS], n_axes, i, j; Real o_dot_c, c_dot_c; Real x_dot_x, x_dot_y, x_dot_v, y_dot_y, y_dot_v, bottom; Real **matrix, solution[N_DIMENSIONS]; for_less( dim, 0, n_volume_dimensions ) starts[dim] = 0.0; /*--- get the list of valid axes (which) */ n_axes = 0; for_less( dim, 0, N_DIMENSIONS ) { axis = spatial_axes[dim]; if( axis >= 0 ) { which[n_axes] = axis; ++n_axes; } } /*--- get the starts: computed differently for 1, 2, or 3 axes */ if( n_axes == 1 ) { o_dot_c = dot_vectors( N_DIMENSIONS, origin, dir_cosines[which[0]] ); c_dot_c = dot_vectors( N_DIMENSIONS, dir_cosines[which[0]], dir_cosines[which[0]] ); if( c_dot_c != 0.0 ) starts[which[0]] = o_dot_c / c_dot_c; } else if( n_axes == 2 ) { x_dot_x = dot_vectors( N_DIMENSIONS, dir_cosines[which[0]], dir_cosines[which[0]] ); x_dot_v = dot_vectors( N_DIMENSIONS, dir_cosines[which[0]], origin ); x_dot_y = dot_vectors( N_DIMENSIONS, dir_cosines[which[0]], dir_cosines[which[1]] ); y_dot_y = dot_vectors( N_DIMENSIONS, dir_cosines[which[1]], dir_cosines[which[1]] ); y_dot_v = dot_vectors( N_DIMENSIONS, dir_cosines[which[1]], origin ); bottom = x_dot_x * y_dot_y - x_dot_y * x_dot_y; if( bottom != 0.0 ) { starts[which[0]] = (x_dot_v * y_dot_y - x_dot_y * y_dot_v) / bottom; starts[which[1]] = (y_dot_v * x_dot_x - x_dot_y * x_dot_v) / bottom; } } else if( n_axes == 3 ) { /*--- this is the usual case, solve the equations to find what starts give the desired origin */ ALLOC2D( matrix, N_DIMENSIONS, N_DIMENSIONS ); for_less( i, 0, N_DIMENSIONS ) for_less( j, 0, N_DIMENSIONS ) { matrix[i][j] = dir_cosines[which[j]][i]; } if( solve_linear_system( N_DIMENSIONS, matrix, origin, solution ) ) { starts[which[0]] = solution[0]; starts[which[1]] = solution[1]; starts[which[2]] = solution[2]; } FREE2D( matrix ); } else { print_error( "Invalid number of axes in convert_transform_origin_to_starts\n"); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_transform_to_starts_and_steps @INPUT : transform separation_signs @OUTPUT : starts steps dir_cosines spatial_axes @RETURNS : @DESCRIPTION: Converts a linear transform to a set of 3 starts, 3 steps, and 3 direction cosines. The separation signs determine the desired signs of each of the separations. @METHOD : @GLOBALS : @CALLS : @CREATED : May. 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void convert_transform_to_starts_and_steps( General_transform *transform, int n_volume_dimensions, Real step_signs[], int spatial_axes[], Real starts[], Real steps[], Real dir_cosines[][N_DIMENSIONS] ) { Real sign, mag; int axis, dim; Real axes[N_DIMENSIONS][N_DIMENSIONS]; Real origin[N_DIMENSIONS]; Transform *linear_transform; if( get_transform_type( transform ) != LINEAR ) { print_error( "convert_transform_to_starts_and_steps(): non-linear transform found.\n" ); return; } linear_transform = get_linear_transform_ptr( transform ); get_transform_origin_real( linear_transform, origin ); get_transform_x_axis_real( linear_transform, &axes[X][0] ); get_transform_y_axis_real( linear_transform, &axes[Y][0] ); get_transform_z_axis_real( linear_transform, &axes[Z][0] ); /*--- assign default steps */ for_less( dim, 0, n_volume_dimensions ) steps[dim] = 1.0; /*--- assign the steps and dir_cosines for the spatial axes */ for_less( dim, 0, N_DIMENSIONS ) { axis = spatial_axes[dim]; if( axis >= 0 ) { mag = dot_vectors( N_DIMENSIONS, axes[dim], axes[dim] ); if( mag <= 0.0 ) mag = 1.0; mag = sqrt( mag ); if( step_signs == NULL ) { if( axes[dim][dim] < 0.0 ) sign = -1.0; else sign = 1.0; } else /*--- make the sign of steps match the step_signs passed in */ { if( step_signs[axis] < 0.0 ) sign = -1.0; else sign = 1.0; } steps[axis] = sign * mag; dir_cosines[axis][X] = axes[dim][X] / steps[axis]; dir_cosines[axis][Y] = axes[dim][Y] / steps[axis]; dir_cosines[axis][Z] = axes[dim][Z] / steps[axis]; } } /*--- finally, get the starts */ convert_transform_origin_to_starts( origin, n_volume_dimensions, spatial_axes, dir_cosines, starts ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_voxel_to_world_transform @INPUT : volume transform @OUTPUT : @RETURNS : @DESCRIPTION: Sets the volume's transformation from voxel to world coords. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - recomputes the starts/steps ---------------------------------------------------------------------------- */ VIOAPI void set_voxel_to_world_transform( Volume volume, General_transform *transform ) { assign_voxel_to_world_transform( volume, transform ); volume->voxel_to_world_transform_uptodate = TRUE; if( get_transform_type( transform ) == LINEAR ) { convert_transform_to_starts_and_steps( transform, get_volume_n_dimensions(volume), volume->separations, volume->spatial_axes, volume->starts, volume->separations, volume->direction_cosines ); } } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_voxel_to_world_transform @INPUT : @OUTPUT : @RETURNS : transform @DESCRIPTION: Returns a pointer to the voxel to world transform of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - now delays recomputing transform ---------------------------------------------------------------------------- */ VIOAPI General_transform *get_voxel_to_world_transform( Volume volume ) { check_recompute_world_transform( volume ); return( &volume->voxel_to_world_transform ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_dimension_names @INPUT : volume @OUTPUT : @RETURNS : list of dimension names @DESCRIPTION: Creates a copy of the dimension names of the volume. Therefore, after use, the calling function must free the list, by calling delete_dimension_names(). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING *get_volume_dimension_names( Volume volume ) { int i; STRING *names; ALLOC( names, get_volume_n_dimensions(volume) ); for_less( i, 0, get_volume_n_dimensions(volume) ) names[i] = create_string( volume->dimension_names[i] ); for_less( i, 0, N_DIMENSIONS ) { if( volume->spatial_axes[i] >= 0 ) { replace_string( &names[volume->spatial_axes[i]], create_string( convert_spatial_axis_to_dim_name(i)) ); } } return( names ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : delete_dimension_names @INPUT : volume, dimension_names @OUTPUT : @RETURNS : @DESCRIPTION: Frees the memory allocated to the dimension names, which came from the above function, get_volume_dimension_names(). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void delete_dimension_names( Volume volume, STRING dimension_names[] ) { int i; for_less( i, 0, get_volume_n_dimensions(volume) ) delete_string( dimension_names[i] ); FREE( dimension_names ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_space_type @INPUT : volume @OUTPUT : @RETURNS : @DESCRIPTION: Returns a copy of the string representing the volume coordinate system name. The calling function must delete_string() the value when done. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 15, 1996 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI STRING get_volume_space_type( Volume volume ) { return( create_string( volume->coordinate_system_name ) ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_space_type @INPUT : volume name @OUTPUT : @RETURNS : @DESCRIPTION: Copies the name into the volume's coordinate system name. Copies the string, rather than just the pointer. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 15, 1996 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_space_type( Volume volume, STRING name ) { delete_string( volume->coordinate_system_name ); volume->coordinate_system_name = create_string( name ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_separations @INPUT : volume @OUTPUT : separations @RETURNS : @DESCRIPTION: Passes back the slice separations for each dimensions. Assumes separations contains enough room for n_dimensions Reals. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_volume_separations( Volume volume, Real separations[] ) { int i; for_less( i, 0, get_volume_n_dimensions( volume ) ) separations[i] = volume->separations[i]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_separations @INPUT : volume separations @OUTPUT : @RETURNS : @DESCRIPTION: Sets the separations between slices for the given volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - now delays recomputing transform ---------------------------------------------------------------------------- */ VIOAPI void set_volume_separations( Volume volume, Real separations[] ) { int i; for_less( i, 0, get_volume_n_dimensions( volume ) ) volume->separations[i] = separations[i]; volume->voxel_to_world_transform_uptodate = FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_starts @INPUT : volume starts[] @OUTPUT : @RETURNS : @DESCRIPTION: Sets the translation portion of the voxel to world transform, by specifying the start vector, as specified by the MINC format. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - now delays recomputing transform ---------------------------------------------------------------------------- */ VIOAPI void set_volume_starts( Volume volume, Real starts[] ) { int c; for_less( c, 0, get_volume_n_dimensions( volume ) ) volume->starts[c] = starts[c]; volume->voxel_to_world_transform_uptodate = FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_starts @INPUT : volume @OUTPUT : starts @RETURNS : @DESCRIPTION: Passes back the start vector of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_volume_starts( Volume volume, Real starts[] ) { int c; for_less( c, 0, get_volume_n_dimensions( volume ) ) starts[c] = volume->starts[c]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_direction_unit_cosine @INPUT : volume axis dir @OUTPUT : @RETURNS : @DESCRIPTION: Sets the direction cosine for one axis, assumed to be unit length. @METHOD : @GLOBALS : @CALLS : @CREATED : May 20, 1997 David MacDonald ---------------------------------------------------------------------------- */ VIOAPI void set_volume_direction_unit_cosine( Volume volume, int axis, Real dir[] ) { int dim; if( axis < 0 || axis >= get_volume_n_dimensions(volume) ) { print_error( "set_volume_direction_cosine: cannot set dir cosine for axis %d\n", axis ); return; } /*--- check if this is a spatial axis */ for_less( dim, 0, N_DIMENSIONS ) { if( volume->spatial_axes[dim] == axis ) break; } if( dim == N_DIMENSIONS ) /* this is not a spatial axis, ignore the dir */ return; volume->direction_cosines[axis][X] = dir[X]; volume->direction_cosines[axis][Y] = dir[Y]; volume->direction_cosines[axis][Z] = dir[Z]; volume->voxel_to_world_transform_uptodate = FALSE; } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_direction_cosine @INPUT : volume axis dir @OUTPUT : @RETURNS : @DESCRIPTION: Sets the direction cosine for one axis. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : May 20, 1997 D. MacDonald - split into set_volume_direction_unit_cosine ---------------------------------------------------------------------------- */ VIOAPI void set_volume_direction_cosine( Volume volume, int axis, Real dir[] ) { Real len, unit_vector[N_DIMENSIONS]; len = dir[X] * dir[X] + dir[Y] * dir[Y] + dir[Z] * dir[Z]; if( len == 0.0 ) { print_error( "Warning: zero length direction cosine in set_volume_direction_cosine()\n" ); return; } if( len <= 0.0 ) len = 1.0; len = sqrt( len ); unit_vector[X] = dir[X] / len; unit_vector[Y] = dir[Y] / len; unit_vector[Z] = dir[Z] / len; set_volume_direction_unit_cosine( volume, axis, unit_vector ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_direction_cosine @INPUT : volume axis @OUTPUT : dir @RETURNS : @DESCRIPTION: Passes back the direction cosine corresponding to the given voxel axis, which must be a spatial dimension. @METHOD : @GLOBALS : @CALLS : @CREATED : Nov. 15, 1996 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_volume_direction_cosine( Volume volume, int axis, Real dir[] ) { int d; if( axis < 0 || axis >= get_volume_n_dimensions(volume) ) { print_error( "get_volume_direction_cosine: cannot get dir cosine for axis %d\n", axis ); return; } for_less( d, 0, N_DIMENSIONS ) { if( volume->spatial_axes[d] == axis ) break; } if( d == N_DIMENSIONS ) /* this is not a spatial axis, ignore the dir */ { dir[X] = 0.0; dir[Y] = 0.0; dir[Z] = 0.0; } else { dir[X] = volume->direction_cosines[axis][X]; dir[Y] = volume->direction_cosines[axis][Y]; dir[Z] = volume->direction_cosines[axis][Z]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_translation @INPUT : volume voxel world_space_voxel_maps_to @OUTPUT : @RETURNS : @DESCRIPTION: Sets the translation portion of the volume so that the given voxel maps to the given world space position. Rewrote this to provide backwards compatibility. @METHOD : @GLOBALS : @CALLS : @CREATED : Aug. 31, 1997 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_translation( Volume volume, Real voxel[], Real world_space_voxel_maps_to[] ) { int dim, dim2, axis, n_axes, a1, a2; Real world_space_origin[N_DIMENSIONS], len; Real starts[MAX_DIMENSIONS], starts_3d[N_DIMENSIONS]; Transform transform, inverse; /*--- find the world position where ( 0, 0, 0 ) maps to by taking the world position - voxel[x_axis] * Xaxis - voxel[y_axis] * Yaxis ..., and fill in the transform defined by Xaxis, Yaxis, Zaxis */ make_identity_transform( &transform ); for_less( dim, 0, N_DIMENSIONS ) { world_space_origin[dim] = world_space_voxel_maps_to[dim]; for_less( dim2, 0, N_DIMENSIONS ) { axis = volume->spatial_axes[dim2]; if( axis >= 0 ) { world_space_origin[dim] -= volume->separations[axis] * volume->direction_cosines[axis][dim] * voxel[axis]; Transform_elem( transform, dim, dim2 ) = volume->direction_cosines[axis][dim]; } } } n_axes = 0; for_less( dim, 0, N_DIMENSIONS ) { axis = volume->spatial_axes[dim]; if( axis >= 0 ) ++n_axes; } /*--- if only one spatial axis, make a second orthogonal vector */ if( n_axes == 1 ) { /*--- set dim to the spatial axis */ if( volume->spatial_axes[0] >= 0 ) dim = 0; else if( volume->spatial_axes[1] >= 0 ) dim = 1; else if( volume->spatial_axes[2] >= 0 ) dim = 2; /*--- set a1 to the lowest occuring non-spatial axis, and create a unit vector normal to that of the spatial axis */ if( dim == 0 ) a1 = 1; else a1 = 0; Transform_elem( transform, 0, a1 ) = Transform_elem(transform,1,dim) + Transform_elem(transform,2,dim); Transform_elem( transform, 1, a1 ) = -Transform_elem(transform,0,dim) - Transform_elem(transform,2,dim); Transform_elem( transform, 2, a1 ) = Transform_elem(transform,1,dim) - Transform_elem(transform,0,dim); len = Transform_elem(transform,0,a1)*Transform_elem(transform,0,a1) + Transform_elem(transform,1,a1)*Transform_elem(transform,1,a1) + Transform_elem(transform,2,a1)*Transform_elem(transform,2,a1); if( len == 0.0 ) len = 1.0; else len = sqrt( len ); Transform_elem(transform,0,a1) /= len; Transform_elem(transform,1,a1) /= len; Transform_elem(transform,2,a1) /= len; } /*--- if only two spatial axis, make a third orthogonal vector */ if( n_axes == 1 || n_axes == 2 ) { /*--- set dim to the one axis that does not have a vector associated with it yet, and make one that is the unit cross product of the other two */ if( volume->spatial_axes[2] < 0 ) dim = 2; else if( volume->spatial_axes[1] < 0 ) dim = 1; else if( volume->spatial_axes[0] < 0 ) dim = 0; a1 = (dim + 1) % N_DIMENSIONS; a2 = (dim + 2) % N_DIMENSIONS; /*--- take cross product */ Transform_elem( transform, 0, dim ) = Transform_elem(transform,1,a1) * Transform_elem(transform,2,a2) - Transform_elem(transform,1,a2) * Transform_elem(transform,2,a1); Transform_elem( transform, 1, dim ) = Transform_elem(transform,2,a1) * Transform_elem(transform,0,a2) - Transform_elem(transform,2,a2) * Transform_elem(transform,0,a1); Transform_elem( transform, 2, dim ) = Transform_elem(transform,0,a1) * Transform_elem(transform,1,a2) - Transform_elem(transform,0,a2) * Transform_elem(transform,1,a1); /*--- normalize vector */ len = Transform_elem(transform,0,dim)*Transform_elem(transform,0,dim) + Transform_elem(transform,1,dim)*Transform_elem(transform,1,dim) + Transform_elem(transform,2,dim)*Transform_elem(transform,2,dim); if( len == 0.0 ) len = 1.0; else len = sqrt( len ); Transform_elem(transform,0,dim) /= len; Transform_elem(transform,1,dim) /= len; Transform_elem(transform,2,dim) /= len; } /*--- find the voxel that maps to the world space origin, when there is no translation, and this is the starts */ compute_transform_inverse( &transform, &inverse ); transform_point( &inverse, world_space_origin[X], world_space_origin[Y], world_space_origin[Z], &starts_3d[X], &starts_3d[Y], &starts_3d[Z] ); /*--- map the X Y Z starts into the arbitrary axis ordering of the volume */ for_less( dim, 0, get_volume_n_dimensions(volume) ) starts[dim] = 0.0; for_less( dim, 0, N_DIMENSIONS ) { axis = volume->spatial_axes[dim]; if( axis >= 0 ) starts[axis] = starts_3d[dim]; } set_volume_starts( volume, starts ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_translation @INPUT : volume @OUTPUT : voxel - returns 0, 0, 0 ... world_space_voxel_maps_to - returns centre of voxel [0][0][0]... @RETURNS : @DESCRIPTION: Reinstated this old function for backward compatibility. Simply returns the voxel 0, 0, 0, and the world coordinate of its centre, to indicate the translational component of the transformation. @METHOD : @GLOBALS : @CALLS : @CREATED : May. 23, 1998 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_volume_translation( Volume volume, Real voxel[], Real world_space_voxel_maps_to[] ) { int dim; for_less( dim, 0, get_volume_n_dimensions(volume) ) voxel[dim] = 0.0; convert_voxel_to_world( volume, voxel, &world_space_voxel_maps_to[X], &world_space_voxel_maps_to[Y], &world_space_voxel_maps_to[Z] ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : reorder_voxel_to_xyz @INPUT : volume voxel @OUTPUT : xyz @RETURNS : @DESCRIPTION: Passes back the voxel coordinates corresponding to the x, y, and z axes, if any. @METHOD : @GLOBALS : @CALLS : @CREATED : May 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void reorder_voxel_to_xyz( Volume volume, Real voxel[], Real xyz[] ) { int c, axis; for_less( c, 0, N_DIMENSIONS ) { axis = volume->spatial_axes[c]; if( axis >= 0 ) xyz[c] = voxel[axis]; else xyz[c] = 0.0; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : reorder_xyz_to_voxel @INPUT : volume xyz @OUTPUT : voxel @RETURNS : @DESCRIPTION: Passes back the voxel coordinates converted from those corresponding to the x, y, and z axis. @METHOD : @GLOBALS : @CALLS : @CREATED : Jun 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void reorder_xyz_to_voxel( Volume volume, Real xyz[], Real voxel[] ) { int c, axis, n_dims; n_dims = get_volume_n_dimensions( volume ); for_less( c, 0, n_dims ) voxel[c] = 0.0; for_less( c, 0, N_DIMENSIONS ) { axis = volume->spatial_axes[c]; if( axis >= 0 ) voxel[axis] = xyz[c]; } } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_voxel_to_world @INPUT : volume x_voxel y_voxel z_voxel @OUTPUT : x_world y_world z_world @RETURNS : @DESCRIPTION: Converts the given voxel position to a world coordinate. Note that centre of first voxel corresponds to (0.0,0.0,0.0) in voxel coordinates. @CREATED : Mar 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - checks to recompute transform ---------------------------------------------------------------------------- */ VIOAPI void convert_voxel_to_world( Volume volume, Real voxel[], Real *x_world, Real *y_world, Real *z_world ) { Real xyz[N_DIMENSIONS]; check_recompute_world_transform( volume ); reorder_voxel_to_xyz( volume, voxel, xyz ); /* apply linear transform */ general_transform_point( &volume->voxel_to_world_transform, xyz[X], xyz[Y], xyz[Z], x_world, y_world, z_world ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_3D_voxel_to_world @INPUT : volume voxel1 voxel2 voxel3 @OUTPUT : x_world y_world z_world @RETURNS : @DESCRIPTION: Convenience function which performs same task as convert_voxel_to_world(), but for 3D volumes only. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void convert_3D_voxel_to_world( Volume volume, Real voxel1, Real voxel2, Real voxel3, Real *x_world, Real *y_world, Real *z_world ) { Real voxel[MAX_DIMENSIONS]; if( get_volume_n_dimensions(volume) != 3 ) { print_error( "convert_3D_voxel_to_world: Volume must be 3D.\n" ); return; } voxel[0] = voxel1; voxel[1] = voxel2; voxel[2] = voxel3; convert_voxel_to_world( volume, voxel, x_world, y_world, z_world ); } /* ----------------------------- MNI Header -----------------------------------@NAME : convert_voxel_normal_vector_to_world @INPUT : volume voxel_vector0 voxel_vector1 voxel_vector2 @OUTPUT : x_world y_world z_world @RETURNS : @DESCRIPTION: Converts a voxel vector to world coordinates. Assumes the vector is a normal vector (ie. a derivative), so transforms by transpose of inverse transform. @CREATED : Mar 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - checks to recompute transform ---------------------------------------------------------------------------- */ VIOAPI void convert_voxel_normal_vector_to_world( Volume volume, Real voxel_vector[], Real *x_world, Real *y_world, Real *z_world ) { Real xyz[N_DIMENSIONS]; Transform *inverse; check_recompute_world_transform( volume ); if( get_transform_type( &volume->voxel_to_world_transform ) != LINEAR ) handle_internal_error( "Cannot get normal vector of nonlinear xforms."); inverse = get_inverse_linear_transform_ptr( &volume->voxel_to_world_transform ); /* transform vector by transpose of inverse transformation */ reorder_voxel_to_xyz( volume, voxel_vector, xyz ); *x_world = Transform_elem(*inverse,0,0) * xyz[X] + Transform_elem(*inverse,1,0) * xyz[Y] + Transform_elem(*inverse,2,0) * xyz[Z]; *y_world = Transform_elem(*inverse,0,1) * xyz[X] + Transform_elem(*inverse,1,1) * xyz[Y] + Transform_elem(*inverse,2,1) * xyz[Z]; *z_world = Transform_elem(*inverse,0,2) * xyz[X] + Transform_elem(*inverse,1,2) * xyz[Y] + Transform_elem(*inverse,2,2) * xyz[Z]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_voxel_vector_to_world @INPUT : volume voxel_vector @OUTPUT : x_world y_world z_world @RETURNS : @DESCRIPTION: Converts a voxel vector to world coordinates. @CREATED : Mar 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void convert_voxel_vector_to_world( Volume volume, Real voxel_vector[], Real *x_world, Real *y_world, Real *z_world ) { int i; Real origin[MAX_DIMENSIONS], x0, y0, z0, x1, y1, z1; for_less( i, 0, MAX_DIMENSIONS ) origin[i] = 0.0; convert_voxel_to_world( volume, origin, &x0, &y0, &z0 ); convert_voxel_to_world( volume, voxel_vector, &x1, &y1, &z1 ); *x_world = x1 - x0; *y_world = y1 - y0; *z_world = z1 - z0; } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_world_vector_to_voxel @INPUT : volume x_world y_world z_world @OUTPUT : voxel_vector @RETURNS : @DESCRIPTION: Converts a world vector to voxel coordinates. @CREATED : Mar 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void convert_world_vector_to_voxel( Volume volume, Real x_world, Real y_world, Real z_world, Real voxel_vector[] ) { int c; Real voxel[MAX_DIMENSIONS], origin[MAX_DIMENSIONS]; convert_world_to_voxel( volume, 0.0, 0.0, 0.0, origin ); convert_world_to_voxel( volume, x_world, y_world, z_world, voxel ); for_less( c, 0, get_volume_n_dimensions(volume) ) voxel_vector[c] = voxel[c] - origin[c]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_world_to_voxel @INPUT : volume x_world y_world z_world @OUTPUT : x_voxel y_voxel z_voxel @RETURNS : @DESCRIPTION: Converts from world coordinates to voxel coordinates. @CREATED : Mar 1993 David MacDonald @MODIFIED : May 22, 1997 D. MacDonald - checks to recompute transform ---------------------------------------------------------------------------- */ VIOAPI void convert_world_to_voxel( Volume volume, Real x_world, Real y_world, Real z_world, Real voxel[] ) { Real xyz[N_DIMENSIONS]; check_recompute_world_transform( volume ); general_inverse_transform_point( &volume->voxel_to_world_transform, x_world, y_world, z_world, &xyz[X], &xyz[Y], &xyz[Z] ); reorder_xyz_to_voxel( volume, xyz, voxel ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : convert_3D_world_to_voxel @INPUT : volume x_world y_world z_world @OUTPUT : voxel1 voxel2 voxel3 @RETURNS : @DESCRIPTION: Convenience function that does same task as convert_world_to_voxel(), but only for 3D volumes. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void convert_3D_world_to_voxel( Volume volume, Real x_world, Real y_world, Real z_world, Real *voxel1, Real *voxel2, Real *voxel3 ) { Real voxel[MAX_DIMENSIONS]; if( get_volume_n_dimensions(volume) != 3 ) { print_error( "convert_3D_world_to_voxel: Volume must be 3D.\n" ); return; } convert_world_to_voxel( volume, x_world, y_world, z_world, voxel ); *voxel1 = voxel[X]; *voxel2 = voxel[Y]; *voxel3 = voxel[Z]; } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_voxel_min @INPUT : volume @OUTPUT : @RETURNS : min valid voxel @DESCRIPTION: Returns the minimum valid voxel value. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_volume_voxel_min( Volume volume ) { return( volume->voxel_min ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_voxel_max @INPUT : volume @OUTPUT : @RETURNS : max valid voxel @DESCRIPTION: Returns the maximum valid voxel value. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_volume_voxel_max( Volume volume ) { return( volume->voxel_max ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_voxel_range @INPUT : volume @OUTPUT : voxel_min voxel_max @RETURNS : @DESCRIPTION: Passes back the min and max voxel values stored in the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_volume_voxel_range( Volume volume, Real *voxel_min, Real *voxel_max ) { *voxel_min = get_volume_voxel_min( volume ); *voxel_max = get_volume_voxel_max( volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_voxel_range @INPUT : volume voxel_min voxel_max @OUTPUT : @RETURNS : @DESCRIPTION: Sets the valid range of voxels. If an invalid range is specified (voxel_min >= voxel_max), the full range of the volume's type is used. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_voxel_range( Volume volume, Real voxel_min, Real voxel_max ) { Real real_min, real_max; if( voxel_min >= voxel_max ) { switch( get_volume_data_type( volume ) ) { case UNSIGNED_BYTE: voxel_min = 0.0; voxel_max = (Real) UCHAR_MAX; break; case SIGNED_BYTE: voxel_min = (Real) SCHAR_MIN; voxel_max = (Real) SCHAR_MAX; break; case UNSIGNED_SHORT: voxel_min = 0.0; voxel_max = (Real) USHRT_MAX; break; case SIGNED_SHORT: voxel_min = (Real) SHRT_MIN; voxel_max = (Real) SHRT_MAX; break; case UNSIGNED_INT: voxel_min = 0.0; voxel_max = (Real) UINT_MAX; break; case SIGNED_INT: voxel_min = (Real) INT_MIN; voxel_max = (Real) INT_MAX; break; case FLOAT: voxel_min = (Real) -FLT_MAX; voxel_max = (Real) FLT_MAX; break; case DOUBLE: voxel_min = (Real) -DBL_MAX; voxel_max = (Real) DBL_MAX; break; } } if( volume->real_range_set ) get_volume_real_range( volume, &real_min, &real_max ); volume->voxel_min = voxel_min; volume->voxel_max = voxel_max; if( volume->real_range_set ) set_volume_real_range( volume, real_min, real_max ); else cache_volume_range_has_changed( volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_real_range @INPUT : volume @OUTPUT : min_value max_value @RETURNS : @DESCRIPTION: Passes back the minimum and maximum scaled values. These are the minimum and maximum stored voxel values scaled to the real value domain. @METHOD : @GLOBALS : @CALLS : @CREATED : June, 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void get_volume_real_range( Volume volume, Real *min_value, Real *max_value ) { *min_value = get_volume_real_min( volume ); *max_value = get_volume_real_max( volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_real_min @INPUT : volume @OUTPUT : @RETURNS : real range minimum @DESCRIPTION: Returns the minimum of the real range of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_volume_real_min( Volume volume ) { Real real_min; real_min = get_volume_voxel_min( volume ); if( volume->real_range_set ) real_min = convert_voxel_to_value( volume, real_min ); return( real_min ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : get_volume_real_max @INPUT : volume @OUTPUT : @RETURNS : real range max @DESCRIPTION: Returns the maximum of the real range of the volume. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Real get_volume_real_max( Volume volume ) { Real real_max; real_max = get_volume_voxel_max( volume ); if( volume->real_range_set ) real_max = convert_voxel_to_value( volume, real_max ); return( real_max ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : set_volume_real_range @INPUT : volume real_min real_max @OUTPUT : @RETURNS : @DESCRIPTION: Sets the range of real values to which the valid voxel range maps @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI void set_volume_real_range( Volume volume, Real real_min, Real real_max ) { Real voxel_min, voxel_max; if( get_volume_data_type(volume) == FLOAT || get_volume_data_type(volume) == DOUBLE ) { /* as float and double use the voxel range */ volume->real_range_set = FALSE; set_volume_voxel_range( volume, real_min, real_max ); /* these really shouldn't be needed but let's be "safe" */ volume->real_value_scale = 1.0; volume->real_value_translation = 0.0; } else { get_volume_voxel_range( volume, &voxel_min, &voxel_max ); if( voxel_min < voxel_max ) { volume->real_value_scale = (real_max - real_min) / (voxel_max - voxel_min); volume->real_value_translation = real_min - voxel_min * volume->real_value_scale; } else { // FIXME: is scale = 0 correct?? volume->real_value_scale = 0.0; volume->real_value_translation = real_min; } volume->real_range_set = TRUE; } if( volume->is_cached_volume ) cache_volume_range_has_changed( volume ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_volume_definition_no_alloc @INPUT : volume nc_data_type signed_flag voxel_min voxel_max @OUTPUT : @RETURNS : @DESCRIPTION: Copies the volume to a new volume, optionally changing type (if nc_data_type is not MI_ORIGINAL_TYPE), but not allocating the volume voxel data (alloc_volume_data() must subsequently be called). @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : Nov. 15, 1996 D. MacDonald - handles space type ---------------------------------------------------------------------------- */ VIOAPI Volume copy_volume_definition_no_alloc( Volume volume, nc_type nc_data_type, BOOLEAN signed_flag, Real voxel_min, Real voxel_max ) { int c, sizes[MAX_DIMENSIONS]; Real separations[MAX_DIMENSIONS]; Real starts[MAX_DIMENSIONS]; Real dir_cosine[N_DIMENSIONS]; Volume copy; if( nc_data_type == MI_ORIGINAL_TYPE ) { nc_data_type = volume->nc_data_type; signed_flag = volume->signed_flag; get_volume_voxel_range( volume, &voxel_min, &voxel_max ); } copy = create_volume( get_volume_n_dimensions(volume), volume->dimension_names, nc_data_type, signed_flag, voxel_min, voxel_max ); for_less( c, 0, N_DIMENSIONS ) copy->spatial_axes[c] = volume->spatial_axes[c]; set_volume_real_range( copy, get_volume_real_min(volume), get_volume_real_max(volume) ); get_volume_sizes( volume, sizes ); set_volume_sizes( copy, sizes ); get_volume_separations( volume, separations ); set_volume_separations( copy, separations ); get_volume_starts( volume, starts ); set_volume_starts( copy, starts ); for_less( c, 0, get_volume_n_dimensions(volume) ) { get_volume_direction_cosine( volume, c, dir_cosine ); set_volume_direction_unit_cosine( copy, c, dir_cosine ); } set_volume_space_type( copy, volume->coordinate_system_name ); for_less( c, 0, get_volume_n_dimensions(volume) ) { if (is_volume_dimension_irregular(volume, c)) { Real *irr_starts = malloc(sizeof(Real) * sizes[c]); Real *irr_widths = malloc(sizeof(Real) * sizes[c]); get_volume_irregular_starts( volume, c, sizes[c], irr_starts); set_volume_irregular_starts( volume, c, sizes[c], irr_starts); get_volume_irregular_widths( volume, c, sizes[c], irr_widths); set_volume_irregular_widths( volume, c, sizes[c], irr_widths); free( irr_starts ); free( irr_widths ); } } return( copy ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_volume_definition @INPUT : volume nc_data_type signed_flag voxel_min voxel_max @OUTPUT : @RETURNS : @DESCRIPTION: Copies the volume to a new volume, optionally changing type (if nc_data_type is not MI_ORIGINAL_TYPE), allocating the volume voxel data, but not initializing the data. @METHOD : @GLOBALS : @CALLS : @CREATED : 1993 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Volume copy_volume_definition( Volume volume, nc_type nc_data_type, BOOLEAN signed_flag, Real voxel_min, Real voxel_max ) { Volume copy; copy = copy_volume_definition_no_alloc( volume, nc_data_type, signed_flag, voxel_min, voxel_max ); alloc_volume_data( copy ); if( !volume_is_alloced( copy ) ) { delete_volume( copy ); copy = NULL; } return( copy ); } /* ----------------------------- MNI Header ----------------------------------- @NAME : copy_volume @INPUT : volume @OUTPUT : @RETURNS : copy of volume @DESCRIPTION: Creates an exact copy of a volume, including voxel values. @METHOD : @GLOBALS : @CALLS : @CREATED : Jun 21, 1995 David MacDonald @MODIFIED : ---------------------------------------------------------------------------- */ VIOAPI Volume copy_volume( Volume volume ) { Volume copy; void *src, *dest; int d, n_voxels, sizes[MAX_DIMENSIONS]; if( volume->is_cached_volume ) { print_error( "copy_volume(): copying cached volumes not implemented.\n" ); return( NULL ); } copy = copy_volume_definition( volume, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0 ); if( !copy ) { return( NULL ); } /* --- find out how many voxels are in the volume */ get_volume_sizes( volume, sizes ); n_voxels = 1; for_less( d, 0, get_volume_n_dimensions(volume) ) n_voxels *= sizes[d]; /* --- get a pointer to the beginning of the voxels */ GET_VOXEL_PTR( src, volume, 0, 0, 0, 0, 0 ); GET_VOXEL_PTR( dest, copy, 0, 0, 0, 0, 0 ); /* --- assuming voxels are contiguous, copy them in one chunk */ (void) memcpy( dest, src, (size_t) n_voxels * (size_t) get_type_size( get_volume_data_type(volume)) ); return( copy ); } /* These are not public functions, so they are not VIOAPI yet */ BOOLEAN is_volume_dimension_irregular(Volume volume, int idim) { if (idim > volume->array.n_dimensions) { return (0); } return (volume->irregular_starts[idim] != NULL); } int get_volume_irregular_starts(Volume volume, int idim, int count, Real *starts) { int i; if (idim >= volume->array.n_dimensions) { return (0); } if (volume->irregular_starts[idim] == NULL) { return (0); } if (count > volume->array.sizes[idim]) { count = volume->array.sizes[idim]; } for (i = 0; i < count; i++) { starts[i] = volume->irregular_starts[idim][i]; } return (count); } int get_volume_irregular_widths(Volume volume, int idim, int count, Real *widths) { int i; if (idim >= volume->array.n_dimensions) { return (0); } if (volume->irregular_widths[idim] == NULL) { return (0); } if (count > volume->array.sizes[idim]) { count = volume->array.sizes[idim]; } for (i = 0; i < count; i++) { widths[i] = volume->irregular_widths[idim][i]; } return (count); } int set_volume_irregular_starts(Volume volume, int idim, int count, Real *starts) { int i; if (idim >= volume->array.n_dimensions) { return (0); } if (volume->irregular_starts[idim] != NULL) { free(volume->irregular_starts[idim]); } if (starts == NULL) { return (0); } if (count > volume->array.sizes[idim]) { count = volume->array.sizes[idim]; } volume->irregular_starts[idim] = malloc(count * sizeof (Real)); if (volume->irregular_starts[idim] == NULL) { return (0); } for (i = 0; i < count; i++) { volume->irregular_starts[idim][i] = starts[i]; } return (count); } int set_volume_irregular_widths(Volume volume, int idim, int count, Real *widths) { int i; if (idim >= volume->array.n_dimensions) { return (0); } if (volume->irregular_widths[idim] != NULL) { free(volume->irregular_widths[idim]); } if (widths == NULL) { return (0); } if (count > volume->array.sizes[idim]) { count = volume->array.sizes[idim]; } volume->irregular_widths[idim] = malloc(count * sizeof (Real)); if (volume->irregular_widths[idim] == NULL) { return (0); } for (i = 0; i < count; i++) { volume->irregular_widths[idim][i] = widths[i]; } return (count); } VIOAPI VIO_Real nonspatial_voxel_to_world(Volume volume, int idim, int voxel) { VIO_Real world; if (is_volume_dimension_irregular(volume, idim)) { if (voxel < 0) { world = 0.0; } else if (voxel >= volume->array.sizes[idim]) { /* If we are asking for a position PAST the end of the axis, * return the very last position on the axis, defined as the * last start position plus the last width. * NOTE! TODO: FIXME! We should take the axis alignment into * account here. */ voxel = volume->array.sizes[idim] - 1; world = (volume->irregular_starts[idim][voxel] + volume->irregular_widths[idim][voxel]); } else { world = volume->irregular_starts[idim][voxel]; } } else { world = volume->starts[idim] + (voxel * volume->separations[idim]); } return (world); } VIOAPI int nonspatial_world_to_voxel(Volume volume, int idim, VIO_Real world) { int voxel; int i; if (is_volume_dimension_irregular(volume, idim)) { voxel = volume->array.sizes[idim]; for (i = 0; i < volume->array.sizes[idim]; i++) { if (world < (volume->irregular_starts[idim][i] + volume->irregular_widths[idim][i])) { voxel = i; break; } } } else { voxel = ROUND((world - volume->starts[idim]) / volume->separations[idim]); } return (voxel); } minc-2.2.00/volume_io/Makefile.am0000644000265600003100000000004012027132664013466 00000000000000SUBDIRS = Documentation Testing minc-2.2.00/volume_io/Makefile.in0000644000265600003100000003514212030077514013506 00000000000000# Makefile.in generated by automake 1.10.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = volume_io DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mni_REQUIRE_LIB.m4 \ $(top_srcdir)/m4/smr_WITH_BUILD_PATH.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POD2MAN = @POD2MAN@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_F77 = @ac_ct_F77@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = Documentation Testing all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu volume_io/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu volume_io/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ am__remove_distdir=: \ am__skip_length_check=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ install-strip .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-generic clean-libtool \ ctags ctags-recursive distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: minc-2.2.00/volume_io/Documentation/0000755000265600003100000000000012030114724014320 500000000000000minc-2.2.00/volume_io/Documentation/Makefile.am0000644000265600003100000000037112027132663016305 00000000000000EXTRA_DIST = volume_io.tex SUFFIXES = .tex .dvi .ps .PHONY: docs docs: volume_io.ps .tex.dvi: latex $< latex $< volume_io.ps: volume_io.dvi dvips $? -o $@ CLEANFILES = \ volume_io.aux volume_io.dvi volume_io.log volume_io.ps volume_io.toc minc-2.2.00/volume_io/Documentation/Makefile.in0000644000265600003100000002262612030077514016322 00000000000000# Makefile.in generated by automake 1.10.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = volume_io/Documentation DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mni_REQUIRE_LIB.m4 \ $(top_srcdir)/m4/smr_WITH_BUILD_PATH.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POD2MAN = @POD2MAN@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_F77 = @ac_ct_F77@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = volume_io.tex SUFFIXES = .tex .dvi .ps CLEANFILES = \ volume_io.aux volume_io.dvi volume_io.log volume_io.ps volume_io.toc all: all-am .SUFFIXES: .SUFFIXES: .tex .dvi .ps $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu volume_io/Documentation/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu volume_io/Documentation/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am .PHONY: docs docs: volume_io.ps .tex.dvi: latex $< latex $< volume_io.ps: volume_io.dvi dvips $? -o $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: minc-2.2.00/volume_io/Documentation/volume_io.tex0000644000265600003100000034261012027132663016776 00000000000000\documentstyle{report} \title{Programmer's Reference for the \\ BIC Volume IO Library} \author{David MacDonald} \newcommand{\name}[1]{{\bf\tt #1}} \newcommand{\desc}[1]{\begin{itemize} \item[] #1 \end{itemize}} \newcommand{\vol}{BIC Volume IO Library} \begin{document} \maketitle \newpage \tableofcontents \newpage \chapter{Introduction} This document describes a library of routines available at the McConnell Brain Imaging Centre (BIC) at the Montreal Neurological Institute. It was developed as part of a medical imaging software testbed by David MacDonald, with source code and considerable input from Peter Neelin, Louis Collins, and others at the Centre. The library, which is referred to as the \vol, comprises a set of functions for reading and writing volumes of medical imaging data, as well as some general support routines useful to many programming tasks. Images at the Brain Imaging Centre are stored on disk in a format called {\bf MINC}, which stands for {\bf Medical Image Net CDF}. More information is available in related documentation specifically concerning this format and the MINC library of routines used to read and write MINC files. The \vol\ is built on top of the MINC library to provide easy access to MINC files for most general operations, without having to learn too much of the details of the MINC library, which is a comprehensive system for handling most conceivable cases. The \vol\ provides a structure for internal storage of volumes and routines to access and modify volumes. In addition, it provides routines to manipulate tag points and transformations and to perform input and output on these objects in the standardized formats of the Brain Imaging Centre. This document describes where to find the \vol, what functionality is provided, and how to integrate it into a user's programs. The library is written in C source code, and is designed to be linked with C source. It makes calls to two other libraries: \name{MINC} (the BIC file format library) and \name{netcdf} (a portable file format manager). \chapter{Compiling and Linking} The library for linking is \name{libvolume\_io.a}, which is in \name{/usr/local/lib}, and the related include files are in the directory, \name{/usr/local/include} under \name{volume\_io}. Both directories are usually in the compiler search path. Source files making calls to Volume IO functions must have the following line at the top, to include the relevant type definitions and prototypes: {\bf\begin{verbatim} #include \end{verbatim}} In order to link with \vol, the relevant libraries must be specified: {\bf\begin{verbatim} cc test_volume_io.o -o test_volume_io \ -lvolume_io -lminc -lnetcdf -lm -lmalloc \end{verbatim}} The two libraries, \name{minc} and \name{netcdf} are usually in \name{/usr/local/lib}, which is automatically in the search path. The \name{-lm} option includes the math library, which is sometimes called by the \vol. The \name{-lmalloc} library provides faster and more robust memory allocation than the default. \chapter{Style} In order to use this library, one must become accustomed to certain subtleties of style, some of which are peculiar to the author of this software and some of which have evolved in ways dependent on history of the software. Therefore, it is important to note the following style-related issues, for which no apologies are forthcoming. \section{Global Variables} The philosophy that global variables are generally a bad idea has been adopted. In many cases, using global variables within functions hides the behaviour of a function, and therefore, it is preferable to specify all relevant information to a function in the argument list, rather than relying on any global variables. Secondly, modification of a global variable by a given function precludes the use of this function in a multi-threaded environment (two processes may attempt to modify the global variable at the same time). As a result of adopting the anti-global variable philosophy, the user of the \vol\ often must specify many arguments to a function. This seems a small price to pay, in return for the ability to see all factors controlling the behaviour of each function in the argument list. \section{Identifier Names} The implementer of this library has an affinity to typing large amounts of text, and generally dislikes abbreviations. As a result, the function and variable names occurring in the \vol\ may be quite verbose, almost to the point of being complete grammatically correct sentences. In general, one will never see functions with names such as \name{rem\_garb()}. Instead, functions are more likely to have names such as \name{remove\_garbage()}, and, in many cases, even \name{take\_garbage\_to\_curb()}. As a result, the user of the \vol\ will have to type longer-than-usual function and variable names, but hopefully will have a clearer insight into the associated functionality. \section{Structure Arguments} There are many objects defined throughout the library as structures of varying and possibly large sizes. Due to the inefficiency of passing structures by value (copying the whole structure to a function), structures are generally passed to functions by reference. Because of this, there is always a potential to pass an invalid pointer to a function which expects a pointer to a structure. The following examples illustrate the right and wrong ways to use such a function. Given a structure and a library function which initializes it, \begin{verbatim} typedef struct { int a, b, c, d; } big_struct; void initialize( struct big_struct *s ) { s->a = 1; s->b = 2; s->c = 3; s->d = 4; } \end{verbatim} the incorrect method of using this function is: \begin{verbatim} int main() { big_struct *s; initialize( s ); /* WRONG */ } \end{verbatim} because the variable \name{s} is an uninitialized pointer. The correct method is to define a structure variable, not a pointer to a structure, and pass a pointer to the structure: \begin{verbatim} int main() { big_struct s; initialize( &s ); } \end{verbatim} Alternately, the incorrect example above could have been corrected by allocating the \name{s} pointer before calling \name{initialize}. \chapter{Types and Macros} There are several types and macros defined for use with the \vol. All function declarations in the library are preceded with either the word \name{public} or \name{private}, which indicates whether the function is accessible from outside the file in which it resides. Users of the library will only be interested in those functions preceded by \name{public}. They are defined as follows: {\bf\begin{verbatim} #define public #define private static \end{verbatim}} A type for logical values is defined: {\bf\begin{verbatim} typedef int BOOLEAN #define FALSE 0 #define TRUE 1 #define OFF FALSE #define ON TRUE \end{verbatim}} Other useful types defined include: {\bf\begin{verbatim} typedef double Real; typedef enum { OK, ERROR, INTERNAL_ERROR, END_OF_FILE, QUIT } Status; typedef char Smallest_int; \end{verbatim}} Some macros useful for general programming include: {\bf\begin{verbatim} N_DIMENSIONS \end{verbatim}} \desc{A constant equal to 3, the number of dimensions in the real world.} {\bf\begin{verbatim} X \end{verbatim}} \desc{A constant equal to 0, used as an index into various XYZ structures.} {\bf\begin{verbatim} Y \end{verbatim}} \desc{A constant equal to 1, used as an index into various XYZ structures.} {\bf\begin{verbatim} Z \end{verbatim}} \desc{A constant equal to 2, used as an index into various XYZ structures.} {\bf\begin{verbatim} SIZEOF_STATIC_ARRAY( array ) \end{verbatim}} \desc{returns the number of elements in a statically allocated array, for example,} {\bf\begin{verbatim} { int size; int array[] = { 1, 2, 3 }; size = SIZEOF_STATIC_ARRAY( array ); /* == 3 */ } \end{verbatim}} {\bf\begin{verbatim} ROUND( x ) \end{verbatim}} \desc{returns the nearest integer to the \name{x}. If halfway in between two integers, returns the higher of the two. Works correctly for negative, zero, and positive numbers.} {\bf\begin{verbatim} IS_INT( x ) \end{verbatim}} \desc{returns \name{TRUE} if the real argument is exactly an integer.} {\bf\begin{verbatim} FRACTION( x ) \end{verbatim}} \desc{returns the fractional part of the argument.} {\bf\begin{verbatim} FLOOR( x ) \end{verbatim}} \desc{returns the largest integer less than or equal to the argument.} {\bf\begin{verbatim} CEILING( x ) \end{verbatim}} \desc{returns the smallest integer greater than or equal to the argument.} {\bf\begin{verbatim} ABS( x ) \end{verbatim}} \desc{returns the absolute value of an integer or real.} {\bf\begin{verbatim} MAX( x, y ) \end{verbatim}} \desc{returns the maximum of two integers or reals.} {\bf\begin{verbatim} MAX3( x, y, z ) \end{verbatim}} \desc{returns the maximum of three integers or reals.} {\bf\begin{verbatim} MIN( x, y ) \end{verbatim}} \desc{returns the minimum of two integers or reals.} {\bf\begin{verbatim} MIN3( x, y, z ) \end{verbatim}} \desc{returns the minimum of three integers or reals.} {\bf\begin{verbatim} INTERPOLATE( alpha, a, b ) \end{verbatim}} \desc{returns the interpolation between \name{a} and \name{b}, where \name{alpha} is in the range zero to one.} {\bf\begin{verbatim} PI \end{verbatim}} \desc{returns the value of $\pi$.} {\bf\begin{verbatim} DEG_TO_RAD \end{verbatim}} \desc{returns the number of radians per degrees, used to multiply an angle in degrees to result in radians.} {\bf\begin{verbatim} RAD_TO_DEG \end{verbatim}} \desc{returns the number of degrees per radian, used to multiply an angle in radians to result in degrees.} {\bf\begin{verbatim} IJ( i, j, nj ) \end{verbatim}} \desc{converts the indices $\left[ i, j \right]$ of a 2-D \name{ni} by \name{nj} array into a single index, based on row-major order.} {\bf\begin{verbatim} IJK( i, j, k, nj, nk ) \end{verbatim}} \desc{converts the indices $\left[ i , j , k \right]$ of a 3-D \name{ni} by \name{nj} by \name{nk} array into a single index, based on row-major order.} {\bf\begin{verbatim} for_less( i, start, end ) \end{verbatim}} \desc{performs a for loop where \name{i} starts at \name{start} and increments until it is greater than or equal to \name{end}. Equivalent to \name{for( i = start; i < end; ++i )}.} {\bf\begin{verbatim} for_inclusive( i, start, end ) \end{verbatim}} \desc{performs a for loop where \name{i} starts at \name{start} and increments until it is greater than \name{end}. Equivalent to \name{for( i = start; i <= end; ++i )}.} {\bf\begin{verbatim} GLUE(x,y) \end{verbatim}} \desc{Special C source macro to stick two different identifiers together, i.e., \name{GLUE(colour,\_name)} results in \name{colour\_name}.} {\bf\begin{verbatim} GLUE3(x,y,z) \end{verbatim}} \desc{Special C source macro to stick three different identifiers together, i.e., \name{GLUE(a,b,c)} results in \name{abc}.} \chapter{Programming Utilities} A set of functions which are useful for general purpose, portable programming is provided. These include such basic areas as strings, time, file IO, etc. Many parts of the \vol\ refer to the programming utilities, and it is advisable that users of the \vol\ try to use these functions whenever convenient. The following is a list of all the programming utilities, grouped into related areas, and ordered alphabetically. \section{Strings} Some simple string manipulation techniques are provided. Strings are arbitrarily long \name{NULL}-terminated character arrays, which are allocated and deleted as needed. The type \name{STRING} is defined as: {\bf\begin{verbatim} typedef char *STRING; \end{verbatim}} The basic string creation and deletion routines are: {\bf\begin{verbatim} public STRING alloc_string( int length ) public STRING create_string( STRING initial ) \end{verbatim}} \desc{The function \name{alloc\_string} allocates storage for a string of the desired length (by allocating \name{length+1} bytes), without assigning any value to the string. The function \name{create\_string} creates an allocated string with the value equal to \name{initial}. If \name{initial} is a \name{NULL} pointer an empty string (``'') is created.} {\bf\begin{verbatim} public void delete_string( STRING string ) \end{verbatim}} \desc{The storage associated with a string may be deleted with this function.} {\bf\begin{verbatim} public int string_length( STRING string ) \end{verbatim}} \desc{Returns the length of the string.} {\bf\begin{verbatim} public BOOLEAN equal_strings( STRING str1, STRING str2 ) \end{verbatim}} \desc{Returns \name{TRUE} if the two strings are exactly equal.} {\bf\begin{verbatim} public void replace_string( STRING *string, STRING new_string ) \end{verbatim}} \desc{A convenience function which deletes the \name{string} argument, and reassigns it to the \name{new\_string}. It does not copy the value of \name{new\_string}, but merely sets the \name{string} to the pointer \name{new\_string}.} {\bf\begin{verbatim} public void concat_char_to_string( STRING *string, char ch ) \end{verbatim}} \desc{Concatenates a character to the end of the string.} {\bf\begin{verbatim} public STRING concat_strings( STRING str1, STRING str2 ) \end{verbatim}} \desc{Creates and returns a string which is the concatenation of the two arguments, without changing the string arguments.} {\bf\begin{verbatim} public void concat_to_string( STRING *string, STRING str2 ) \end{verbatim}} \desc{Replaces the argument \name{string} with the concatenation of the arguments \name{string} and \name{str2}.} {\bf\begin{verbatim} public BOOLEAN is_lower_case( char ch ) \end{verbatim}} \desc{Returns \name{TRUE} if the character is a lower case letter.} {\bf\begin{verbatim} public BOOLEAN is_upper_case( char ch ) \end{verbatim}} \desc{Returns \name{TRUE} if the character is a upper case letter.} {\bf\begin{verbatim} public char get_lower_case( char ch ) \end{verbatim}} \desc{If the character is upper case, returns the lower case version of the character, otherwise, returns the character itself.} {\bf\begin{verbatim} public char get_upper_case( char ch ) \end{verbatim}} \desc{If the character is lower case, returns the upper case version of the character, otherwise, returns the character itself.} {\bf\begin{verbatim} public BOOLEAN string_ends_in( STRING string, STRING ending ) \end{verbatim}} \desc{Determines if the string ends in the specified \name{ending}. For instance, passing the arguments, \name{"rainfall"} and \name{"fall"} returns \name{TRUE}.} {\bf\begin{verbatim} public STRING strip_outer_blanks( STRING str ) \end{verbatim}} \desc{Returns a string which is the argument \name{str} without any leading or trailing blanks.} {\bf\begin{verbatim} public void make_string_upper_case( STRING string ) \end{verbatim}} \desc{Converts the string to an all upper case string. Modifies the string in place.} {\bf\begin{verbatim} public int find_character( STRING string, char ch ) \end{verbatim}} \desc{Searches for the given character in the given \name{string}, returning the index where it was found, or -1 if it was not found.} {\bf\begin{verbatim} public BOOLEAN blank_string( STRING string ) \end{verbatim}} \desc{Returns true if the string is empty or consists of only space, tab, and newline characters.} \section{General File IO} Although one may use the standard UNIX file interface (\name{fprintf}, for example), the \vol\ contains a set of routines for doing all file operations, with the potential to be portable to other operating systems. There are some other minor advantages, including the automatic expansion of \name{\~\ } and environment variables. Also, automatic decompression of compressed files is provided. {\bf\begin{verbatim} public STRING expand_filename( STRING filename ) \end{verbatim}} \desc{Searches the argument \name{filename} for certain patterns, and expands them appropriately, returning the resulting expanded filename. Any sequence of characters starting with a \name{\~\ } up to but not including a slash, \name{/}, will be changed to the specified user's home directory. Any occurrence of a dollar sign, \name{\$}, will result in the following text, up to the next slash, being expanded to the environment variable specified by the text. This expansion can be avoided by placing a backslash, \name{$\backslash$}, before any \name{\~\ } or \name{\$}. In all the following functions which take filenames, automatic expansion of filenames is performed.} {\bf\begin{verbatim} public BOOLEAN file_exists( STRING filename ) \end{verbatim}} \desc{Returns \name{TRUE} if the file exists.} {\bf\begin{verbatim} public BOOLEAN check_clobber_file( STRING filename ) public BOOLEAN check_clobber_file_default_suffix( STRING filename, STRING default_suffix ) \end{verbatim}} \desc{Checks to see if the file exists, and if so, prompts the user as to whether it may be overwritten. Returns TRUE if either the file does not exist, or if it does and the user answers \name{`y'} to the prompt. The second form of the file appends a default suffix to the filename, if it does not yet have a suffix.} {\bf\begin{verbatim} public void remove_file( STRING filename ) \end{verbatim}} \desc{Removes the specified file, which results in the file being removed only after all references to it are closed.} {\bf\begin{verbatim} public BOOLEAN filename_extension_matches( STRING filename, STRING extension ) \end{verbatim}} \desc{Returns \name{TRUE} if the file ends in the given extension, preceded by a period. e.g., \name{filename\_extension\_matches( "volume.mnc" , "mnc" )} returns \name{TRUE}. Correctly handles compressed files, e.g., passing the arguments, \name{"volume.mnc.Z"} and \name{"mnc"} returns \name{TRUE}.} {\bf\begin{verbatim} public STRING remove_directories_from_filename( STRING filename ) \end{verbatim}} \desc{Strips the directories from the filename, returning the result.} {\bf\begin{verbatim} public STRING extract_directory( STRING filename ) \end{verbatim}} \desc{Extracts the directory from the filename, returning the result.} {\bf\begin{verbatim} public STRING get_absolute_filename( STRING filename, STRING directory ) \end{verbatim}} \desc{Given a filename and a current directory, returns an absolute filename (one starting with a slash, \name{/}.} {\bf\begin{verbatim} public Status open_file( STRING filename, IO_types io_type, File_formats file_format, FILE **file ) public Status open_file_with_default_suffix( STRING filename, STRING default_suffix, IO_types io_type, File_formats file_format, FILE **file ) \end{verbatim}} \desc{The function \name{open\_file()} opens the specified file, where \name{io\_type} must be one of \name{WRITE\_FILE} or \name{READ\_FILE}, and \name{file\_format} must be one of \name{ASCII\_FORMAT} or \name{BINARY\_FORMAT}. If successful, the file pointer is passed back in the last argument and a status of \name{OK} is returned. Otherwise, a null pointer is passed back, and a status of \name{ERROR} is returned. Filename expansion is automatically performed. The second function performs the same task as \name{open\_file} with the addition that it automatically adds the specified suffix extension, if needed. On input, if the specified file does not exist and the file does not have an extension, then it looks for the specified file with the default extension.} {\bf\begin{verbatim} public Status close_file( FILE *file ) \end{verbatim}} \desc{Closes the file, returning \name{OK} if successful.} {\bf\begin{verbatim} public Status set_file_position( FILE *file, long byte_position ) \end{verbatim}} \desc{Seeks to the specified position in the file, where 0 corresponds to the beginning of the file, returning \name{OK} if successful.} {\bf\begin{verbatim} public Status flush_file( FILE *file ) \end{verbatim}} \desc{Flushes the file buffer of any pending output, returning \name{OK} if successful.} {\bf\begin{verbatim} public Status input_character( FILE *file, char *ch ) \end{verbatim}} \desc{Inputs a character from the file and passes it back as the second argument. If the character is the end of file character, returns a status of \name{ERROR}, otherwise, \name{OK}.} {\bf\begin{verbatim} public Status unget_character( FILE *file, char ch ) \end{verbatim}} \desc{Places the character back on the input queue.} {\bf\begin{verbatim} public Status input_nonwhite_character( FILE *file, char *ch ) \end{verbatim}} \desc{Inputs the next non-white character, i.e. the next character that is neither a blank, a tab, or a newline character.} {\bf\begin{verbatim} public Status skip_input_until( FILE *file, char search_char ) \end{verbatim}} \desc{Inputs characters from the file until the specified search character is found.} {\bf\begin{verbatim} public Status input_string( FILE *file, STRING *str, char termination_char ) \end{verbatim}} \desc{Inputs a string from the file. The file is read into the string until either the termination character or a newline character is found. If the string ends at a newline character and the termination character is not a newline, the next character available from the file will be the newline character. Otherwise, the next character available is the one just after the termination character found.} {\bf\begin{verbatim} public Status input_quoted_string( FILE *file, STRING *str ) \end{verbatim}} \desc{Inputs a string from a file, delimited by quotation marks, returning \name{OK} or \name{ERROR}. After successful reading of a string, the next character available from the file is the one just after the ending quotation mark.} {\bf\begin{verbatim} public Status input_possibly_quoted_string( FILE *file, STRING *str ) \end{verbatim}} \desc{Inputs a string from a file, delimited by quotation marks or white space, returning \name{OK} or \name{ERROR}. After successful reading of a string, the next character available from the file is the one just after the ending quotation mark or last non-white space character.} {\bf\begin{verbatim} public Status input_line( FILE *file, STRING line ) \end{verbatim}} \desc{Inputs characters from the file into the argument \name{line}, up until the next newline character. If a newline was found, the next available character will be the one after the newline. The newline character is not stored in the string.} {\bf\begin{verbatim} public Status input_boolean( FILE *file, BOOLEAN *b ) \end{verbatim}} \desc{Inputs the next non-white character. If it is a ``\name{f}'' or ``\name{F}'', then the value \name{FALSE} is passed back. If it is a ``\name{t}'' or ``\name{T}'', then the value \name{TRUE} is passed back. Otherwise \name{ERROR} is returned.} {\bf\begin{verbatim} public Status input_short( FILE *file, short *s ) public Status input_unsigned_short( FILE *file, unsigned short *s ) public Status input_int( FILE *file, int *i ) public Status input_real( FILE *file, Real *r ) public Status input_float( FILE *file, float *f ) public Status input_double( FILE *file, double *d ) \end{verbatim}} \desc{Inputs a value of the specified type from an ascii file.} {\bf\begin{verbatim} public Status input_newline( FILE *file ) \end{verbatim}} \desc{Inputs and discards characters from the file up to and including the next newline character. Returns \name{OK} if a newline was found, or \name{ERROR} if the end of file was reached first.} {\bf\begin{verbatim} public Status input_binary_data( FILE *file, void *data, size_t element_size, int n ) \end{verbatim}} \desc{Inputs an array of data from a file, in binary format. The array contains \name{n} elements, each of size \name{element\_size}. Returns either \name{OK} or \name{ERROR}.} {\bf\begin{verbatim} public Status output_character( FILE *file, char ch ) \end{verbatim}} \desc{Outputs a character to the file, returning \name{OK} or \name{ERROR}.} {\bf\begin{verbatim} public Status output_string( FILE *file, STRING str ) \end{verbatim}} \desc{Outputs the specified string to the file, returning \name{OK} or \name{ERROR}.} {\bf\begin{verbatim} public Status output_quoted_string( FILE *file, STRING str ) \end{verbatim}} \desc{Outputs a quotation mark, the specified string, and a closing quotation mark.} {\bf\begin{verbatim} public Status output_newline( FILE *file ) \end{verbatim}} \desc{Outputs a newline character, returning \name{OK} or \name{ERROR}.} {\bf\begin{verbatim} public Status output_boolean( FILE *file, BOOLEAN b ) \end{verbatim}} \desc{If the argument is \name{TRUE}, then a space and the letter ``\name{T}'' is output, otherwise, a space and the letter ``\name{F}'' is output. } {\bf\begin{verbatim} public Status output_short( FILE *file, short s ) public Status output_unsigned_short( FILE *file, unsigned short s ) public Status output_int( FILE *file, int i ) public Status output_real( FILE *file, Real r ) public Status output_float( FILE *file, float f ) public Status output_double( FILE *file, double d ) \end{verbatim}} \desc{Outputs a space and then the specified value to an ascii file.} {\bf\begin{verbatim} public Status output_binary_data( FILE *file, void *data, size_t element_size, int n ) \end{verbatim}} \desc{Outputs an array of data to a file, in binary format. The array contains \name{n} elements, each of size \name{element\_size}. Returns either \name{OK} or \name{ERROR}.} {\bf\begin{verbatim} public Status io_binary_data( FILE *file, IO_types io_flag, void *data, size_t element_size, int n ) \end{verbatim}} \desc{Inputs or outputs the specified binary data, depending on whether the argument \name{io\_flag} is \name{READ\_FILE} or \name{WRITE\_FILE}.} {\bf\begin{verbatim} public Status io_newline( FILE *file, IO_types io_flag, File_formats format ) \end{verbatim}} \desc{Inputs or outputs an ascii newline character, depending on whether the argument \name{io\_flag} is \name{READ\_FILE} or \name{WRITE\_FILE}. If the \name{format} argument is \name{BINARY\_FORMAT}, this function does nothing.} {\bf\begin{verbatim} public Status io_quoted_string( FILE *file, IO_types io_flag, File_formats format, STRING str ) \end{verbatim}} \desc{If the \name{format} argument is \name{ASCII\_FORMAT}, inputs or outputs a quotation mark delimited string, depending on whether the argument \name{io\_flag} is \name{READ\_FILE} or \name{WRITE\_FILE}. IF the \name{format} argument is \name{BINARY\_FORMAT}, inputs or outputs a string preceded by an integer indicating the length of the string.} {\bf\begin{verbatim} public Status io_boolean( FILE *file, IO_types io_flag, File_formats format, BOOLEAN *b ) public Status io_short( FILE *file, IO_types io_flag, File_formats format, short *short_int ) public Status io_unsigned_short( FILE *file, IO_types io_flag, File_formats format, unsigned short *unsigned_short ) public Status io_unsigned_char( FILE *file, IO_types io_flag, File_formats format, unsigned char *c ) public Status io_int( FILE *file, IO_types io_flag, File_formats format, int *i ) public Status io_real( FILE *file, IO_types io_flag, File_formats format, Real *r ) public Status io_float( FILE *file, IO_types io_flag, File_formats format, float *f ) public Status io_double( FILE *file, IO_types io_flag, File_formats format, double *d ) \end{verbatim}} \desc{Inputs or outputs a binary or ascii value of the specified type.} {\bf\begin{verbatim} public Status io_ints( FILE *file, IO_types io_flag, File_formats format, int n, int *ints[] ) \end{verbatim}} \desc{Inputs or outputs an array of integers in binary or ascii format.} {\bf\begin{verbatim} public Status io_unsigned_chars( FILE *file, IO_types io_flag, File_formats format, int n, unsigned char *unsigned_chars[] ) \end{verbatim}} \desc{Inputs or outputs an array of unsigned characters in binary or ascii format.} \section{Memory Allocation} A set of macros is provided to allow easy allocation and deallocation of memory, with up to 5 dimensional arrays. Memory allocation checking is also performed, to catch errors such as freeing memory that was not allocated. Also, the memory allocation automatically tracks all memory allocated, so that detection of memory leaks (orphaned memory) is possible. \subsection{Basic Memory Allocation} The basic macros are as follows: {\bf\begin{verbatim} ALLOC( ptr, n_items ) \end{verbatim}} \desc{Allocates \name{n\_items} elements of the correct type, assigning the result to the argument \name{ptr}.} {\bf\begin{verbatim} FREE( ptr ) \end{verbatim}} \desc{Frees the memory pointed to by the argument \name{ptr}.} {\bf\begin{verbatim} REALLOC( ptr, n_items ) \end{verbatim}} \desc{Changes the size of the memory pointed to by \name{ptr} to be of size \name{n\_items} elements, possibly changing the value of \name{ptr} in the process.} {\bf\begin{verbatim} ALLOC_VAR_SIZED_STRUCT( ptr, element_type, n_elements ) \end{verbatim}} \desc{Allocates a variable sized structure, which must be of a specific form. The last element of the structure must be an array of size 1, and this array will constitute the variable-sized part of the structure. The argument \name{element\_type} must be the type of this last element, and the argument \name{n\_elements} is the desired number of elements to allocate for this array, in addition to the memory for the first part of the structure. An example of usage is:} \begin{verbatim} { struct { int a; float b; char data[1]; } *ptr; ALLOC_VAR_SIZED_STRUCT( ptr, char, 10 ); ptr->a = 1; ptr->b = 2.5; ptr->data[0] = 'a'; ptr->data[9] = 'i'; } \end{verbatim} {\bf\begin{verbatim} ALLOC2D( ptr, n1, n2 ) ALLOC3D( ptr, n1, n2, n3 ) ALLOC4D( ptr, n1, n2, n3, n4 ) ALLOC5D( ptr, n1, n2, n3, n4, n5 ) \end{verbatim}} \desc{Allocates a 2 to 5 dimensional array of size \name{n1} by \name{n2}, etc. and stores the result in the specified pointer, \name{ptr}. In the 2 dimensional case, this is accomplished with only 2 memory allocations, one to allocate \name{n1} times \name{n2} elements for the storage, and the second to allocate \name{n1} pointers into the first memory area. In general, there is one memory allocation for each dimension required.} {\bf\begin{verbatim} FREE2D( ptr ) FREE3D( ptr ) FREE4D( ptr ) FREE5D( ptr ) \end{verbatim}} \desc{Frees the memory associated with the multi-dimensional array.} {\bf\begin{verbatim} public void set_alloc_checking( BOOLEAN state ) \end{verbatim}} \desc{Enables or disables allocation checking. It is usually called at the beginning of a program to provide double-checking of allocation. It incurs an extra allocation every time one of the previous allocation macros is invoked. If this function is not called, allocation checking can be turned on by setting the environment variable \name{DEBUG\_ALLOC} to anything. Allocation checking detects three types of memory programming errors: \begin{itemize} \item[] freeing a pointer that was not allocated, \item[] by checking that memory chunks returned from the system malloc routine do not overlap existing ones, sometimes detects when the system memory has become corrupted, and \item[] by recording all memory allocated and printing out what is currently allocated, can detect memory leaks. \end{itemize} } {\bf\begin{verbatim} public void output_alloc_to_file( STRING filename ) \end{verbatim}} \desc{If memory checking was enabled, this function can be used to detect memory leaks. At the end of a program, the programmer should free up all memory that is known, then call this function. Any remaining allocated memory is printed out to a file, indicating the file and line number where the memory was allocated.} \subsection{Higher Level Array Allocation} In addition to the basic memory allocation macros described previously, a set of useful macros for dealing with arrays of dynamically changing size are provided: {\bf\begin{verbatim} SET_ARRAY_SIZE( array, previous_n_elems, new_n_elems, chunk_size ) \end{verbatim}} \desc{This macro increases or decreases the size of an array, by specifying the number of elements previously allocated to the array (starts out at zero). The \name{chunk\_size} argument defines the size of the memory chunks which are allocated. For instance, if \name{chunk\_size} is 100, then this macro will only reallocate the array if the size change crosses to a different multiple of 100, thus avoiding memory allocation every time it is called. This specification of the granularity of the memory allocation must be consistently specified; if this macro is called with a given variable and chunk size, then subsequent calls to this macro with the same variable must specify the same chunk size. Note also that the number passed in as \name{new\_n\_elems} must be passed in as \name{previous\_n\_elems} on the next call to this macro.} {\bf\begin{verbatim} ADD_ELEMENT_TO_ARRAY( array, n_elems, elem_to_add, chunk_size ) \end{verbatim}} \desc{Adds the argument \name{elem\_to\_add} to the array at the \name{n\_elems}'th index, then increments \name{n\_elems}. The argument \name{chunk\_size} specifies the granularity of memory allocation.} {\bf\begin{verbatim} DELETE_ELEMENT_FROM_ARRAY( array, n_elems, index_to_remove, chunk_size ) \end{verbatim}} \desc{Deletes the \name{index\_to\_remove}'th element from the array, decreasing the number of elements in the array (\name{n\_elems}) and decreasing the memory allocation, if crossing a multiple of \name{chunk\_size}. Again, \name{chunk\_size} must be specified the same for all invocations of the previous three macros involving a given pointer.} {\bf\begin{verbatim} ADD_ELEMENT_TO_ARRAY_WITH_SIZE( array, n_alloced, n_elems, elem_to_add, chunk_size ) \end{verbatim}} \desc{Adds an element (\name{elem\_to\_add}) to the array, incrementing \name{n\_elems}. If necessary, the memory is increased by the amount specified in \name{chunk\_size} and the \name{n\_alloced} variable is incremented by this amount. The usage of this differs from the use of \name{ADD\_ELEMENT\_TO\_ARRAY} in that the number of elements (\name{n\_elems}) can be decreased arbitrarily, without causing memory to be deallocated.} \section{Progress Reports} In order to provide simple monitoring of the progress of a particular processing task, a progress reporting module is available. While a task is in progress, the progress report prints dots across the line indicating how close to finished the task is. If the task is going to take very long, (greater than 2 minutes), the progress report periodically prints the current percentage done and the estimated time remaining. An example of usage, followed by function descriptions, is presented: \begin{verbatim} { int i, n_slices; progress_struct progress; n_slices = 100; initialize_progress_report( &progress, FALSE, n_slices, "Processing Slices" ); for( i = 0; i < n_slices; ++i ) { process_slice( i ); update_progress_report( &progress, i + 1 ); } terminate_progress_report( &progress ); } \end{verbatim} {\bf\begin{verbatim} public void initialize_progress_report( progress_struct *progress, BOOLEAN one_line_only, int n_steps, STRING title ) \end{verbatim}} \desc{Initializes a progress report struct, specifying the number of steps that will occur in the processing, and the title to print out for the progress report. During progress report, the display will automatically switch from the short-job mode of printing a single row of dots across a line to the long-job mode of periodically printing the percentage done and estimated time remaining. If the \name{one\_line\_only} flag is \name{TRUE}, this is disabled and only a single row of dots will be displayed.} {\bf\begin{verbatim} public void update_progress_report( progress_struct *progress, int current_step ) \end{verbatim}} \desc{Tells the progress reporting module how many steps have been done, and causes update of the display of dots on the line or estimated time remaining.} {\bf\begin{verbatim} public void terminate_progress_report( progress_struct *progress ) \end{verbatim}} \desc{Terminates the progress report.} \section{Text Output} Rather than using the standard UNIX function \name{printf} for routine text output, a module which is similar in appearance is provided, which allows for installing arbitrary printing output functions. This can be used, for instance, to mirror output to a log file for instance, or to send text to an X window. The primary change is to use a function called \name{print} or \name{print\_error} with exactly the same arguments as for the standard \name{printf} function. {\bf\begin{verbatim} public void print( STRING format, ... ) public void print_error( STRING format, ... ) \end{verbatim}} \desc{Takes the same arguments as \name{printf()}, but allows installing of a user output function for the final stage of output.} {\bf\begin{verbatim} public void set_print_function( void (*function) ( STRING ) ) public void set_print_error_function( void (*function) ( STRING ) \end{verbatim}} \desc{Sets the output function, where all text from calls to \name{print()} or \name{print\-\_error} will be sent. By default, there is no print function, and output is sent to printf().} {\bf\begin{verbatim} public void push_print_function() public void push_print_error_function() \end{verbatim}} \desc{Temporarily sets the print or error printing function to go to standard out, and allows the user to set another print function, which will disappear when the corresponding \name{pop} function is called.} {\bf\begin{verbatim} public void pop_print_function() public void pop_print_error_function() \end{verbatim}} \desc{Restores the previous user print or error printing function.} \section{Time} Some basic utilities relating to time, date, and CPU time are provided. {\bf\begin{verbatim} public Real current_cpu_seconds( void ) \end{verbatim}} \desc{Returns the number of CPU seconds used by the current process so far.} {\bf\begin{verbatim} public Real current_realtime_seconds( void ) \end{verbatim}} \desc{Returns the number of seconds that the current process has been running.} {\bf\begin{verbatim} public STRING get_clock_time() \end{verbatim}} \desc{Returns a string representing the current clock time (hours and minutes), for which the caller is reponsible for deleting.} {\bf\begin{verbatim} public STRING get_date() \end{verbatim}} \desc{Returns a string representing the current date, for which the caller is reponsible for deleting.} {\bf\begin{verbatim} public STRING format_time( STRING format, Real seconds ) \end{verbatim}} \desc{Takes a time in seconds and a format string which has format components, e.g. ``\%g \%s'', and prints the time into a string in appropriate units of milliseconds, seconds, minutes, days, etc. The string is returned and the calling program is responsible for deleting the string.} {\bf\begin{verbatim} public void print_time( STRING format, Real seconds ) \end{verbatim}} \desc{Same as \name{format\_time}, but calls \name{print()} with the result.} {\bf\begin{verbatim} public void sleep_program( Real seconds ) \end{verbatim}} \desc{Suspends the program for the specified number of seconds. Note that on most systems, this will only be performed to the nearest multiple of some particular time increment. On Silicon Graphics Systems this will be to the nearest hundredth of a second.} \chapter{Volumes} Processing tasks within the lab where this software was developed deal with multi-dimensional volumes of data such as created by Magnetic Resonance and PET scanners. Therefore, an extensive set of routines is provided to represent volumes, and to read and write volumes in the MINC format. The basic type of a volume is \name{Volume}, which is actually a pointer to an allocated structure which contains all the information about the type of volume, number of dimensions, voxel values, etc. In order to use a volume structure, the volume must first be created, then the size of the volume set, then the large array of voxel values is allocated. Alternately, a volume may be automatically created by calling the appropriate function to read a MINC file and create a volume. A volume has an associated number of dimensions, which must be in the range from one to five, but typically is three. The volume is thought of as a multi-dimensional array of any of a variety of types, including all sizes of integer and real types. Even though a volume may be stored in say, a 1 byte type, with values from zero to 255, there is a real value range which provides mapping a mapping from voxel values to any arbitrary real range. In this way, the real range may be any valid real interval and is independent of the particular storage type. Since most volumes will be created by reading from a MINC file, this method will be presented first, followed by a description of how to create a volume from scratch. Finally a lower level of MINC input and output for more advanced applications will be presented. \section{Volume Input} {\bf\begin{verbatim} public Status input_volume( STRING filename, int n_dimensions, STRING dim_names[], nc_type volume_nc_data_type, BOOLEAN volume_signed_flag, Real volume_voxel_min, Real volume_voxel_max, BOOLEAN create_volume_flag, Volume *volume, minc_input_options *options ) \end{verbatim}} \desc{This routine reads a volume from a MINC file, first creating the volume if the \name{create\_volume\_flag} is specified as \name{TRUE} (the usual case). The number of dimensions is the desired number of dimensions for the volume. If this is less than the number of dimensions in the file, then only the first part of the file, corresponding to this number of dimensions, is read. If the number of dimensions specified is less than 1, then the number of dimensions in the file is used. The argument \name{dim\_names} specifies in what order the volume is to be stored in the volume variable. For each dimension in the stored volume, there is a corresponding name, which is one of \name{MIxspace}, \name{MIyspace}, \name{MIzspace}, \name{ANY\_SPATIAL\_DIMENSION}, or an empty string. These are matched up with corresponding dimensions in the file and the dimension ordering of the volume array is reordered on input. So, if the user wishes to represent the volume in X-Z-Y order, then the value passed as the \name{dim\_names} array should be the three strings, \name{MIxspace}, \name{MIzspace}, and \name{MIyspace}. This choice of ordering is important, as it defines the order of any subsequent reference to voxel indices.} \desc{The four arguments, \name{volume\_nc\_data\_type} through \name{volume\_voxel\_max} can be used to specified the desired storage type within the volume variable, automatically converted from the storage type in the file. The \name{volume\_nc\_data\_type} is one of \name{MI\_ORIGINAL\_TYPE}, \name{NC\_BYTE}, \name{NC\_SHORT}, \name{NC\-\_LONG}, \name{NC\_FLOAT}, or \name{NC\_DOUBLE}. For the integer types, the \name{volume\-\_signed\-\_flag} is \name{TRUE} if a signed type is desired, otherwise, it is \name{FALSE}. The \name{volume\_voxel\_min} and \name{volume\_voxel\_max} specify the range of valid voxel values, and are usually set equal to indicate to use the full range of the type, e.g. zero to 255.0 for unsigned \name{NC\_BYTE}. If \name{MI\_ORIGINAL\_TYPE} is passed, then the type, sign, and voxel range in the file are used.} \desc{If the \name{create\_volume\_flag} is \name{TRUE}, the usual case, then the volume is automatically created. Otherwise, it is assumed that the volume already exists and will only be recreated if its current size is different from the new size resulting from the file, thus reducing the amount of memory allocation when reading multiple files.} \desc{The \name{options} argument specifies some special options to the input process, and is usually passed just a \name{NULL} pointer, indicating that the default options should be used. Currently the possible options are:} {\bf\begin{verbatim} public void set_default_minc_input_options( minc_input_options *options ) \end{verbatim}} \desc{Fills in the default options into an \name{options} structure which will subsequently be passed to \name{input\_volume()}.} {\bf\begin{verbatim} public void set_minc_input_promote_invalid_to_min_flag( minc_input_options *options, BOOLEAN flag ) \end{verbatim}} \desc{By default, any voxel value which is outside the valid range of voxel values is promoted to the minimum valid voxel value. If this \name{flag} is set to \name{FALSE}, this promotion is disabled.} {\bf\begin{verbatim} public void set_minc_input_vector_to_scalar_flag( minc_input_options *options, BOOLEAN flag ) \end{verbatim}} \desc{MINC and Volume\_IO treat a volume with MIvector\_dimension as the last (i.e.\ fastest varying) dimension as a \emph{vector volume}. By default, such a vector volume is converted to a scalar volume on input. The value at each voxel becomes the mean of the vector components for that voxel. This conversion can be disabled by passing the \name{flag} as \name{FALSE}.} {\bf\begin{verbatim} public void set_minc_input_vector_to_colour_flag( minc_input_options *options, BOOLEAN flag ) public void set_minc_input_colour_dimension_size( minc_input_options *options, int size ) public void set_minc_input_colour_indices( minc_input_options *options, int indices[4] ) \end{verbatim}} \desc{MINC and Volume\_IO treat a volume with MIvector\_dimension as the last (i.e. fastest varying) dimension as a \emph{vector volume}. Such a volume may be converted on input to a \emph{colour volume} by calling \name{set\-\_minc\-\_input\-\_vector\-\_to\-\_colour\-\_flag} with \name{flag} set to \name{TRUE}. If this option is set to true, any vector volume with the number of components specified by \name{set\_minc\_input\_colour\_dimension\_size} (default 3) is converted to a colour volume, using the indices specified by \name{set\-\_minc\-\_input\-\_colour\-\_indices} (default 0, 1, 2).} {\bf\begin{verbatim} public void set_minc_input_user_real_range( minc_input_options *options, double minimum, double maximum ) \end{verbatim}} \desc{By default, files read into an integer-type volume will be scaled so that the real range is the full range of the data in the input file. The user can define another range by calling this function with an appropriate real minimum and maximum. For float-type Volumes, setting the range will change the real range of the volume, but not change the actual values in the volume. If minimum is greater than or equal to maximum, then the default behaviour is restored.} \section{Alternative Volume Input Methods} Rather than using the \name{input\_volume()} function to input a volume in one shot, there is another method which will allow interspersing volume input with other processing tasks. The following is the set of routines which the \name{input\_volume()} function calls in order to input a volume. {\bf\begin{verbatim} public Status start_volume_input( STRING filename, int n_dimensions, STRING dim_names[], nc_type volume_nc_data_type, BOOLEAN volume_signed_flag, Real volume_voxel_min, Real volume_voxel_max, BOOLEAN create_volume_flag, Volume *volume, minc_input_options *options, volume_input_struct *input_info ) \end{verbatim}} \desc{This initializes a filename for inputting the volume incrementally. The arguments to this are identical to those for the \name{input\_volume()} function, with the addition of the \name{input\_info} structure which is initialized for use in the remaining functions. The volume is created if necessary, but not allocated, and no part of the volume is read in.} {\bf\begin{verbatim} public void delete_volume_input( volume_input_struct *input_info ) \end{verbatim}} \desc{Closes the file and terminates the input of the volume. By calling the \name{start\_volume\_input()} function followed by the \name{delete\_volume\_input()} function, a volume can be created that has all the information about the file volume, without the voxels being allocated.} {\bf\begin{verbatim} public void cancel_volume_input( Volume volume, volume_input_struct *input_info ) \end{verbatim}} \desc{Closes the file, terminates the input of the volume, and deletes the volume. Simply calls \name{delete\_volume\_input()} followed by \name{delete\_volume()}.} {\bf\begin{verbatim} public BOOLEAN input_more_of_volume( Volume volume, volume_input_struct *input_info, Real *fraction_done ) \end{verbatim}} \desc{Inputs a small chunk of the volume, calculated to be efficient, yet not be so large that one cannot usably intersperse calls to do other processing with calls to this function. Returns \name{TRUE} if there is more to do, i.e., this function should be called again. The fraction done is passed back as a number between 0 and 1.} {\bf\begin{verbatim} public Minc_file get_volume_input_minc_file( volume_input_struct *volume_input ) \end{verbatim}} \desc{The \name{Minc\_file} structure from the volume input is passed back, to allow use of this in routines that require this type.} \section{Volume Output} Volume output is accomplished by one of two routines, depending on whether or not the volume is treated as a modified version of another volume or is an independent volume on its own. {\bf\begin{verbatim} public Status output_volume( STRING filename, nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, Volume volume, STRING history, minc_output_options *options ) \end{verbatim}} \desc{Outputs the specified volume to the specified filename. If the argument \name{file\_nc\_data\_type} is \name{MI\_ORIGINAL\_TYPE} then the volume is stored in the MINC file in the same type as in the volume variable. Otherwise, the four arguments, \name{file\_nc\_data\_type}, \name{file\_signed\_flag}, \name{file\_voxel\_min}, and \name{file\_voxel\_max}, specify the type and valid voxel range to store the volume in the file. If the \name{history} argument is non-null, then it represents a description of the volume, and will be placed in the MINC volume. If the \name{options} argument is \name{NULL}, then the default options will be used. Otherwise, some specific output options can be set through this parameter, and the following functions:} {\bf\begin{verbatim} public void set_default_minc_output_options( minc_output_options *options ) \end{verbatim}} \desc{Sets the \name{options} structure to the default values. The user can then override the default values and pass the structure to the \name{output\_volume()} function. Currently, there is only one output option:} {\bf\begin{verbatim} public void delete_minc_output_options( minc_output_options *options ) \end{verbatim}} \desc{Deletes the \name{options} data.} {\bf\begin{verbatim} public void set_minc_output_dimensions_order( minc_output_options *options, int n_dimensions, STRING dimension_names[] ) \end{verbatim}} \desc{Defines the output order of the file. Each dimension name string must have a matching dimension name in the volume, which defines the order of the dimensions in the output file. For instance, one may have input the volume in \name{(x, y, z)} order. To get it output in \name{(z, y, x)} order, set \name{dimension\_names} to the three strings \name{MIzspace}, \name{MIyspace}, and \name{MIxspace}.} {\bf\begin{verbatim} public void set_minc_output_real_range( minc_output_options *options, Real real_min, Real real_max ) \end{verbatim}} \desc{Defines the image range that will appear in the file. By default, none is specified, and \name{output\_volume} uses the real minimum and maximum of the volume. To set the real range of the volume, see the relevant documentation for \name{set\_volume\_real\_range()}.} If the volume is a modification of another volume currently stored in a file, then it is more appropriate to use the following function to output the volume: {\bf\begin{verbatim} public Status output_modified_volume( STRING filename, nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, Volume volume, STRING original_filename, STRING history, minc_output_options *options ) \end{verbatim}} \desc{The only difference between this function and the other method of volume output (\name{output\_volume()}), is that this function copies auxiliary data from the original file (\name{original\_filename}) to the new file. This auxiliary data includes such items as patient name and other scanning data, and is not read into a volume, so the only way to correctly pass it along to a new MINC file is to use this function.} \section{Volume Manipulation} Once a volume has been created and allocated, there are many functions for manipulating the volume. Note that associated with each volume is a valid voxel range indicating the range of values actually stored in the volume, for instance, zero to 200 is one possible range for an unsigned byte volume. There is a second range, the \name{real} range, which is the mapping of the valid voxel range to an arbitrary real range, for instance, the zero to 200 of valid voxels could map to -1.5 to 1.5 in the \name{real} range. When dealing with volumes, one is generally interested in the \name{real} range. {\bf\begin{verbatim} public Real get_volume_voxel_value( Volume volume, int v0, int v1, int v2, int v3, int v4 ) \end{verbatim}} \desc{Given a volume and from one to five voxel indices, depending on the volume dimensions, returns the corresponding voxel value. For instance, if the volume is three dimensional, then the final two arguments are ignored.} {\bf\begin{verbatim} value = convert_voxel_to_value( volume, voxel ); \end{verbatim}} \desc{Given a volume and a voxel value, converts this to a value in the real range, and returns it.} {\bf\begin{verbatim} voxel = convert_value_to_voxel( volume, value ) \end{verbatim}} \desc{Given a volume and a real value, converts this to a voxel value in the valid voxel range, and returns it.} {\bf\begin{verbatim} public Real get_volume_real_value( Volume volume, int v0, int v1, int v2, int v3, int v4 ) \end{verbatim}} \desc{Given a volume and from one to five voxel indices, depending on the volume dimensions, returns the corresponding real value. For instance, if the volume is three dimensional, then the final two arguments are ignored.} {\bf\begin{verbatim} public void set_volume_voxel_value( Volume volume, int v0, int v1, int v2, int v3, int v4, Real voxel ) \end{verbatim}} \desc{Given a volume, one to five voxel indices, and a \name{voxel} value, assigns this value to the corresponding voxel in the volume. Note that no conversion from the valid real range to the valid voxel range is performed, so the user may need to use the \name{convert\_value\_to\_voxel} function first or use the \name{set\_volume\_real\_value} function.} {\bf\begin{verbatim} public void set_volume_real_value( Volume volume, int v0, int v1, int v2, int v3, int v4, Real value ) \end{verbatim}} \desc{Given a volume, one to five voxel indices, and a \name{value}, assigns this value to the corresponding voxel in the volume, after converting to a voxel value.} {\bf\begin{verbatim} public void delete_volume( Volume volume ) \end{verbatim}} \desc{Deletes all the memory associated with an volume.} {\bf\begin{verbatim} public nc_type get_volume_nc_data_type( Volume volume, BOOLEAN *signed_flag ) \end{verbatim}} \desc{Returns the storage type of the volume (for instance, \name{NC\_SHORT}), and passes back an indication of whether it is signed or unsigned.} {\bf\begin{verbatim} public int get_volume_n_dimensions( Volume volume ) \end{verbatim}} \desc{Returns the number of dimensions of the volume.} {\bf\begin{verbatim} public void get_volume_sizes( Volume volume, int sizes[] ) \end{verbatim}} \desc{Stores the size of each dimension in the array \name{sizes}. This is the number of voxels in each dimension. The array \name{sizes} must be at least as large as the number of dimensions of the volume.} {\bf\begin{verbatim} public void get_volume_separations( Volume volume, Real separations[] ) \end{verbatim}} \desc{Stores the slice separation for each dimension in the array \name{separations}. The array \name{separations} must be at least as large as the number of dimensions of the volume.} {\bf\begin{verbatim} public Real get_volume_voxel_min( Volume volume ) public Real get_volume_voxel_max( Volume volume ) public void get_volume_voxel_range( Volume volume, Real *voxel_min, Real *voxel_max ) \end{verbatim}} \desc{The first two functions return the minimum or maximum allowable voxel value. The third function passes back both values.} {\bf\begin{verbatim} public Real get_volume_real_min( Volume volume ) public Real get_volume_real_max( Volume volume ) public void get_volume_real_range( Volume volume, Real *min_value, Real *max_value ) \end{verbatim}} \desc{The first two functions return the minimum or maximum real value. The third function passes back both values. The mapping to this real space linearly maps the minimum \name{voxel} value to the minimum \name{real} value and the maximum \name{voxel} value to the maximum \name{real} value.} {\bf\begin{verbatim} public STRING *get_volume_dimension_names( Volume volume ) \end{verbatim}} \desc{Returns a pointer to the list of names of each dimension. This memory must be freed by the calling function using the following function.} {\bf\begin{verbatim} public void delete_dimension_names( Volume volume, STRING dimension_names[] ) \end{verbatim}} \desc{Frees the memory allocated for the dimension names.} {\bf\begin{verbatim} public void set_rgb_volume_flag( Volume volume, BOOLEAN flag ) \end{verbatim}} \desc{Sets the volume flag indicating whether the volume is of type red-green-blue colour. Only volumes whose data type is unsigned long may be rgb volumes.} {\bf\begin{verbatim} public BOOLEAN is_an_rgb_volume( Volume volume ) \end{verbatim}} \desc{Returns \name{TRUE} if the volume is a red-green-blue colour volume, as can be created on volume input.} \subsection{Volume Coordinate Systems} A volume has two coordinate systems. The {\bf voxel} coordinate system is simply the n-dimensional indexing coordinate system for a volume. A voxel coordinate of (0.0, 0.0, 0.0), for instance, corresponds to the centre of the first voxel in a three dimensional volume. A voxel coordinate of ( 99.0, 0.0, 0.0 ) corresponds to the centre of the last voxel in the first direction of a three dimensional volume of size ( 100, 200, 150 ). The second coordinate system is an arbitrary three dimensional coordinate system, usually referred to as the {\bf world} coordinate system, often the Talairach coordinate system. The following functions provide conversion to and from these two coordinate systems: {\bf\begin{verbatim} public void convert_voxel_to_world( Volume volume, Real voxel[], Real *x_world, Real *y_world, Real *z_world ) \end{verbatim}} \desc{Given a volume and a real valued voxel index, passes back the corresponding world coordinate.} {\bf\begin{verbatim} public void convert_3D_voxel_to_world( Volume volume, Real voxel1, Real voxel2, Real voxel3, Real *x_world, Real *y_world, Real *z_world ) \end{verbatim}} \desc{Same as \name{convert\_voxel\_to\_world} except it applies only to three dimensional volumes.} {\bf\begin{verbatim} public void convert_world_to_voxel( Volume volume, Real x_world, Real y_world, Real z_world, Real voxel[] ) \end{verbatim}} \desc{Converts a world coordinate into a voxel. In order to use these voxel coordinates as integer indices, for instance, as arguments to the \name{GET\_VALUE} macros, each component of the argument \name{voxel} must first be rounded to the nearest integer.} {\bf\begin{verbatim} public void convert_3D_world_to_voxel( Volume volume, Real x_world, Real y_world, Real z_world, Real *voxel1, Real *voxel2, Real *voxel3 ) \end{verbatim}} \desc{Same as \name{convert\_world\_to\_voxel} except it applies only to three dimensional volumes.} {\bf\begin{verbatim} public void convert_voxel_vector_to_world( Volume volume, Real voxel_vector[], Real *x_world, Real *y_world, Real *z_world ) public void convert_world_vector_to_voxel( Volume volume, Real x_world, Real y_world, Real z_world, Real voxel_vector[] ) \end{verbatim}} \desc{These two functions convert vectors between the voxel and world spaces. This is done by transforming the point (0,0,0) to the other space, in addition to treating the vector as a point and transforming it to the other space, and passing back the vector between the two results.} {\bf\begin{verbatim} public void convert_voxel_normal_vector_to_world( Volume volume, Real voxel1, Real voxel2, Real voxel3, Real *x_world, Real *y_world, Real *z_world ) \end{verbatim}} \desc{Converts a vector which is assumed to be a surface normal to the world coordinate system.} \subsection{Volume Interpolation} In addition to the routines for accessing particular voxel values, the volume can be interpolated using nearest neighbour, linear, or cubic interpolation, specified in either voxel or world space. {\bf\begin{verbatim} public int evaluate_volume( Volume volume, Real voxel[], BOOLEAN interpolating_dimensions[], int degrees_continuity, BOOLEAN use_linear_at_edge, Real outside_value, Real values[], Real **first_deriv, Real ***second_deriv ) \end{verbatim}} \desc{Interpolates a volume at the specified voxel, where \name{degrees\_continuity} has values -1, 0, or 2, for nearest neighbour, linear, or cubic interpolation. If \name{use\_linear\_at\_edge} is true, then any cubic interpolation will be downgraded to linear interpolation near the edge of the volume. This option is only needed in special cases. The parameter \name{outside\_value} is the value for any point outside the volume. The argument \name{interpolating\-\_dimensions} indicates which dimensions are being interpolated, typically a \name{NULL} pointer indicating that all dimensions are being interpolated. The interpolated values are placed in the values array. The number of values is equal to the number of values in the non-interpolated dimensions, which is one, if all dimensions are being interpolated. If the derivative arguments are non-null, then the resulting derivatives are placed in the appropriate places. The \name{first\_deriv} is a two dimensional array of size number of values by number of interpolating dimensions. The \name{second\_deriv} is a three dimensional array of size number of values by number of interpolating dimensions by number of interpolating dimensions.} {\bf\begin{verbatim} public void evaluate_volume_in_world( Volume volume, Real x, Real y, Real z, int degrees_continuity, BOOLEAN use_linear_at_edge, Real outside_value, Real values[], Real deriv_x[], Real deriv_y[], Real deriv_z[], Real deriv_xx[], Real deriv_xy[], Real deriv_xz[], Real deriv_yy[], Real deriv_yz[], Real deriv_zz[] ) \end{verbatim}} \desc{Interpolates a volume at the specified world position, where \name{degrees\-\_continuity} has values -1, 0, or 2, for nearest neighbour, linear, or cubic interpolation. If \name{use\_linear\_at\_edge} is true, then any cubic interpolation will be downgraded to linear interpolation near the edge of the volume. This option is only needed in special cases. The parameter \name{outside\_value} is the value for any point outside the volume. The interpolated values are placed in the values array. The number of values is equal to the number of values in the non-spatial dimensions, which is one if all dimensions are spatial. If the derivative arguments are non-null, then the resulting derivatives are placed in the appropriate places.} {\bf\begin{verbatim} public void set_volume_interpolation_tolerance( Real tolerance ) \end{verbatim}} \desc{For speed considerations, if a volume is evaluated at or near a voxel centre, then no interpolation is performed, and the voxel value is returned. The tolerance defines how close to the voxel centre this occurs, and defaults to 0. Note that if derivatives are desired and the degree of continuity specified is 0 or greater, then interpolation will be performed, even when within the specified tolerance of the voxel.} \section{Volume Creation from Scratch} In some circumstances, it is desirable to create volumes in ways other than reading from a file. The following functions provide methods to create a volume from scratch or to create a volume which is similar to an existing volume. {\bf\begin{verbatim} public Volume create_volume( int n_dimensions, STRING dimension_names[], nc_type nc_data_type, BOOLEAN signed_flag, Real voxel_min, Real voxel_max ) \end{verbatim}} \desc{Creates and returns a volume of the given type (for instance, \name{NC\_BYTE}, \name{signed\_flag} equal \name{FALSE}), and given valid voxel range. The \name{dimension\-\_names} is used to describe each dimension of the volume and is currently only used when writing the volume to a file.} {\bf\begin{verbatim} public void set_volume_voxel_range( Volume volume, Real voxel_min, Real voxel_max ) public void set_volume_real_range( Volume volume, Real real_min, Real real_max ) \end{verbatim}} \desc{After creation of a volume, the valid voxel range or valid real range can subsequently be changed by using these functions.} {\bf\begin{verbatim} public void set_volume_sizes( Volume volume, int sizes[] ) \end{verbatim}} \desc{Sets the sizes of the volume, the number of voxels in each dimension. Note that this must be done before calling the function \name{alloc\_volume\_data} to allocate the voxels.} {\bf\begin{verbatim} public void alloc_volume_data( Volume volume ) \end{verbatim}} \desc{After the volume has been created, and its size has been set, then this function allocates the memory for the voxels. Note that the voxel values are not initialized, and the user must fill the volume with desired values.} Associated with each volume is a transformation from \name{voxel} space to \name{world} space. There are several ways to define this transformation. The simplest is just to specify it directly: {\bf\begin{verbatim} public void set_voxel_to_world_transform( Volume volume, General_transform *transform ) \end{verbatim}} \desc{Assigns the given transformation to the volume.} {\bf\begin{verbatim} public General_transform *get_voxel_to_world_transform( Volume volume ) \end{verbatim}} \desc{Returns a pointer to the voxel to world transform of the volume.} {\bf\begin{verbatim} public void set_volume_separations( Volume volume, Real separations[] ) \end{verbatim}} \desc{Sets the inter-voxel separations in each of the volume dimensions. Note that this will cause the voxel-to-world transformation to be updated accordingly.} {\bf\begin{verbatim} public void set_volume_translation( Volume volume, Real voxel[], Real world_space_voxel_maps_to[] ) \end{verbatim}} \desc{Sets the translation portion of the voxel-to-world transformation. A voxel coordinate is specified (\name{voxel}), as well as a real world position to which it is desired that this voxel map (\name{world\_space\_voxel\_maps\_to}). The voxel-to-world transformation is updated to provide this mapping.} {\bf\begin{verbatim} public void set_volume_direction_cosine( Volume volume, int dimension, Real dir[] ) \end{verbatim}} \desc{Sets the real world axis for a specific voxel dimension. For instance if \name{dimension} is 1, and \name{dir} is (0.0, 1.0, 1.0), then voxels along the second dimension of the volume will map to the real world axis (0.0, 1.0, 1.0) normalized to unit length, then scaled by the volume separation for the second volume dimension.} {\bf\begin{verbatim} public void get_volume_direction_cosine( Volume volume, int dimension, Real dir[] ) \end{verbatim}} \desc{Passes back the real world axis for a specific voxel dimension. Note that \name{dimension} must be a spatial dimension in the volume.} {\bf\begin{verbatim} public void set_volume_space_name( Volume volume, STRING name ) \end{verbatim}} \desc{Sets the coordinate system type of the volume in terms of a string name. This can be any string, but a set of defined constants is given by MINC: \name{MI\_NATIVE}, \name{MI\_TALAIRACH}, and \name{MI\_CALLOSAL}.} {\bf\begin{verbatim} public STRING get_volume_space_name( Volume volume ) \end{verbatim}} \desc{Returns a copy of the coordinate system type of the volume in terms of a string name. The calling function must free this string when finished with it.} \subsection{Copying Volumes} Another method of creating a volume is to simply copy the entire volume definition from an existing volume: {\bf\begin{verbatim} public Volume copy_volume_definition( Volume existing_volume, nc_type nc_data_type, BOOLEAN signed_flag, Real voxel_min, Real voxel_max ) public Volume copy_volume_definition_no_alloc( Volume volume, nc_type nc_data_type, BOOLEAN signed_flag, Real voxel_min, Real voxel_max ) \end{verbatim}} \desc{Both functions creates and returns a new volume which has the same definition (sizes, voxel-to-world space transform, etc.), as an existing volume. If the argument \name{nc\_data\_type} is not \name{MI\_ORIGINAL\_TYPE}, then the storage type of the new volume differs from the original and is specified by \name{nc\_data\_type}, \name{signed\_flag}, \name{voxel\_min}, and \name{voxel\_max}. In the first function, the voxel values are allocated but not initialized. In the second function, they are not allocated.} {\bf\begin{verbatim} public Volume copy_volume( Volume volume ) \end{verbatim}} \desc{Creates an exact copy of a volume.} \subsection{Volume Caching} In order to efficiently handle volumes that are too large for virtual memory, a simple caching scheme has been implemented. Disk files are read and written on demand to provide the appearance of having large volumes fully resident in memory. All the volume routines described previously support this feature transparently, but there are a few routines for configuration of the volume caching. {\bf\begin{verbatim} public void set_n_bytes_cache_threshold( int threshold ) \end{verbatim}} \desc{Sets the threshold number of bytes for volume caching. If a volume larger than this is created, either explicitly or by input from a file, then that volume will be internally represented by the caching scheme. If this function is not called, the default is either 80 megabytes, or the value of the environment variable \name{VOLUME\_CACHE\_THRESHOLD}, if present. A threshold of zero will cause all volumes to be cached. A threshold less than zero will result in no volumes being cached.} {\bf\begin{verbatim} typedef enum { SLICE_ACCESS, RANDOM_VOLUME_ACCESS } Cache_block_size_hints; public void set_cache_block_sizes_hint( Cache_block_size_hints hint ) public void set_default_cache_block_sizes( int block_sizes[] ) \end{verbatim}} \desc{ When a voxel is accessed in a cached volume, the corresponding block containing the voxel is read from or written to the disk as necessary. These two functions control the default size of the blocks and therefore the tradeoff between fast access of adjacent voxels (using large block sizes) and fast access of arbitrarily distributed voxels (using small block sizes). The function \name{set\_cache\_block\_sizes\_hint} indicates that the default block sizes for volumes created in the future should be computed based on the assumption that the application will be accessing volume voxels mostly in a slice-by-slice manner (\name{SLICE\_ACCESS}) or in an unpredictable order (\name{RANDOM\_VOLUME\_ACCESS}). The second function, \name{set\-\_default\-\_cache\-\_block\-\_sizes}, provides an alternative where the default block sizes are explicitly set. A call to either function overrides any previous call to the other function. If neither of these functions is called, the default value is a block size of 8 voxels per dimension, or the value specified by the environment variable \name{VOLUME\_CACHE\_BLOCK\_SIZE}. These functions only affect volumes created afterwards. In order to change the value for a given volume, the following function may be used:} {\bf\begin{verbatim} public void set_volume_cache_block_sizes( Volume volume, int block_sizes[] ) \end{verbatim}} \desc{Sets the size of the cache block for the given volume. Because this function causes the cache to be completely flushed, in order to change the block size, it may incur a temporary speed penalty during subsequent voxel accesses which cause the cache to read blocks from a file} {\bf\begin{verbatim} public void set_default_max_bytes_in_cache( int n_bytes ) \end{verbatim}} \desc{Sets the default maximum number of bytes allowed in the cache for each volume. A higher number may provide faster access, due to a greater chance of finding a particular voxel within the cache, so this value should be as large as reasonable, given the amount of virtual memory available. If this function is not called, the default value is 80 megabytes, or the value of the environment variable \name{VOLUME\_CACHE\_SIZE}, if present. Setting a value of 0 will result in cached volumes having exactly one block in their cache. This function only affects volumes created subsequently. In order to change this value for a specific volume, the following function may be used:} {\bf\begin{verbatim} public void set_volume_cache_size( Volume volume, int max_memory_bytes ) \end{verbatim}} \desc{Sets the maximum number of bytes allowed in the cache for a particular volume. Calling this function flushes the cache, in order to reallocate the data structures to account for the new size. As in calling the function \name{set\_volume\_cache\_block\_sizes}, there may be a temporary speed loss in accessing pixels.} {\bf\begin{verbatim} public void set_cache_output_volume_parameters( Volume volume, STRING filename, nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, STRING original_filename, STRING history, minc_output_options *options ) \end{verbatim}} \desc{When a cached volume is modified, a temporary file is created to contain the voxel values. When the volume is deleted this file is also deleted. When a cached volume is output, the temporary file is copied to the output file, which results in two copies of the volume existing at once, which may incur unacceptable demands on disk storage, especially for large volumes. To avoid this, an application can specify a filename where to place the voxel values, which overrides the use of a temporary file. When the volume is deleted, this file is closed and remains on the disk, obviating the need for the application to output the volume. If the application later calls \name{output\_volume()} to output this volume to a file of the same name as that set by this function, the request to output will be ignored, because the volume already exists in this file. Basically, the programmer should call \name{set\_cache\_output\_volume\_parameters()} with the same parameters that will be passed to the eventual call to \name{output\_volume()}. If the volume is a cached volume, then the output file will be created as soon as a volume voxel is set, and the later call to \name{output\_volume()} will not recreate the file, but simply flush the cache buffer to make the file fully up to date. If the volume is not a cached volume, the call to \name{set\_cache\_output\_volume\_parameters()} will be ignored, and the later call to \name{output\_volume()} will create the file as specified. Note that when calling this function, it is important to delete the volume before exitting the program, so that cached volumes will flush their buffer and close the file, Otherwise, the most recent changes to the volume will not be written to the file.} \section{Source Code Example} An examples of reading, writing, and manipulating volumes is presented here. This is a complete program to read a MINC volume, change all values over 100.0 to 100.0, then write out the result in a new file. {\small \begin{verbatim} #include /* ------------------------------------------------------------------ @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ------------------------------------------------------------------ */ int main( int argc, char *argv[] ) { int v1, v2, v3, sizes[MAX_DIMENSIONS]; Real value; Volume volume; /*--- input the volume */ if( input_volume( "volume.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &volume, (minc_input_options *) NULL ) != OK ) return( 1 ); get_volume_sizes( volume, sizes ); /*--- change all values over 100 to 100 */ for( v1 = 0; v1 < sizes[0]; ++v1 ) { for( v2 = 0; v2 < sizes[1]; ++v2 ) { for( v3 = 0; v3 < sizes[2]; ++v3 ) { value = get_volume_real_value( volume, v1, v2, v3, 0, 0 ); if( value > 100.0 ) { set_volume_real_value( volume, v1, v2, v3, 0, 0, 100.0 ); } } } } /*--- output the modified volume */ if( output_modified_volume( "output.mnc", MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, volume, "volume.mnc", "Modified by clamping to 100", (minc_output_options *) NULL ) != OK ) return( 1 ); return( 0 ); } \end{verbatim} } \section{Multiple Volume Input} The \name{input\_volume} function described previously is intended to be a simple single-function interface for reading volumes for most applications. Occasionally, however, an application may not want to read the whole volume at once, or may need to break the input file into several volumes, for instance, the slices of a 3D volume. This can be facilitated by the following functions: {\bf\begin{verbatim} public Minc_file initialize_minc_input( STRING filename, Volume volume, minc_input_options *options ) \end{verbatim}} \desc{This functions opens a MINC file for input to the specified volume. The number of dimensions in the file must be greater than or equal to the number of dimensions in the volume, and each dimension name in the volume must have a matching dimension name in the file. A file handle is returned, for use in the following routines.} {\bf\begin{verbatim} public Minc_file initialize_minc_input_from_minc_id( int minc_id, Volume volume, minc_input_options *options ) \end{verbatim}} \desc{This performs the same task as \name{initialize\_minc\_input}, except it takes a previously opened MINC file as an argument, rather than a filename.} {\bf\begin{verbatim} public int get_minc_file_id( Minc_file file ) \end{verbatim}} \desc{Returns the MINC id of the file, a handle which can be used to perform MINC functions on the file.} {\bf\begin{verbatim} public int get_n_input_volumes( Minc_file file ) \end{verbatim}} \desc{Determines the total number of volumes in the opened MINC file. For instance, if the file contains x, y, z data of size 100 by 200 by 300 and the file was opened with a two dimensional x-z volume, then the number of volumes returned will be 200, the number of y slices.} {\bf\begin{verbatim} public BOOLEAN input_more_minc_file( Minc_file file, Real *fraction_done ) \end{verbatim}} \desc{Reads part of the MINC file to the volume specified in \name{initialize\-\_minc\-\_input}. This function must be called until it returns FALSE, at which point the volume has been fully read in. In order to read the next volume in the file, if any, the following function must be called.} {\bf\begin{verbatim} public BOOLEAN advance_input_volume( Minc_file file ) \end{verbatim}} \desc{Advances the input file to the next volume.} {\bf\begin{verbatim} public BOOLEAN reset_input_volume( Minc_file file ) \end{verbatim}} \desc{Resets the input to the beginning of the first volume in the file.} {\bf\begin{verbatim} public Status close_minc_input( Minc_file file ) \end{verbatim}} \desc{Closes the MINC file.} \section{Multiple Volume Output} Similarly to the multiple volume input, there are routines for providing output to a file by subvolumes. {\bf\begin{verbatim} public Minc_file initialize_minc_output( STRING filename, int n_dimensions, STRING dim_names[], int sizes[], nc_type file_nc_data_type, BOOLEAN file_signed_flag, Real file_voxel_min, Real file_voxel_max, General_transform *voxel_to_world_transform, Volume volume, minc_output_options *options ) \end{verbatim}} \desc{Opens a MINC file for creation. The arguments specify the number of dimensions and the names of each dimension, as well as the sizes in each dimensions. The type of the file is controlled by the four parameters, \name{file\_nc\_data\_type}, \name{file\_signed\_flag}, \name{file\_voxel\_min}, and \name{file\_voxel\_max}. The transformation to world coordinates is specified by the \name{voxel\_to\_world\_transform} argument. The \name{volume} is attached to file for output. The volume must have no more dimensions than the file and the names of each dimension must match with one of the dimensions in the file. The \name{options} are as specified for the \name{output\_volume} function. Note that, unlike the \name{output\_volume} function, if the image minimum and maximum are not specified, then the output file will have a separate image minimum and maximum for each image.} {\bf\begin{verbatim} public int get_minc_file_id( Minc_file file ) \end{verbatim}} \desc{Returns the MINC id of the file, a handle which can be used to perform MINC functions on the file.} {\bf\begin{verbatim} public Status copy_auxiliary_data_from_minc_file( Minc_file file, STRING filename, STRING history_string ) \end{verbatim}} \desc{Copies the auxiliary information from the MINC file specified in the \name{filename} argument to the open MINC \name{file}.} {\bf\begin{verbatim} public Status output_minc_volume( Minc_file file ) \end{verbatim}} \desc{Outputs the attached volume to the MINC file in the current file position. The file position is advanced by the size of the volume.} {\bf\begin{verbatim} public Status output_volume_to_minc_file_position( Minc_file file, Volume volume, int volume_count[], long file_start[] ) \end{verbatim}} \desc{More general routine to output the specified volume to the MINC file in the specified position. Since this routine does not update the file position, it does not interfere with normal volume output using the function \name{output\_minc\_volume}. The volume hyperslab defined by \name{volume\_count} is written to the file starting at the given file position.} {\bf\begin{verbatim} public Status close_minc_output( Minc_file file ) \end{verbatim}} \desc{Closes the MINC file.} \chapter{Tag Points} Tag points are sets of three dimensional points which are used to mark positions of interest. Generally these result from manually locating corresponding positions in multiple volumes to provide a mapping among the volumes. Tag points are stored in an ascii format devised at the McConnell Brain Imaging Centre, with a convention of filenames ending in \name{.tag}. A tag file can contain either sets of single tag points or two tag points, depending on whether the file corresponds to one or two volumes. Each tag point consists of three coordinates, x, y, and z. Each set of one or two tag points has additional optional information stored with it. A tag point set may or may not include a set of three values: a real valued weight, an integer structure id, and an integer patient id. A tag point may or may not include a label string. Functions to read and write files of this format are described: {\bf\begin{verbatim} public Status input_tag_points( FILE *file, int *n_volumes, int *n_tag_points, Real ***tags_volume1, Real ***tags_volume2, Real **weights, int **structure_ids, int **patient_ids, STRING *labels[] ) public Status input_tag_file( STRING filename, int *n_volumes, int *n_tag_points, Real ***tags_volume1, Real ***tags_volume2, Real **weights, int **structure_ids, int **patient_ids, STRING *labels[] ) \end{verbatim}} \desc{These two functions read a set of tag points from a file. The first form assumes the file is already open and will be closed by the calling function, while the second form opens and closes the file specified by a filename, with a default extension of \name{.tag}. The number of volumes (number of tags in a set, currently either one or two) is passed back in the \name{n\_volumes} argument. The number of tag points is passed back in the \name{n\_tag\_points} argument. The three dimensional coordinates of the first tag point in each set is passed back in the argument \name{tags\_volume1}. If the number of volumes is two, then the second tag point in each set is passed back in the argument \name{tags\_volume2}. The final four arguments pass back the auxiliary information associated with each tag point set. If the calling program is not interested in any one of the four data, then it can pass in a \name{NULL} pointer and the values in the file will not be passed back.} {\bf\begin{verbatim} public void free_tag_points( int n_volumes, int n_tag_points, Real **tags_volume1, Real **tags_volume2, Real weights[], int structure_ids[], int patient_ids[], STRING labels[] ) \end{verbatim}} \desc{When finished with a list of tag points, the associated memory may be freed by calling this function.} {\bf\begin{verbatim} public Status initialize_tag_file_input( FILE *file, int *n_volumes ) public BOOLEAN input_one_tag( FILE *file, int n_volumes, Real tag_volume1[], Real tag_volume2[], Real *weight, int *structure_id, int *patient_id, STRING *label, Status *status ) \end{verbatim}} \desc{These two routines provide a more memory efficient method to input tag points. After opening a file, the first routine is called to initialize the input of tags. The next routine is repeatedly called until it returns FALSE, reading one tag at a time.} {\bf\begin{verbatim} public Status output_tag_points( FILE *file, STRING comments, int n_volumes, int n_tag_points, Real **tags_volume1, Real **tags_volume2, Real weights[], int structure_ids[], int patient_ids[], STRING labels[] ) public Status output_tag_file( STRING filename, STRING comments, int n_volumes, int n_tag_points, Real **tags_volume1, Real **tags_volume2, Real weights[], int structure_ids[], int patient_ids[], STRING labels[] ) \end{verbatim}} \desc{These two functions write a list of tag points to a tag point file. The first form assumes that the file has already been opened and will be closed later by the calling function, while the second form opens and closes the file, with the default extension of \name{.tag}. The \name{comments} argument is any arbitrary string documenting the contents of this file. The number of volumes (\name{n\_volumes}) must be either one or two. The number of tag points is specified by the argument \name{n\_tag\_points}. The positions of the sets of one or two tag points are in the arguments \name{tags\_volume1} and \name{tags\_volume2}. If any of the three arguments, \name{weights}, \name{structure\_ids}, or \name{patient\_ids}, are specified as \name{NULL}, then none of these three pieces or information is written to the file. Similarly, if the \name{labels} argument is \name{NULL}, then no labels are written to the file.} {\bf\begin{verbatim} public STRING get_default_tag_file_suffix() \end{verbatim}} \desc{Returns a pointer to a string consisting of the default suffix for tag point files, currently \name{``tag''}. This pointer should not be freed or its contents modified.} {\bf\begin{verbatim} public Status initialize_tag_file_output( FILE *file, STRING comments, int n_volumes ) public Status output_one_tag( FILE *file, int n_volumes, Real tag_volume1[], Real tag_volume2[], Real *weight, int *structure_id, int *patient_id, STRING label ) public void terminate_tag_file_output( FILE *file ) \end{verbatim}} \desc{These two routines provide a more memory efficient method to output tag points. After opening a file, the first routine is called to initialize the output of tags. The next routine is repeatedly called to output a single tag point each time. The third routine is called to indicate the end of tag files.} \section{Source Code Example} The following is an example which reads a tag volume, removes all tags which have negative x positions, ignores the second tag point in each set, if present, and writes the result to a new file. {\small \begin{verbatim} #include int main( int argc, char *argv[] ) { int i, n_volumes, n_tag_points, *structure_ids, *patient_ids; Real **tags1, **tags2, *weights; STRING *labels; int new_n_tag_points, *new_structure_ids, *new_patient_ids; Real **new_tags1, *new_weights; STRING *new_labels; /*--- input the tag file */ if( input_tag_file( "input_tags.tag", &n_volumes, &n_tag_points, &tags1, &tags2, &weights, &structure_ids, &patient_ids, &labels ) != OK ) return( 1 ); /*--- create a new tag point list of only those tag points whose x coordinate is nonnegative */ new_n_tag_points = 0; for_less( i, 0, n_tag_points ) { if( tags1[i][0] >= 0.0 ) { /*--- increase the memory allocation of the tag points */ SET_ARRAY_SIZE( new_tags1, new_n_tag_points, new_n_tag_points+1, 10 ); ALLOC( new_tags1[new_n_tag_points], 3 ); SET_ARRAY_SIZE( new_weights, new_n_tag_points, new_n_tag_points+1, 10 ); SET_ARRAY_SIZE( new_structure_ids, new_n_tag_points, new_n_tag_points+1, 10 ); SET_ARRAY_SIZE( new_patient_ids, new_n_tag_points, new_n_tag_points+1, 10 ); SET_ARRAY_SIZE( new_labels, new_n_tag_points, new_n_tag_points+1, 10 ); ALLOC( new_labels[new_n_tag_points], strlen(labels[i])+1 ); /*--- copy from the input tags to the new tags */ new_tags1[new_n_tag_points][0] = tags1[i][0]; new_tags1[new_n_tag_points][1] = tags1[i][1]; new_tags1[new_n_tag_points][2] = tags1[i][2]; new_weights[new_n_tag_points] = weights[i]; new_structure_ids[new_n_tag_points] = structure_ids[i]; new_patient_ids[new_n_tag_points] = patient_ids[i]; (void) strcpy( new_labels[new_n_tag_points], labels[i] ); /*--- increment the number of new tags */ ++new_n_tag_points; } } /*--- output the new tags, the subset of the input tags */ if( output_tag_file( "output.tag", "Removed negative X's", 1, new_n_tag_points, new_tags1, NULL, new_weights, new_structure_ids, new_patient_ids, new_labels ) != OK ) return( 1 ); return( 0 ); } \end{verbatim} } \chapter{Transforms} In dealing with such tasks as inter- and intra-subject registration both within and across imaging modalities, the concept of transformations between different coordinate systems arises. A module is provided to handle both linear (affine) and non-linear transformations, and to provide input and output in a standardized Brain Imaging Centre format, usually to filenames with the extension \name{.xfm}. To support these functions, two structure types are provided. The first (\name{Transform}) is a four by four linear (affine) transform, which facilitates rigid transformations, consisting of scaling, rotation, translation, and shearing. The second is a higher level transform (\name{General\_transform}), which represents either a linear transform, a non-linear transform (thin-plate spline), a smoothly interpolated grid transform, a user definable transform, or a concatenation of two or more of these. \section{Linear Transforms} The linear transform functions all deal with objects whose type is \name{Transform}. {\bf\begin{verbatim} #define Transform_elem( transform, i, j ) \end{verbatim}} \desc{Is used to set or retrieve the value of the \name{i}'th row and \name{j}'th column of the transform, where $0 <= i,j <= 3$.} {\bf\begin{verbatim} public void make_identity_transform( Transform *transform ) \end{verbatim}} \desc{Creates a four by four identity transform.} {\bf\begin{verbatim} public void transform_point( Transform *transform, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans ) \end{verbatim}} \desc{Transforms a three dimensional point by the given transform, passing back the three transformed coordinates.} {\bf\begin{verbatim} public void transform_vector( Transform *transform, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans ) \end{verbatim}} \desc{Transforms a three dimensional vector by the given transform, passing back the three transformed coordinates. The only difference between transforming a point and a vector is that transforming a vector does not involve the translational component of the transform.} {\bf\begin{verbatim} public void inverse_transform_point( Transform *transform, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans ) \end{verbatim}} \desc{Assuming the transform is an orthogonal transform (no shear components), the point is transformed by the inverse of the transform.} {\bf\begin{verbatim} public void inverse_transform_vector( Transform *transform, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans ) \end{verbatim}} \desc{Assuming the transform is an orthogonal transform (no shear components), the vector is transformed by the inverse of the transform.} {\bf\begin{verbatim} public void concat_transforms( Transform *result, Transform *t1, Transform *t2 ) \end{verbatim}} \desc{Multiplies the transform \name{t2} by the transform \name{t1}, storing the product in \name{result}. Transforming a point by \name{result} is equivalent to transforming the point by \name{t1}, then transforming the result by \name{t2}.} \section{General Transforms} General transforms can represent linear transforms, thin\--\-plate spline transforms, grid transforms, and user defined transforms, and concatenations of these. All functions dealing with general transforms involve objects of type \name{General\-\_transform}. {\bf\begin{verbatim} public void create_linear_transform( General_transform *transform, Transform *linear_transform ) \end{verbatim}} \desc{Creates a general transform consisting of a single linear transform, specified by \name{linear\_transform}. If a \name{NULL} is passed as the argument \name{linear\-\_transform}, then an identity transform is created.} {\bf\begin{verbatim} public void create_thin_plate_transform( General_transform *transform, int n_dimensions, int n_points, float **points, float **displacements ) \end{verbatim}} \desc{Creates a general transform consisting of a thin plate spline, which provides a smooth non-linear mapping of a multidimensional space. The \name{points} argument is an array of size \name{n\_points} by \name{n\_dimensions}, representing a set of points. The \name{displacements} is a (\name{n\_points} + \name{n\_dimensions} + 1) by \name{n\_dimensions} array, which is created by the function \name{get\_\-nonlinear\_\-warp()}, which is not included in this library.} {\bf\begin{verbatim} public void create_grid_transform( General_transform *transform, Volume displacement_volume ) \end{verbatim}} \desc{Creates a general transform consisting of a grid transform, which provides a smooth non-linear mapping of a multidimensional space. The \name{displacment\_volume} argument is a four dimensional volume representing the displacements for the x, y, and z directions. Three of the dimensions of the volume must correspond to the x, y, and z spatial dimensions, and the fourth must have exactly three components, the displacements in each direction in world space. The dimensions may be in any order.} {\bf\begin{verbatim} typedef void (*User_transform_function)( void *user_data, Real x, Real y, Real z, Real *x_trans, Real *y_trans, Real *z_trans ) public void create_user_transform( General_transform *transform, void *user_data, size_t size_user_data, User_transform_function transform_function, User_transform_function inverse_transform_function ) \end{verbatim}} \desc{Creates a user defined transformation, by copying the user data (\name{size\-\_user\-\_data} bytes of data starting at \name{user\_data}). Two function pointers are also required, to specify the method of transforming points and inversely transforming points. These functions are of the type \name{User\-\_transform\-\_function}, which is specified above.} {\bf\begin{verbatim} public void delete_general_transform( General_transform *transform ) \end{verbatim}} \desc{Frees up the memory stored in the general transform structure.} {\bf\begin{verbatim} public Transform_types get_transform_type( General_transform *transform ) \end{verbatim}} \desc{Returns the general transform type, one of \name{LINEAR}, \name{THIN\_PLATE\_SPLINE}, \name{USER\_TRANSFORM}, or \name{CONCATENATED\_TRANSFORM}.} {\bf\begin{verbatim} public Transform *get_linear_transform_ptr( General_transform *transform ) \end{verbatim}} \desc{If the general transform is of type \name{LINEAR}, then returns a pointer to the linear transform (of type \name{Transform}), for use with the routines specific to linear transforms, described earlier. Otherwise prints an error message.} {\bf\begin{verbatim} public void concat_general_transforms( General_transform *first, General_transform *second, General_transform *result ) \end{verbatim}} \desc{Concatenates two general transforms. If both transforms are of type \name{LINEAR}, then the result is also of this type, being the matrix product of the two. Otherwise, the resulting transform is simply the concatenation of the two transforms.} {\bf\begin{verbatim} public int get_n_concated_transforms( General_transform *transform ) \end{verbatim}} \desc{Returns the number of concatenated transforms in the given transform. If the type of the transform is \name{CONCATENATED\_TRANSFORM}, then the number returned is the number of transforms, otherwise it is one.} {\bf\begin{verbatim} public General_transform *get_nth_general_transform( General_transform *transform, int n ) \end{verbatim}} \desc{If the transform is of type \name{CONCATENATED\_TRANSFORM}, then a pointer to the \name{n}'th transform is returned, where \name{n} is greater than or equal to zero and less than the number of transforms in the concatenated transform.} \section{Using General Transforms} {\bf\begin{verbatim} public void general_transform_point( General_transform *transform, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) \end{verbatim}} \desc{Transforms a three dimensional point by a general transform, passing back the result in the last three arguments.} {\bf\begin{verbatim} public void general_inverse_transform_point( General_transform *transform, Real x, Real y, Real z, Real *x_transformed, Real *y_transformed, Real *z_transformed ) \end{verbatim}} \desc{Transforms a three dimensional point by the inverse of the general transform, passing back the result in the last three arguments.} {\bf\begin{verbatim} public void copy_general_transform( General_transform *transform, General_transform *copy ) \end{verbatim}} \desc{Creates a copy of the general transform, allocating memory within the structure as required.} {\bf\begin{verbatim} public void create_inverse_general_transform( General_transform *transform, General_transform *inverse ) \end{verbatim}} \desc{Creates a new general transform that is the inverse of the given one.} {\bf\begin{verbatim} public void invert_general_transform( General_transform *transform ) \end{verbatim}} \desc{Changes the transform to be its inverse. Calling it twice on the same transform is equivalent to not calling the function at all.} \section{Reading and Writing General Transforms} General transforms are stored in files in an ascii format devised at the McConnell Brain Imaging Centre, and usually have a filename extension of \name{.xfm}. The input and output functions are: {\bf\begin{verbatim} public Status output_transform_file( STRING filename, STRING comments, General_transform *transform ) public Status output_transform( FILE *file, STRING filename, int *volume_count_ptr, STRING comments, General_transform *transform ) \end{verbatim}} \desc{These two functions write the general transform to a file, in the appropriate format. The \name{comments} line is an arbitrary string which is stored in the file for documentation purposes. Newline characters in the \name{comments} correctly result in a multi-line comment with a comment character inserted at the beginning of each line. The first form opens the file, with a default extension of \name{.xfm}, writes the transform, then closes the file. The second form of the function assumes the file is already open and will later be closed. Because the transform may contain pointers to MINC files that define the transform, the name of the file must be passed in to this function, to be used to create the name of the MINC files. The volume\_count\_ptr must point to an integer that has been initialized. Each time an auxiliary MINC file of the transform is created, the integer is used to create a unique filename, and then the volume\_count\_ptr is incremented. Both functions return \name{ERROR} or \name{OK}.} {\bf\begin{verbatim} public Status input_transform( FILE *file, STRING filename, General_transform *transform ) public Status input_transform_file( STRING filename, General_transform *transform ) \end{verbatim}} \desc{Inputs a general transform from a file. The first form assumes the file has already been opened for input, and will later be closed. The second form opens the file for input, with a default extension of \name{.xfm}, reads the transform, then closes the file. Both functions return \name{ERROR} or \name{OK}.} {\bf\begin{verbatim} public STRING get_default_transform_file_suffix() \end{verbatim}} \desc{Returns a pointer to a string consisting of the default suffix for transform files, currently \name{``xfm''}. This pointer should not be freed or its contents modified.} \chapter{Final Source Code Example} This is an example which attempts to illustrate a typical processing task incorporating use of volumes, tag points, and transformations. This is a full program which, when linked to the \vol, reads two volumes in MINC format, a set of tag points from file, and a transformation from file. The tag points are assumed to be in the world space of the first volume, and the transformation is assumed to transform points in the world space of the first volume to the world space of the second volume. The program transforms each tag point by the transformation input (presumably transforming from the world space of the first volume to that of the second volume), then transforms the result to the voxel space of the second volume. If the voxel coordinate is within the second volume, then the value of the corresponding voxel is printed. {\small \begin{verbatim} #include /* ------------------------------------------------------------------ @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ------------------------------------------------------------------ */ int main() { int v1, v2, v3, sizes[MAX_DIMENSIONS]; Real x_world2, y_world2, z_world2; Real voxel2[MAX_DIMENSIONS]; Real voxel_value; Volume volume1, volume2; int i, n_volumes, n_tag_points; int *structure_ids, *patient_ids; Real **tags1, **tags2, *weights; STRING *labels; General_transform transform; /*--- input the two volumes */ if( input_volume( "volume1.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &volume1, (minc_input_options *) NULL ) != OK ) return( 1 ); if( input_volume( "volume2.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &volume2, (minc_input_options *) NULL ) != OK ) return( 1 ); /*--- input the tag points */ if( input_tag_file( "tags_volume1.tag", &n_volumes, &n_tag_points, &tags1, &tags2, &weights, &structure_ids, &patient_ids, &labels ) != OK ) return( 1 ); /*--- input the general transform */ if( input_transform_file( "vol1_to_vol2.xfm", &transform ) != OK ) return( 1 ); /*--- convert each tag point */ get_volume_sizes( volume2, sizes ); for_less( i, 0, n_tag_points ) { /*--- transform the tag points from volume 1 to volume 2 world space */ general_transform_point( &transform, tags1[i][X], tags1[i][Y], tags1[i][Z], &x_world2, &y_world2, &z_world2 ); /*--- transform from volume 2 world space to volume 2 voxel space */ convert_world_to_voxel( volume2, x_world2, y_world2, z_world2, voxel2 ); /*--- convert voxel coordinates to voxel indices */ v1 = ROUND( voxel2[0] ); v2 = ROUND( voxel2[1] ); v3 = ROUND( voxel2[2] ); /*--- check if voxel indices inside volume */ if( v1 >= 0 && v1 < sizes[0] && v2 >= 0 && v2 < sizes[1] && v3 >= 0 && v3 < sizes[2] ) { voxel_value = get_volume_real_value( volume2, v1, v2, v3, 0, 0 ); print( "The value for tag point %d (%s) is: %g\n", i, labels[i], voxel_value ); } else print( "The tag point %d (%s) is outside.\n" ); } /*--- free up memory */ delete_volume( volume1 ); delete_volume( volume2 ); free_tag_points( n_volumes, n_tag_points, tags1, tags2, weights, structure_ids, patient_ids, labels ); delete_general_transform( &transform ); return( 0 ); } \end{verbatim} } \end{document} minc-2.2.00/volume_io/Testing/0000755000265600003100000000000012030114724013124 500000000000000minc-2.2.00/volume_io/Testing/Makefile.am0000644000265600003100000000067212027132664015116 00000000000000# Programming examples and test programs. INCLUDES = \ -I$(top_srcdir)/libsrc \ -I$(top_builddir)/volume_io/Include \ -I$(top_srcdir)/volume_io/Include \ -I$(top_srcdir)/progs/Proglib LDADD = ../../libvolume_io2.la ../../libminc2.la noinst_PROGRAMS = example_modify example_tags example_volume_io check_PROGRAMS = test-xfm TESTS = check_xfm.sh EXTRA_DIST = $(TESTS) \ t1.xfm t2.xfm t3.xfm t3_grid_0.mnc minc-2.2.00/volume_io/Testing/Makefile.in0000644000265600003100000004374312030077514015131 00000000000000# Makefile.in generated by automake 1.10.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Programming examples and test programs. VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = example_modify$(EXEEXT) example_tags$(EXEEXT) \ example_volume_io$(EXEEXT) check_PROGRAMS = test-xfm$(EXEEXT) subdir = volume_io/Testing DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mni_REQUIRE_LIB.m4 \ $(top_srcdir)/m4/smr_WITH_BUILD_PATH.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = PROGRAMS = $(noinst_PROGRAMS) example_modify_SOURCES = example_modify.c example_modify_OBJECTS = example_modify.$(OBJEXT) example_modify_LDADD = $(LDADD) example_modify_DEPENDENCIES = ../../libvolume_io2.la ../../libminc2.la example_tags_SOURCES = example_tags.c example_tags_OBJECTS = example_tags.$(OBJEXT) example_tags_LDADD = $(LDADD) example_tags_DEPENDENCIES = ../../libvolume_io2.la ../../libminc2.la example_volume_io_SOURCES = example_volume_io.c example_volume_io_OBJECTS = example_volume_io.$(OBJEXT) example_volume_io_LDADD = $(LDADD) example_volume_io_DEPENDENCIES = ../../libvolume_io2.la \ ../../libminc2.la test_xfm_SOURCES = test-xfm.c test_xfm_OBJECTS = test-xfm.$(OBJEXT) test_xfm_LDADD = $(LDADD) test_xfm_DEPENDENCIES = ../../libvolume_io2.la ../../libminc2.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/ac_config_aux/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = example_modify.c example_tags.c example_volume_io.c \ test-xfm.c DIST_SOURCES = example_modify.c example_tags.c example_volume_io.c \ test-xfm.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POD2MAN = @POD2MAN@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_F77 = @ac_ct_F77@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = \ -I$(top_srcdir)/libsrc \ -I$(top_builddir)/volume_io/Include \ -I$(top_srcdir)/volume_io/Include \ -I$(top_srcdir)/progs/Proglib LDADD = ../../libvolume_io2.la ../../libminc2.la TESTS = check_xfm.sh EXTRA_DIST = $(TESTS) \ t1.xfm t2.xfm t3.xfm t3_grid_0.mnc all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu volume_io/Testing/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu volume_io/Testing/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done example_modify$(EXEEXT): $(example_modify_OBJECTS) $(example_modify_DEPENDENCIES) @rm -f example_modify$(EXEEXT) $(LINK) $(example_modify_OBJECTS) $(example_modify_LDADD) $(LIBS) example_tags$(EXEEXT): $(example_tags_OBJECTS) $(example_tags_DEPENDENCIES) @rm -f example_tags$(EXEEXT) $(LINK) $(example_tags_OBJECTS) $(example_tags_LDADD) $(LIBS) example_volume_io$(EXEEXT): $(example_volume_io_OBJECTS) $(example_volume_io_DEPENDENCIES) @rm -f example_volume_io$(EXEEXT) $(LINK) $(example_volume_io_OBJECTS) $(example_volume_io_LDADD) $(LIBS) test-xfm$(EXEEXT): $(test_xfm_OBJECTS) $(test_xfm_DEPENDENCIES) @rm -f test-xfm$(EXEEXT) $(LINK) $(test_xfm_OBJECTS) $(test_xfm_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example_modify.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example_tags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example_volume_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-xfm.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: minc-2.2.00/volume_io/Testing/example_modify.c0000644000265600003100000000375412027132664016234 00000000000000#include /* ------------------------------------------------------------------ @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ------------------------------------------------------------------ */ int main( int argc, char *argv[] ) { int v1, v2, v3, sizes[MAX_DIMENSIONS]; Real value; Volume volume; /*--- input the volume */ if( input_volume( "volume.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &volume, (minc_input_options *) NULL ) != OK ) return( 1 ); get_volume_sizes( volume, sizes ); /*--- change all values over 100 to 100 */ for( v1 = 0; v1 < sizes[0]; ++v1 ) { for( v2 = 0; v2 < sizes[1]; ++v2 ) { for( v3 = 0; v3 < sizes[2]; ++v3 ) { value = get_volume_real_value( volume, v1, v2, v3, 0, 0 ); if( value > 100.0 ) { set_volume_real_value( volume, v1, v2, v3, 0, 0, 100.0 ); } } } } /*--- output the modified volume */ if( output_modified_volume( "output.mnc", MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, volume, "volume.mnc", "Modified by clamping to 100", (minc_output_options *) NULL ) != OK ) return( 1 ); return( 0 ); } minc-2.2.00/volume_io/Testing/example_tags.c0000644000265600003100000000677712027132664015713 00000000000000#include /* ---------------------------------------------------------------------------- @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- */ int main( int argc, char *argv[] ) { int i, n_volumes, n_tag_points, *structure_ids, *patient_ids; Real **tags1, **tags2, *weights; STRING *labels; int new_n_tag_points, *new_structure_ids, *new_patient_ids; Real **new_tags1, *new_weights; STRING *new_labels; /*--- input the tag file */ if( input_tag_file( "input_tags.tag", &n_volumes, &n_tag_points, &tags1, &tags2, &weights, &structure_ids, &patient_ids, &labels ) != OK ) return( 1 ); /*--- create a new tag point list of only those tag points whose x coordinate is nonnegative */ new_n_tag_points = 0; for_less( i, 0, n_tag_points ) { if( tags1[i][0] >= 0.0 ) { /*--- increase the memory allocation of the tag points */ SET_ARRAY_SIZE( new_tags1, new_n_tag_points, new_n_tag_points+1, 10 ); ALLOC( new_tags1[new_n_tag_points], 3 ); SET_ARRAY_SIZE( new_weights, new_n_tag_points, new_n_tag_points+1, 10 ); SET_ARRAY_SIZE( new_structure_ids, new_n_tag_points, new_n_tag_points+1, 10 ); SET_ARRAY_SIZE( new_patient_ids, new_n_tag_points, new_n_tag_points+1, 10 ); SET_ARRAY_SIZE( new_labels, new_n_tag_points, new_n_tag_points+1, 10 ); new_labels[new_n_tag_points] = create_string( labels[i] ); /*--- copy from the input tags to the new tags */ new_tags1[new_n_tag_points][0] = tags1[i][0]; new_tags1[new_n_tag_points][1] = tags1[i][1]; new_tags1[new_n_tag_points][2] = tags1[i][2]; new_weights[new_n_tag_points] = weights[i]; new_structure_ids[new_n_tag_points] = structure_ids[i]; new_patient_ids[new_n_tag_points] = patient_ids[i]; /*--- increment the number of new tags */ ++new_n_tag_points; } } /*--- output the new tags, the subset of the input tags */ if( output_tag_file( "output.tag", "Removed negative X's", 1, new_n_tag_points, new_tags1, NULL, new_weights, new_structure_ids, new_patient_ids, new_labels ) != OK ) return( 1 ); free_tag_points( n_volumes, n_tag_points, tags1, tags2, weights, structure_ids, patient_ids, labels ); free_tag_points( 1, new_n_tag_points, new_tags1, NULL, new_weights, new_structure_ids, new_patient_ids, new_labels ); return( 0 ); } minc-2.2.00/volume_io/Testing/example_volume_io.c0000644000265600003100000000707512027132664016743 00000000000000#include /* ------------------------------------------------------------------ @COPYRIGHT : Copyright 1993,1994,1995 David MacDonald, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ------------------------------------------------------------------ */ int main() { int v1, v2, v3, sizes[MAX_DIMENSIONS]; Real x_world2, y_world2, z_world2; Real voxel2[MAX_DIMENSIONS]; Real voxel_value; Volume volume1, volume2; int i, n_volumes, n_tag_points; int *structure_ids, *patient_ids; Real **tags1, **tags2, *weights; STRING *labels; General_transform transform; /*--- input the two volumes */ if( input_volume( "volume1.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &volume1, (minc_input_options *) NULL ) != OK ) return( 1 ); if( input_volume( "volume2.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &volume2, (minc_input_options *) NULL ) != OK ) return( 1 ); /*--- input the tag points */ if( input_tag_file( "tags_volume1.tag", &n_volumes, &n_tag_points, &tags1, &tags2, &weights, &structure_ids, &patient_ids, &labels ) != OK ) return( 1 ); /*--- input the general transform */ if( input_transform_file( "vol1_to_vol2.xfm", &transform ) != OK ) return( 1 ); /*--- convert each tag point */ get_volume_sizes( volume2, sizes ); for_less( i, 0, n_tag_points ) { /*--- transform the tag points from volume 1 to volume 2 world space */ general_transform_point( &transform, tags1[i][X], tags1[i][Y], tags1[i][Z], &x_world2, &y_world2, &z_world2 ); /*--- transform from volume 2 world space to volume 2 voxel space */ convert_world_to_voxel( volume2, x_world2, y_world2, z_world2, voxel2 ); /*--- convert voxel coordinates to voxel indices */ v1 = ROUND( voxel2[0] ); v2 = ROUND( voxel2[1] ); v3 = ROUND( voxel2[2] ); /*--- check if voxel indices inside volume */ if( v1 >= 0 && v1 < sizes[0] && v2 >= 0 && v2 < sizes[1] && v3 >= 0 && v3 < sizes[2] ) { voxel_value = get_volume_real_value( volume2, v1, v2, v3, 0, 0 ); print( "The value for tag point %d (%s) is: %g\n", i, labels[i], voxel_value ); } else print( "The tag point %d (%s) is outside.\n" ); } /*--- free up memory */ delete_volume( volume1 ); delete_volume( volume2 ); free_tag_points( n_volumes, n_tag_points, tags1, tags2, weights, structure_ids, patient_ids, labels ); delete_general_transform( &transform ); return( 0 ); } minc-2.2.00/volume_io/Testing/test-xfm.c0000644000265600003100000000350512027132664014773 00000000000000#define _GNU_SOURCE 1 #include #include #include Real tolerance = 1e-8; int is_equal_real( Real e, Real a ) { return fabs(e-a) < tolerance; } /* Args: expected, actual. */ void assert_equal_point( Real ex, Real ey, Real ez, Real ax, Real ay, Real az, const char* msg ) { if ( is_equal_real(ex,ax) && is_equal_real(ey,ay) && is_equal_real(ez,az) ) return; printf( "%s failure.\n" "Expected: %f %f %f\n" " Actual: %f %f %f\n", msg, ex,ey,ez, ax,ay,az ); exit(3); } int main( int ac, char* av[] ) { int N; General_transform xfm; if ( ac != 3 && ac != 4 ) { fprintf( stderr, "usage: %s N transform.xfm [tolerance]\n", av[0] ); return 1; } N = atoi( av[1] ); if ( input_transform_file( av[2], &xfm ) != OK ) { fprintf( stderr, "Failed to load transform '%s'\n", av[2] ); return 2; } if ( ac == 4 ) { tolerance = atof( av[3] ); printf( "Setting tolerance to %f.\n", tolerance ); } while (N-- > 0) { Real x = 500.0 * ( drand48() - 0.5 ); Real y = 500.0 * ( drand48() - 0.5 ); Real z = 500.0 * ( drand48() - 0.5 ); Real tx,ty,tz; Real a,b,c; general_transform_point( &xfm, x,y,z, &tx,&ty,&tz ); /* Check that general_inverse_transform_point() and invert_general_transform() behave sensibly. */ general_inverse_transform_point( &xfm, tx,ty,tz, &a,&b,&c ); assert_equal_point( x,y,z, a,b,c, "general_inverse_transform_point()" ); invert_general_transform( &xfm ); general_transform_point( &xfm, tx,ty,tz, &a,&b,&c ); assert_equal_point( x,y,z, a,b,c, "general_transform_point() / inverted xfm" ); general_inverse_transform_point( &xfm, x,y,z, &a,&b,&c ); assert_equal_point( tx,ty,tz, a,b,c, "general_inverse_transform_point() / inverted xfm" ); } return 0; } minc-2.2.00/volume_io/Testing/check_xfm.sh0000755000265600003100000000034212027132664015342 00000000000000#! /bin/sh # Exit if error. set -e ./test-xfm 10000 $srcdir/t1.xfm ./test-xfm 10000 $srcdir/t2.xfm # Transformation t3 is non-injective, so we have to set the tolerance # fairly large. ./test-xfm 10000 $srcdir/t3.xfm 0.9 minc-2.2.00/volume_io/Testing/t1.xfm0000644000265600003100000000017712027132664014122 00000000000000MNI Transform File % Single linear transformation. Transform_Type = Linear; Linear_Transform = 1 0 0 10 0 1 0 20 0 0 1 30; minc-2.2.00/volume_io/Testing/t2.xfm0000644000265600003100000000032112027132664014112 00000000000000MNI Transform File % Concatenation of two linear transforms. Transform_Type = Linear; Linear_Transform = 1 0 0 10 0 1 0 20 0 0 1 30; Transform_Type = Linear; Linear_Transform = 1 0 0 3 0 1 0 2 0 0 1 1; minc-2.2.00/volume_io/Testing/t3.xfm0000644000265600003100000000043712027132664014123 00000000000000MNI Transform File % Concatenation including a grid transform. Transform_Type = Linear; Linear_Transform = 1 0 0 -87 0 1 0 -45 0 0 1 55; Transform_Type = Grid_Transform; Displacement_Volume = t3_grid_0.mnc; Transform_Type = Linear; Linear_Transform = 1 0 0 63 0 1 0 37 0 0 1 -55; minc-2.2.00/volume_io/Testing/t3_grid_0.mnc0000644000265600003100000124446412027132664015345 00000000000000CDF vector_dimensionzspaceyspacexspaceà  rootvariable varidMINC standard variablevartypegroup________versionMINC Version 1.0parentchildrenimage zspace varidMINC standard variablevartypedimension____versionMINC Version 1.0comments.Z increases from patient inferior to superiorspacing regular__ alignmentcentrestep?ðstart@K€unitsmm spacetype yspace varidMINC standard variablevartypedimension____versionMINC Version 1.0comments/Y increases from patient posterior to anteriorspacing regular__ alignmentcentrestep?ðstartÀb0unitsmm spacetype xspace varidMINC standard variablevartypedimension____versionMINC Version 1.0comments'X increases from patient left to rightspacing regular__ alignmentcentrestep?ðstartÀ[àunitsmm spacetype  image-min varidMINC standard variablevartypevar_attributeversionMINC Version 1.0 _FillValueparentimage $ image-max varidMINC standard variablevartypevar_attributeversionMINC Version 1.0 _FillValue?ðparentimage ,image parent rootvariablevaridMINC standard variablevartypegroup________versionMINC Version 1.0 image-max--->image-max image-min--->image-mincompletetrue_signtype signed__ valid_rangeÀßÿ€@ßÿ€@ 4€ÀI@I  !"##$%&''()**+,,-.//01123445667889::;<<=>>??@@@@@@@@@@@@@@@@@@@@@@@?>=<;:9876543210/.-,+*)('&%$#"!    "#%&()+-/124579;=>@ACEFHIKMNPQSTVWXZ[]^`abdeghjklnoprstvwxz{|}~€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚€~|zxvtrpnljhfdb`^\ZXVTRPNLJHFDA?=;97531/-+)'%#!    "$&')+.02479;=@BEHJMORTWZ\_adfikmpruwy|~€‚„†ˆ‹‘“•—šœž ¢¤¦¨ª¬®°²´¶¸º¼¾¿ÁÂÄÅÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÆÅÄÂÀ¾¼º·´±®«¨¥¢Ÿœ™–“Ї„~{wtqnkgd`]ZWTQNKHEB?<9641/,*(%#!   "$&(+-/2479<?CEHKNQTW[^behlosvz}€„‡‹Ž‘”—›ž¡¤§ª­°³µ¸»¾ÁÄÇÉÌÏÒÕØÚÝàãåèëíðóõøûýÿ                   ýú÷ôðìèäàÜØÔÐÌÈÄÀ¼¸´¯«¦¢™•‘Œ‡ƒ~zvrnjfb^ZVRNJGD@=:741.+(%#!   "$'),/247:=@DGJNRVY]adhlpty}…‰Ž’—›Ÿ£§¬°´¸¼ÀÄÈÌÐÔØÜßâæéíñôøûÿ  "%(,/269<?BEGJLNPRSTTTTTTTTTTTTSRPNKHD@<840+&! þùôïêäßÙÓÍȽ·²¬¦¡›–‘Œ‡‚}xsnid_[WSOKGC?;841-*(%"  !#&(*-036:>ADHLPTX\`ejnrw|€…Š”™ž£¨­³¸½ÂÇÌÑ×Üáæëïôùþ  $)-15:>BFJNSW[_cgkosw{ƒ†‰“•˜šœžžžžžžžžžžœš—”‘‰…€{vqlf`ZTNHB<60*#úóíæßØÒËĽ·±ª¤ž˜’Œ†€zupkfa\WRMIEA<841-*'$!   "%'*-0369=AEIMRV[_dinrx}ƒˆ“˜ž¤ª¯µ»ÁÈÎÔÚàæìòøþ !',27<AEJOTY^chmrw|…Š”™ž£¨¬±¶º¿ÃÇËÏÓ×ÚÞáäæèéêêêêêêêêéèæãàÜØÔÐËÆÀº´®¨¡š“Œ…~voh`YQIA90( øðèàÙÑÊ»´­¦Ÿ˜’‹…ysmga\WRMHC>:62.+'$   !$&(+.148<?CGLPUZ_dioty…‹’˜ž¤«±¸¾ÅËÒÙáèïöý  '.5;BIOU\bhnsy~„Š•›¡¦¬±·¼ÂÇÍÒØÞäéïôùþ #'+.13567888876531.*&! ÿùòëãÛÓËú²©¡˜†}tjaWNE<2)  ûòêáØÐÈÀ¸±©¢š”Œ…~xqke_YTNIE@;62.)&"  !#&(+.158<@EIMRW\aflrx~„Š‘˜Ÿ¦­´»ÂÉÑØàçï÷ÿ (08@HPX_gov}…Œ“𠦬³¹ÀÆÍÓÙàæìòùÿ %,28>DIOUZ`einrvz}€‚„…†‡‡†…„‚€}zvqlf`ZTMF>6.& ÷íäÚÐÆ»±¦œ‘†|qg\RG=2' ÷íäÚÒÉÀ¸°¨Ÿ—ˆzslf`ZTOID>940+'$   !#%'+-148<@EINRW\bhnsz€‡Ž”›£«²»ÂËÒÚâëóû (2;DMV_hqz‚‹“œ¤¬´½ÄÌÓÚáèð÷þ !(/6=DKRY`gov|ƒŠ—¤ª¯´¹¾ÃÇËÎÑÓÕÖ××ÖÕÓÑÎËÈþ¸²«¤•…|sj`VK@5* ýòæÚζªž“‡{ocWL@5*  ÿõëâØÎż³ª¡™‘‰zslf_YSMGA<62-)%!   "$'),/37;?DHMRW\bgmtz‡Ž–¥­µ¾ÆÏØáêòû!*4>IS]gq{…™£­¶ÀÉÒÛäíöþ&.6=EMT\dks{‚Š’š¢ª²¹ÁÈÐ×ßæíóú  #%&'''&$! ÿøðèßÖ̸®£˜Œ€tg[OB5(óæÙ˾±¤—Š}pcWK?3'úïåÛÐÆ½³ª¡˜ˆ€xqjc\UOIC=72-)%   !#&(+.159=BFKPU[`flry€‡Ž–¥®¶¿ÈÑÚäîø )4>IS^iu€‹–¡­¸ÃÍØâí÷ (1:CLT\enw‡˜ ¨±¹ÁÊÒÛäìõþ'/7>ELSZ`ejnqtwxyyyxvspmhc]VNF=4+  ÿôèÛÎÁ³¦˜Š|n`QC4%ùëÜο±£•‡yk^QD7+üðåÚÐÆ¼²¨Ÿ—Ž…|tme^WPJD>72-(#  !$&),/26:?CHMRX]cjpw~…Œ”œ¤¬µ¾ÇÐÚäîù#.9DP[gr~Š—£¯»ÇÔàì÷%0:EPZdnxŠ“œ¦¯¹ÁÊÓÜåî÷ &/9BKU^gpy‚В𡩝µ»¿ÃÇÊÌÍÍÍÌÊÇÄÀ»µ¯§Ÿ–ƒxl`TH<. ôåÖÇ·¨˜ˆxhWG7'÷èØÉºª›Œ~oaTF9,úîãØÍ¸®¤›‘ˆwog_XQKD=71,&!  !$'),037;@EJOTZ`fmsz‰‘™¡©²»ÅÎØãíø$0;GS`ly…’Ÿ¬¹ÇÔáîû".;GS_jvŒ—¢¬¶ÀÊÔÞèòü",6@JT^hr}‡‘œ¦°ºÄÍ×àèñù !"##"  ûòèÞÓÇ»® “…vgWG6&óâÑ¿®œŠyhVE3"ïßξ®žŽpaSE7)öêÞÒǽ²§”Šxph`XQJC=60*$  !#'),037;@EJOU[ahov}„Œ”¥®·ÀÊÕßéô #/;GTan{‰–¤²ÀÎÜëù#1?LZgt𦲾ÊÕàëö !+5@JU_itŠ• «¶ÁÌ×ãîù$.8AJRZagmquxz{{zyvrmhaYQG=1% ýîßп¯žŒzhUC0 ÷äѾ«˜…r_M:(òáϾ­}m^O@2$ üïã×ËÀµª •‹‚yqh_XPIB;4-'!   #&),037;AFKPU[bipw~†Ž—Ÿ¨²»ÅÏÚåðû ,8ER`m{‰—¦´ÃÒâð.=L[iw†”¢¯½Ê×ãðü ,7CNYdoz†‘œ§³¾ÊÖâîú+7CO[gs~ˆ’œ¦¯·¾ÄÊÎÒÔÖÖÕÓÐÌÇÁº²¨ž“‡yl]N>- øæÒ¿«—‚nZE0óÞɵ ŒxdP<)ñÞÌ»©™ˆwgWH9*óçÚη« –Œ‚yog^VOG?81*$  "%(+/37;@FKPV\biqx€‡˜¡ª´¾ÈÒÝéô &3@N[ix†•¤³ÃÓâò#3DTdtƒ“¢±ÀÎÝëù!/;HTamy…‘œ¨´ÀÍÙåñþ $1>KXes€›¨µÂÎÚåðû$*.13331.*$ ÷ëÞÐÁ±¡}kWD/ðÚí—kT>(ûåϹ£ŽxcO:&ÿìÙÆ´¢n]M>/ öéÜÏ÷« •‹wne\TLD<5-'   !$'*.16:?DJPV\bipx€ˆ‘™¢«µ¿ÊÕàìø+9GUcr °ÀÐáñ$5GXiz‹œ­½ÍÝìü (7ESao|‰–£°½ÉÕâïü #0>KXftƒ‘Ÿ­¼ÊØçö,9FR]hqz‡Œ’““‘ŽŠ„}uk`TG9)öã릑{dM6îÖ¾¦Žv^F.þçи¢‹u_J4  ÷ãмª—…sbRB2#÷êÜ϶ªŸ”‰ukbYQI@80)" "&),049>CINU[bipx‡š£¬¶ÀËÖâîú!/=L[jyˆ˜©¹ÊÛíþ!3EWj| ²ÄÕæ÷(8HWfv…“¢¯½ËÙçô*8ESao}Œš©¸ÇÖåõ#3CSbq€ž«¸ÄÎØáèîòõööõñíçßÖÌÀ³¥–…taN9$øàɰ—~dJ1ýãɯ•{bH.üã˳›„mW@*ëÖ¯œ‰wfTD4$÷éÛÎÁ´¨’†|rh_VME<3,%  !$(+/37=BGMSYahov~†˜¢¬¶ÁË×ãïü $2AP_oŸ°ÁÓå÷ .ATgzŽ¡´ÆÙìþ"3DUfv†—§¶ÆÕãò,:HWftƒ‘ ¯¾ÍÜìü ,=N^o€’£´ÅÖç÷".9CKRW[\][XSME;0$öäѽ¨’{dK2þãÈ­‘uY=!éβ–z_D)õÛ©‘yaJ3ñÜdzŸŒygUE4$öèÙ̾²¥™‚xndZQH?7.'  "&)-15:@EKQW^fmu}…Ž—¡«µÀËÖãðü %4CRbr‚“¤µÇÙìÿ%9Mau‰±ÅÙí':L^p‚“¤¶Æ×ç÷'6FUdtƒ“¢²ÁÑàðÿ0@Qbs…—©¼Îáõ.ASctƒ‘¨²¹¿ÄÆÇÆÃ¾·®¤˜‹|kZF2îÕ¼¡†kN2÷Ù»aC%éË®sV:éϵ›‚iQ9" õßʵ ygUD3"ôåÖÈ»®¡•‰~ti_ULC:1)!  !$(+/38=CIOU\cks{ƒŒ•Ÿ©´¿ÊÕâîü %5DTct…—¨ºÌßò.BVk–«ÀÕêÿ(<PcwŠœ¯ÁÓå÷*;K\l}ž®¿Ðàð!1BRct…—©»Îâõ 2H]rˆœ°ÃÖçö%,14541,%öæÔÁ¬–fM2úÝÀ¡‚cD$ãâ‚bB"âã„fI,ôÙ¾£‰oV>%÷áʵ ŒxfSB0 ðáÒĶ©œ„yndYPF=4+"  "%)-16;AGMRY`hpx€‰“œ¦±½ÈÔàíú$4CTdu†˜ª½Ïãö 4I^sŠ ¶Íâø$9OcxŒ¡µÈÛî'9J\n‘£µÇØêü0ARct…—¨¹ËÞñ-BXn…œ³Ëãú&:N_p~Š”£§¨¨¥Ÿ˜Ž‚ueTA,þå˯“uW7÷Ö´’pM+å }[9öÔ³“tU7ýàĨsY@'÷àɳžŠvcP>, ûëÜÍ¿±¤—Šti^SI@6-$  #'+/49>DJPV]emu}†™£®¹ÅÑÞêø#2BScu†˜«¾Ñåù#8Ndz‘¨À×î2I_u‹¡¶Ëàô0DWj|¡´ÈÛî':M_qƒ•§¹ÊÜî&9Mcy§¿Øò %@Ys‹¢¸ÌÞïý   ùêÙdzœ„kP3÷×¶•rO,ã¾™tO*à»–rN*ãÁ _@!åÈ«tY@&õÞDZ›‡r_K9'õåÖǹ«„xmaWLB8/&   %(,16;AGMSZbjrzƒŒ– «¶ÂÎÚçõ 0@Par…—ª¾Ñåú%;Qh–®Æß÷'>Vm…œ²Éßõ 4I^s‡š®ÂÖêÿ)=RfzŽ¡´ÇÚìþ"4GZn‚—­ÅÝö,He‚Ÿ»Øó&=Rdt‚•›ž›•‚ueS?)÷ܾ €_=õЫ„^6çÀ˜pH!úÓ¬†_9ðÌ©‡fE%çɬsX>$ òÚí—‚mYF3!þîßÏÀ±¤–Š}qeZOE;1'  !&*.38=DJPW^fnvˆ’œ§²¾Ê×äñÿ,<M]o•¨¼Ðåú%<Rj‚›³Ìåþ0Iaz’ªÂÚñ4KawŒ¢·Ìàö !8Nd{‘¦¼Ðåù  3EWj|¢·Ìâù+Gc Àà @_}˜²Êßò     ! !    ÷æÓ½¥‹oQ2ï˦Z2 à·b8 㸎d:ç¾–mFùÔ°jH'çÈ«qU:íÕ¾§‘{fS?,÷ç×Ǹªœ‚ui]RG=2(  "'+04:@FLSZbjs{„Ž˜£®¹ÅÒàíú (8HYk}‘¤¸Íâø$;Rjƒœ¶Ïé7Qk„¶Ïè0G^v¤ºÐçý*AYq‰¡¹Ñèÿ+?Tg{ ²ÅØë,E^z—¶×ù?cˆ«Îð  - H ` u † •   ¨ ¬ ­ « ¥ œ o [ C ) îάˆc<ì—l@湋^0Õ¨{O#øÍ¢yP'Ú´kH&åŧ‰lP4ÿçηŸ‰s_K7$ïÞο°¢”†ylaUJ>4*  #(,16<BIOV]fnw€‰“ž©µÀÍÚèõ#3CTgyŒ ´Éßô ":Qj‚œ¶Ñë!<Wr§ÁÛô'@Xpˆ¡¹Ñè.F_x’¬Æàú,D[rˆ±Ä×êü!5J`w¬Éè -Sy¡Êò  B h Œ ­ Ë ç ÿ  % 2 ; A C A ; 1 %   ë Ñ µ – u R - ݳˆ\.Ò£sCá°€Oï¿a3جV,ܵjF#àÀ¡ƒfH,øÞÆ®—€kVB.öåÕŶ§˜Š}pdXL@5+   $)-28>DKRYair{„Ž™¤¯»ÈÔâðþ -=Oas†š¯ÄÚð6Og€šµÐë#?[w’®Éäþ3Mg€™²Ìåþ.G`z•°Ìè <Wr‹¤¼Óèý#5GYl€”ªÂÜù9^„®Ø  2 ` Ž º å  4 W w “ ª ¾ Î Ù à â à Ú Ñ Ã ² „ h J )  Þ ¶ Œ _ 2 Ò¡o< Ö£o;Òžk7Ò o?ಅY.Û³ŒfAûÙ¹™z\?#îÔ»£Œv`K7#þìÛË»¬ŽtgZNB7,! !%*.4:@GMT\dmv‰“ž©µÁÎÜé÷&7HZm€”¨¾Ôê1Jd}˜²Îé"@\z–³Ïë#>YsލÂÜö*D]w’¯Ìé&Db€žºÕð  6K^q‚”¥·Êßõ (FfŠ²Ü 9 k ž Ò  9 j ˜ Ä ì  0 L c t ‰ ‹ … { l Y B ( é Ä s G  é · „ P ä­v>Ï—_'ð¹‚Lá­yGä´†X,Ö­…^9òЯpR5ýãɰ˜kU@,óâÑÀ°¡’„wj]PD8-" "&+05<CIOW_gpyƒ˜£¯ºÇÕãñÿ/ARexŒ¡¶Ìãú*C]x“¯Êæ >\z˜µÓð *Fb~™´Ïê ;VqŒ¨Åã#Dd…¦Çæ">Xp‡›®ÀÑáò)?Xs’µÛ  4 g Õ  J … ¿ ÷ , ^ Œ µ Ú ù  ' 6 ? C B < 1 ! ô × ¶ ‘ j ?  â ° { E Ô š _ $è¬o3ö»D Ï•[#ëµJ䳃T&úϤ|U/ çÄ£ƒdE( ðÖ¼£Œt^H3 ùçÖŵ¥–ˆzl_RF:.# #',17>EKRYbkt}‡‘œ¨´ÀÍÛéø(8J]pƒ˜­ÄÚò #<VpŒ¨Åáÿ;Yx—¶Õó/Li†£¿Úö-IeºÙø;^¥Èì2Sr«ÄÚï"1@PatŠ¢¾Þ  , [ Ž Ç  D † É N Ž Ë  7 g ´ Ñ è ù    õ ä Í ² ’ m E  ë ¹ … O  Û ž a " â ¡ ` Ýœ[Ú›\à£g,ò¹Já®}LðÄ™pH"ýÚ·–uU7þãÈ®–~gQ;&ÿíÛʹ©š‹}oaTG;/$ #(-39@GMT\enw‹•¡­¹ÆÓáðÿ0ATgz¤ºÑè3Mh„ ½Ûø5Ut”´Ôó1PnŒªÇã9UrެÉè +Os™Àç5[€¤Åä1EWftŽœ¬¾Óì  * Q  ² ë + o ¸  P é 2 w ¸ ó ( W    » Î Ú à ß Ø Ê ·  [ 3  Ö £ l 3 ÷ ¹ z 8 õ ± k % ß ˜ R Ä~9õ²o-ì¬n0ó¸FÚ¥sAã¶‹a9îʨ†eF( ïÓ¹Ÿ‡oXB-òàν­Ž€qcVI<0$ $).4;AIOW_hqz„Ž™¥±¾ËÙçö'8J]q…š°ÇÞö)C^z—´Òð/No°Ñò2Qp®Íë%B_|™·Öõ9^…­Ö+VªÓù>[uŒŸ¯¼ÈÒÝé÷   5 S w ¡ Ó L ” á 4 Š ã ; ’ æ 5 ~ Á ü0]‚ŸµÃÉÈÀ±›~\5 × ¡ h , í « g ! Ú ‘ H ý ± e  Ë  3çS Ã}8ô±p0ñ´x>Ï™e3Ó¦zP(ݹ–tT5úÞéw_I3 ÷äÒÁ±¡‘‚seXK>1%  %*/5<CKRYajt}‡’ž©µÃÐßíü .@Sfz¥¼Óë8SoŒªÈæ%Fgˆ©Ëí0Qq‘°Ðï,Ig„¢ÀÞþ Dj’¼çCr¡Ðþ*Sy›ºÔêû    " + 4 @ P e ~ Ä ò * j ³  ] ¼  … ë O ®Z¤æ Py™±ÀÇÅ»ª‘qKí¶{< ú ´ l ! Õ ‡ 7 ç – D ñ Ÿ L ù § U ¶gφ>÷±m*ê«m2øÀ‰U"ðÁ“g=ïʦƒaA"ç̱—~fO9$ûèÖÅ´¤”„ugYL?2& !&+17>ELT[dmv€‹–¢­ºÇÕäó#5H[o„™°Çßø,Gc€ž¼Ûû;]¡Äæ ,No±Òò1OmЍÆä&KqšÅó#T‡»ð$V‡³Ûÿ  7 J Y b h m p u | ‡ — « Ç é  G … Í ! ~ ä R Å < ±#ôP¢ê(]ˆ«ÅÕÜÙκyMã¦eÖ‰: è ” ? è 7 ß † , Ó y ! É r Èu$Õ‰>ô«e Þ^!ç­vA ܬ~R(Úµ‘oM-ñÔ¹Ÿ†mV?)íÚÈ·¦–†wi[N@3' !&,28?FNV^fpyƒŽ™¥²¾ÌÚéø*<Ocx£ºÒë:Vr¯Ïï0Qt—ºÝ%HkޝÑó4Sq­Êé *NužÊù+`˜Ñ E·ê  D g … ® ¹ ½ ¾ ¼ º º ¿ Ê Û ò  7 g ¡ ç : ™  { û ‚ ”e¾ M†´Øó úâÁ—f-í©`Ám¼` ¤ D ã ƒ " Á a   B ä ˆ -Ô}(Ö†8ë XÍ‹K Ñ—_*öÄ•g;éÞ{X7ùÜÀ¥‹s[D-ðÝ˺©˜ˆyj\OA4( "'-39AHPW`ir|†‘©µÃÐÞíý1CWk€–­ÄÝö+Hd‚ Àá#Eg‹¯Ó÷@e‰¬Ïò5Uu“±Ïí -PužËú.f¡ß a¢ã Y Š µ × ó       ü ø û   : ^ ‹   U ³ œ ' ½\ýš/¸3ŸþO•Ïþ$@QXSC'Ï–U Àn¾až:Ôl š 1 Ç ^ ö Ž ' À \ ø — 7Ù~&Ð},ÝFþ¸t3õ¸~EÜ«{M"øÐª…bA ãÇ«‘x`H2ôàͼ«šŠzk]OB5( #(.4;BIQYbku~‰” ¬¹ÇÕãò%7J^rˆž¶Îç8Us‘±Ñò6Y}¡Æì7\¦Êî5Vw—¶Ôò0QuœÇ÷,f¤æ-vÀ S — Ô  1 P f u } | q ^ F 2 ' , ? ^ † ´ é ) v Ò > » K î¡]Îv ‘fº;k‘®ÁÈ®Œ]$á–Dí‘1Îgý‘#³BÐ] ê w  “ " ³ E Ø m  ž 9ØyÃnÉ{/åžZØ›a)ó¿Ž^1ݵlJ(êͰ•|dL5 öâϽ¬›‹{l^PC5) #).5<CKS[dmwŒ—£¯½ÊÙè÷*=Pdy¦¾×ñ (Eb Àâ&Jn“¸Þ+QwÃé3Vyš»Úù5UvšÃñ%_Ÿå1Õ *  Ò c ˜ ¼ Ò Þ å è ã Î ª } W E N p ¢ Ü  Y ¤ û e â tܵ—r=õ—!•ùN”Îþ&E[bY@ÞšKó•3Ìaò •¢&©+®1 ´ 9 ¾ E Ï Z ç w  4Îk °X°`È€;ø¹|A Ó n@è¿™tQ/ïÒµšgO8! ÷äѾ­œŒ|n_QC6) $)/5=ELT]foyƒŽš¦³ÀÎÝìû /BVk€—®Çáû3Qp¯Ðò9^ƒ©ÏöEl“ºâ /UzžÁâ!?\{œÀêS“Û,‚Þ > ¡  f À C ^ ` W P Q Q 9 ü ¨ a D Z ˜ í E • ã 9 Ÿ  ¸c(ö5+¯aßP³O‰»è)0#̇4Õo“¨.±1®)¢‘~öo è c à ` â g î w  ” '½Wõ—=å‘?ñ¥]Õ–Xæ±~MóÉ¡{X5ôÖ¹‚iQ:# ùåÒ¿­Œ}n`RD6) $*/6>FMV^hq{†‘©¶ÃÒáð"4H\q‡ž¶Ðê!?]}¾à'Lr™Àç7`ˆ±Ù*Rz¡Æê .Mj‡¤ÄèEÈuÙ D ³ & ›  } Û  ! ý Ç £ ¤ Ð Ô q à ,  ; ® L Ü 0 u î u ÿ @]Ž-_¹¸LÄ0© Rx¤ã@C)ö²\õ‚ Ž „úmÝK¶ ‰ó\Ç4¢ ƒ ø p ë i ê o ö ‚ ¥<ØwÂlË7ñ¯o2øÁŒZ*ýѨ‚]:øÚ¼ …kR;$úæÓÀ®}o`RD6)  %*07?GNW`is}ˆ“Ÿ«¸ÆÕäô':MbwŽ¥¾Øó,JjŠ«Íñ:`‡¯×)R|¦Ðú$Nx¢Ëò>`¸Óñ;n­úWÁ 5 ¯ 1 º E Ì O à 6 0 °  Æ Ò + ‹ ô ž å ž  ™ € ª ë ô àËânko2éš^"¸7¶‡„k¤t²´k&Í_ÜO¿1¥‰ö`Å'…à:”îI¦eÈ. ˜  t é a Ý ] à hô„³Pó™Cð U Ç…F Йf4Ø®‡b>ûܾ¢†lS<%úæÓÁ®~o`RD6)  %+18@HOXajt‰•¡®»É×ç÷,?Sg}”¬Åàû6Uv—ºÝ'NuÆðDošÅðHt¡Íú%Ow›»Ùó $Af•Ó$‹   ­ O ÿ — + Â< V 8 { É D ] ¼ · Ì Á  ¤ ¢ ´ ŸWU£¤¨^”K'Bµupx‚™ SF¯®4þž1“ê,‡íU½#…ã;ŒÙ"j²ûE’á3‰â? Ÿ  n Ý O Å @ À EÎ\ï‡$ÆkÁr&Þ™XÞ¥p= Þ³‹eAýÝ¿£‡mS<%úæÓÀ®}n`RD6) !&,29@IPYblv€‹—£°½ËÚéú 0CWlƒš³Ìç"@a‚¥Èí:b‹´Þ 5`¹æAožÎþ/_Žºã#<Pcw’¹ð<¨ J ï ¡ * ¬ S qQÈ´ ° D Y G   ê  Å i  – F ¿ æHŠio¯W;¡Q»à=7mm;¹(ǀРŒ!!ˆ!h! xçÜþN¹yØ3‡ÑI}±äQ‹Ê RžíA š ø [ Ä 1 £  —  ,¾Uò“7áŽ?ô¬h(ê°yDã·ŽgBýÝ¿£‡lS;%úæÒ¿®œŒ|n_QC6) !&,3:AIQZcmw‚™¥²¿ÍÜìý!4G\qˆ ¹Ôï +Kl޲×ý%Mv¡Ìø$Q­Û 9išÍ6m¤Ú ;c‚š«´ºÅÛÿ9™ J U Ó † ² š ) ê »a¢ ò ² ¢  i u q 9 å ¼ å P ÷ ç$zÀ«Ào!oÇ-~…Ÿ¼ïñ´NÍ ] ñ!\!M"R"Ô"¡"”" !´ º·3¦úX­V“º×ñ,Ln”¿ð'b¤ê6 ‡ Þ ; Ÿ  v ë eäjõ†¹Zÿ©W¾x5õºKçºhCýݾ¡…kR:# øäѾ­›‹{l^PC5) !'-3;BJR[dnyƒŽ›§´ÂÐßïÿ$7K`v¦ÀÛ÷5Ux›Àæ7aŒ¸äApŸÏÿ0b•Ê:v´ô3q¨×û&%þ =Ò « ; Î ß ½ D  è ») ¹ ª ¿ E  E ¤ T   : º z ¢7èûö´“dâÒ·ø  ? É!J!æ"s"©"Ù#*#y#¹#h#V#"q!¬!, € Lž]”Ž{zˆ‘œ«Âà0aš× f ·  n Ô ? ± )¨,·HÞ{ÂmÎ…@ÿÁ‡O꼑hBûÛ¼ŸƒiP8! öâϽ«šŠzk]OB5( "'-4<CKS\eoz„œ©¶ÄÒáñ';Od{’«Æâÿ>`ƒ¨ÎöIu¢Ïþ._Âô'[‘Ç=|¿Qè-h“°ÑØ•K/‘×5‰ Y   p o 7 Ç 2 > é N ©  £ Ž Õ = 8 ü | Ì šçöÛÙ…èL5ÛGÞð¼-# Ÿ" "Á"ã#·$o$E$X$€$»$½$º$#å$#y"À"J!Ì!G —Ü–Q(úéÙÏÐÚí'O´ ñ 6 ‚ Ö 2 • þ nåcçr›8Ú-Ý’JÈ‹Së¼f@øØ¹›eL5óàÍ»ª™ˆyj\NA4( "'.5<DLT]fp{†‘«¸ÆÔãó)=Rh—±Ìé&HkµÝ0]йéL³çS‹Å?Èe¼uÌ  P c u … oò oP” b 3 Î i 9 ð : ¨ J æ b À p  Ÿ # ¾   ³ ž )ZQxCv»ÿ¹v혜pŒ!4"Ã#Î$¢%`%»%é%²&E&q&=&:&%à%”%<$°$(#q"ï"U!Æ!* .!Ö¯˜„W!þéàßæõ +R ¸ ø @ ‘ ë K ³ #™›'¹Rð”=êœS ÌŽTëºc<ôÔ´—{aH1ðÝʹ¨—†whZM@3' "(.5=EMU^gq|‡’Ÿ¬¹ÈÖåõ,@Ulƒœ¶Òï/Qu›ÂëBp Ñ7l¢ÙK†ÂB‡ÐsÐ5¢  † Û - ]  Ï€b } × œ Ë S  Ù ƒ  ¨ x ¿ ä … G « ÷ 8Šd  ; w  ´ Ë > l QAº¶ÿ!?¸ÀžÒV3Á!"ú#Ý%j&K&½''«'Ç'è(0'é'ð'ß'¦'B&¶%ì%$U#Á#"m!¾ ©ˆ'Ér4ñÛÎÊÏÝô> p ¬ ò A ˜ ø _ÎEÄIÖj¥Jõ¤YÎTè·Š_7ïί‘v\C,ìÙǶ¥”„ufYL?2& "(.5=EMU^hr}ˆ“ ­»ÉØç÷.CXo‡¡¼Øö7Z€§Ïú&T…¶êVŽÈ@¿GÛ,‚ßE¸ 7 Ä w ï  € ™ ,ù8¸ m 9 ¼ M t È ƒ  I F o î r  N ¾7?É´à>´Þ g û ð S ˜ ÷j0nÈ«uçû¤M? Ü"§$%`&k'0'ß(s(ý)z)})š)Í*)¤)U(»'‹&{%‡$Å$#<"œ!© vzIXµ‚M༤˜•›«Æ ë  S — å < › sêjñ´Vþ«]ÏŽR䳄Y1 èǨ‹pV=&úçÔ²¡‘‚rdWJ=1% "(/6>EMV_is~‰”¡®¼ÊÙéù 0E[r‹¥ÀÝü?dŠ²Ü 7gšÎ=w³ñ2u¹J—è<•óXÅ . × x M @ H h P v L ? Ó { Ï ” £ @ C “ Ù · ß Ü ¯pN  ÞS÷qàî!éÙq E V ä è „Ô©àiXóÿ¥o ¦"º$,%4&ˆ'ª(s)%)ì*)*£*ß+,+#+c*Ï)­(Ê'ƒ&k%•$Ü$%#H"Z!O GNçÑû¡@ë­„gSHFPf ˆ ´ ì 0 ~ Õ 5ž‰ •'À_®^Í‹NÞ¬}Q(ß¾ ƒhN6 õáϽ­ŽpbTH<0$ "(/6>FNV`jtŠ•¢¯½ÌÛëû 2G^uŽ©Åã$Gm”¾êHz¯ç [™Úe¯ûKóM« rØ > °  s É N ÿ Ô ¦ =  Ï ® Z µ w ì ¯ È ‹  ! î °3„@È,Z…Ælºþö¬É[ Ï t Æ ‹ ø•#Iš,(ϲ¼œŽ! # $f%s&´'Â(ì)”**˜*æ+m+4+O+š+)Ú(¼'æ&Ø&@%Â%$)#)"! ýÎË!Jýlçœj<ùåÝã ö  B z ¿ eÇ2¦"§4Ée°]ɆG Ö£sGøÕ´–z_F.îÛʸ¨™Š{m_RE:.# "(/6>FNW`ju‹–£°¾ÍÜìý!4I`x’­Éè+OužÉö&YŽÅ<{¾OîDú[À(“ý [ « î Æ G  Ó ê þ  « N ) | ' A k Z ¦ 4 © F º ^yõ5£žù[o;[ý)øÙ. J Ó  ½ß¿ïðXPí!/#@$’%¸&Å((ñ){)Â*e*ô+'*÷*½*¹*M)>(D'H&Ö&›&L%Þ%8#ù"Ø!Æ ¯¢Ä-ïNÏ“Sஆl`c v • à ý C “íRÀ7·?Ði ¯Z Â~>˘h<íÉ©‹oU<%ûçÕò¢“…wi\OC8-" "(/6>FOWaku€‹—¤±¿ÎÞîþ"6Kb{•°Íì 1V~¨Ô5j¡ÜYœå1‚Ø3”ùcÐ?° & ™ ò  V Æ } 9 ¾  ! † ù Ë Ø 7 ˆ r  Ì d 3 ¾ ^ ± þÅJ¹âD=Ýcnƒú™R3‚r „ « ŧˆu È7Àxrþ {#&$>%t&˜'Ë(ù)I)…* *Î*Æ*w*)™)t('|&ñ&“&o&¬&|%«$Ó#¢"W!K R… œg$õ²>ý¯d'úÝÐ Ó æ  8 u ½ nÖHÃGÔjªT¹s3ö¿‹[/ß¼œ~cI2òßͽ¬œreXL@5+! "(/6?GOXbku€Œ˜¥²ÀÏßï$8Md}—³Ññ6\…°ÞCzµò3v¿ _¸}ê^ÖQÐ C ½ 2 z ƒ Ê o ñ ‹ á ÿ B ¶] ‚ Ù ^ ž 1 Õ ¶ j ×  j ½ên‹•ïtмø^ü¶‚YSPji t x ˜ æl,ä±t9ñ¦ q"#…$™%ß'P(.(Ü))È*c*o)ë)˜)ˆ),(O'%&ª&‡&ˆ&°&«&%$0"ó!Õ! C<,üïÿêqðt ¾ƒW:- 3 I o £ ã 0‡êVÍLÕg£Kù­f%è°|LöЮŽpU<%ûèÖŵ¥–‡zl`TI>3) "(/7?GOXblvŒ˜¥³ÁÐàð%9Ne~™¶Ôô;bŒ¸èQ‹ÈL•â5ŽîUÇFÍUÝ c Ø ) ž ¼ Ú h   9 |  8 ü  Ñ º ; ¨ ¶ .  O ` Q \ Ørò¤aB8„ó‰H;hÒo.þÖ²š„| { ‘ Ð EöÛÚØÊ¹£…Jç!Q"ˆ#¦$Î%ñ&ù'­(^);)…)Ñ)|)p)Z)q(d'&&ž&_&&š&‹%ô%$=#Ÿ"¶" ! =÷µ‡‰]«ýŽCÊ y „ ¡ Ì  JœùaÒNÓbù™?ìžWןj:å¿~aG.ïÝÌ»¬€sg[PE:0&  "(/7?GOYblv™¦³ÂÑáñ':Ofš·Ö÷?g‘¿ð%^šÚf´_½"‘ ™Fâ k æ 7 O Ù 7 Y ü Í ±1+ ‡ & ä º 1 Á | @ Ÿ © ,×  Ô·á› Ø<ÿÍÿŒÿ}ÿ®&ཧ‰b7òÞà ² Á  µ¾ÿ27YI˜ Ô!Ñ"´#Ÿ$›%Œ&_'%'½(9(|)(Õ(ÿ(Ö(q'm&w&\&Y&†&b%Ñ$Æ$'#Ñ#ˆ"ˆ!µ ÆÃ;÷Ò²VÚEýÃ6øÌ · ¸ Ë î `¬gÔLÎYî‹0ÛDÄ‹V&úÒ¬‹lP7 õãÑÁ±¢”†ymaVKA7-$  #)/7?GPYblw‚™¦´ÃÒâò(;Pg€›¸×ùBj–Åø.i¨ì4Ó+ˆìVÇEÛ„ _ ¶ f Ë  g ß t ‰6A ž   I  È Ž ‡ •ÃY¨°¾½ÂÅÿõÿRþâþ£þþœÿJQЇyM Ì–xlÜ ° ¿ 3@ÿTFW1µ ¾!P!Ê"~#j$q%A%ë&o&Ò'2'z'½'Ô( (5'n&Ö&Š&£&~&H%°$Ì$#Å#ˆ"æ!© ¯¾¡\ §Hã¡nAøF ê â ì 5 o· iÒFÅMÞyÇx/ë­t@ä¼—vX=%úæÕÄ´¥—‰}qfZPF<3*!  #)07?GPYcmw‚Žš§µÃÓâó)<Qhœ¹ØùCm™Éý6sµüI›òP³‰úu÷œú ‰  µ µ . ~ . ¯¥Í  É Ö í å { Ê 0 ° Ê™ªÙHv›°¸·ÿ¾þáþ5ýÉý•ý†ýqþ2>¶µn¤{(¬)Ã ç ¤ ¡º†°:&9à ˆ û!!t"Ó#Ó$¦% %‡%Î&&3&]&‹&Æ&å'M'&€&ž&¨&%[$¿$#€# "7!] ˜‘ÕÁ-­CèĤ]Ýy5 ÿ   B x¼ fÌ=¸=Ìd°`Ò”\'øÌ¥`C)üèÖŵ¦˜‹sh^TJ@7/&  #)07?GPYcmxƒŽ›¨µÄÓãó)=Ri‚ºØúDmšË:z¿ \´ußMÀ,’D® n >  ë £ a † Ò^‚  ž “ W T  ¡ u © " †¥¡œ¼ì(h£ÅÆÿ­þ—ý“üÛü‚üuü‰üæþÿÿÿcvã –Bò ã  i 2æˆæEÇà ý!©"€$$t$×%%$%%%$%0%G%g%ª%â%ö&&@&‚&B%<$¤#ì#<"ˆ!n ° I¾Âfª1øÙã³Jï‘N(   # G {»_Á.¦)µLì•Dú¶x@ ݲ‹hH,üèÕÄ´¥˜‹si^ULC:2*#  #)07@HPZdnxƒ›¨¶ÅÔãô*>Sjƒ¹ØùBl™Ë<~ÆlÊ0› ƒ÷h¬xº † ¢ ô  òSmËÖi E   n C ù 7 Ù ¶ 3 b‹™•”¦Ö#ƒà%þºý]üRûSûûtûzü?þ„hRah6¥ï:ú Ó ä Â-–9Æ->ì T ®!Ž"ª$ $÷%M%;$è$|$>$$ $=$f$$½$ÿ%s&,&%$m#Ý#:!á ¨÷ÛjÀV’˵¡q,ëšbD (  " E wµÿS²‘›0Îv%Û—Y!îÀ•oM.ûåÒÁ±¢”‡|qf]TLC;4-&   #)08@HQZdnxƒœ©·ÅÔäô+>Sj‚œ¸Öö?h•Çþ:}ÇvÝLÃ?¼=’ pö $ ¨  E Ð-©YU}ÿY J Ù ¨  \ ¢ 3 ¤ËÉ·œ‡Ç8ØyäÿâýÐücûXúéúLúAúÞûÙþ4l—m,ŒŠÉø³µ¿ Æ ý ³ ùrôÞg‚µJ«‰  A"²$h%m%Þ%¢$Ê$#~###3#f#’#½#ù$\$­$Â$]#ç#°"¨!³ Z MWŠã¥žƒF»p[   : lªòDŸxõ}­S¹u8Í vQ0øáÍ»«œ‚wmcYQIB:3-'!  #)08@HQZdny„œ©·ÅÔäõ+>Siš¶Óò:bÀö3vÂyçcëxv,©÷ I ´ — Ó … «uä¼W›9 à  ¯ A \ ™ è &7!í¨l^«ps‡'ÿÝý¢ûºû¨ûsûú|úÈûåýæ* á<à[°²  Ž ƒ N $ *È’‘®vGÌ\|Úè!#^$)$R$…#ò#0"i!°!æ"V"§"Á"â##%#8#)"ù"È""€!˜ ¾O£„1`ûZͲ¾ƒ0ä’D' å ë  & [œâ1ˆëZÕ[í‰.Ý“Pܪ}U1ôÛŲ¢“†zoe\SLD=61+&!  $*08@HQZdny…‘ª¸ÆÕåö+>Sh˜²Ïí2Y…´ê%h´ oänÅVÆñWˆã 7 • 2 È ‰ P’kÅ  Õ º  æ X Ö B † ¿ÙË”5·- ÎwÆ™7þDü™üUüáûôúÍú¶ûºýzÿ…f<'Ì£§Óƒ Ž v % “ ( ÷[QËî·Ì v7ï&† P!-!ì!z!( „â» Œ!Ÿ!é""+"3","!ò!Å!‘!o!G!X m5¯S®¦v¼¤Äq"Çg$ì e • Ú Þ  JÑnÌ8±6Æ`³j'뵄Y2ðÕ½¨–‡zodZRJC=71+'"  $*18@IQ[eoz…‘ž«¸ÇÖæö+?Rg~•¯Êç)Nw¥ØQšðTÍ^ö»Ã¶ôbà H › û 9  Q ‡9a • þ P f ± ò . “ Àº‹6¨Üÿfÿj†xÛÒŽÿFý½ý ü­ûÖúßúû_üÕþ{_”™"§Ò d ¹ ª ø "  Ï ¹W¶)DŠ}S¹v#ÎGm2ï|¼Ñ 72-($  $*18AIR[eoz†’ž«¹ÇÖæ÷,>Rf|’ªÄàý@f¿ó/sÄ%›8éÍO\M†­ – × ã ¤ » e ° n » ï & Í B ‚ ¥ Ž R ï è~‘~IþÖþvÿâéŽX‰ÿaþ5ý0ü^ûvú©úvûüQýÀÿ@PÍk{™} C  þ ¤  ¶ c«ÿ•ÑæÓÆ&8+Q~v2ÊéHäÚ™ i Ö!! Û ] ½’i7ñœdqû—$òÿ|ï9묙“!à Ÿ ¦ Ü º ÿ N¯æ-ƒé]Þl©W Í“_0ãè{iZNE<5.)#   $*19AIR[epz†’Ÿ¬¹È×ç÷+>Qey¦¾×ò.PužÌ>†àhò·‹£½úH+Ü &  @ ã Ì  ã ¦ £ 9 Ÿ  h š ¤ v  ¡¤‡ŒÄyÿ‹ÿªÊ·ê‚dÿ]þ6ý$üDûXúIú2úìüý’þàÿ‰©u % ` qQ Á  Ø ì pfŽÕµ†p„/!÷Ry ¬tê<#wD`Æx # Ý ;ꢛdË™y@ð|z3p‹ð³mgY%å Ö ì .  H z—ÀX»-­:Óv$Ûšb/Û¸š€jWG:0(!  $*19AIR\fp{†“Ÿ¬ºÈ×çø +=Pcw‹¡·Îåþ4SvÉû7…ú¼àhÓç[¯Ñ#s*Å Å û Ó U Æ  ˜  o Ð Ñ x à ‡7ƒÿpóŠªHÕlÖ»rÿXþ/üêûÿû;úSúQú¹üeþÿkl|à µ ß m î o 2 êþœžNŒôJÙ{X+~Dê_6w*æÉºàTRÚ#ƒòø¶Wô˜MÆþ h•x™\s@ë  G t ž ½‚`Ó'ŠûyAî¥e.ýѬ‹oWB1# ÿýÿüÿúÿùÿøÿøÿøÿùÿùÿúÿúÿûÿüÿýÿþÿÿÿÿ %+29BJS\gq{‡“ ­»ÉØèø +=Oat‡›®ÂÖêÿ,Fe‡®ÞbÓ·ñS`"l¬ÎQü É ,ÐÆ l ô y  • 5  ë±%¨©ïeW@Óqÿ+þüÍûUúøúÀûû´ý9þº‹NGÁì ^ D Î ê îÀáבi |çˆKñQvòÑ!­-¥G2AkêÁXí=î4Àš1®$¢•¯ŒÀEíÜÔë>k ˆ ³ ¡ ·U¡ôVÅBÍdµm.÷Èžz[A+ ÿþÿõÿïÿêÿçÿåÿäÿäÿäÿäÿåÿçÿéÿêÿìÿîÿðÿòÿôÿöÿùÿûÿýÿþ %+2:BJS]gq|‡”¡®»ÊÙéù ,=N`rƒ”¥µÄÓâðÿ#;Z…·¾èS›ò0áÉ͇Dgô!Gž  § ` »  í Ê êë(`§4ªŸÁLAŽ•ÿýòü&û^ûûMûhü¿ýçÿt–õoqi … Ò Í À ¦ S è ¿-êß>ÉâC¼õô†œ×gX%Vq˜›®—#ÚÅæq\Ðcº‰ç™‰Ú³vA¨ÞX» x d j w T à1n¾  ’(Ëy2ó¾hF*ÿýÿíÿáÿ×ÿÐÿÌÿÊÿÉÿÉÿÊÿÌÿÎÿÐÿÒÿÕÿØÿÜÿßÿãÿæÿéÿìÿðÿóÿ÷ÿúÿýÿÿ %+2:BJS]gq|ˆ”¡®¼ËÚêú ,=N_o~š§²»ÃÉÎÒ×âý,m¿µÀ·FïÐWШf4|ÝL®Ÿ C &  g Š Œ è÷eâCù§‹¡­#ze 0Gÿ.ý$ûÖûFûiûŽü¡ý ÿÿá™V| - K ¸ ˆ K e ( Æ(|´ƒöTÅ,¥ïŸ>Z:#’fd)ÜÛ•(âŒ9.~·]‡¬á%€»››pñ y¢â.y ( ( $   +‰éSÌTéŒ;ô¶U0ÿõÿßÿÎÿÀÿ¶ÿ®ÿªÿ¨ÿ¨ÿªÿ¬ÿ¯ÿ²ÿ¶ÿºÿ¾ÿÂÿÇÿÌÿÑÿ×ÿÛÿàÿäÿéÿîÿòÿ÷ÿûÿþ %+2:BJS]gr}ˆ•¢¯½ËÛêû ,=M\kx…˜ž¢£ ™Ž€z‡ÆvÊ¡Œ‰3Sígsö}…º ” ‰ ²  f Õ]©×Ë‹UFLÓb·5®Éÿ’ý£ü7ü ü ü&ýYþŽÿoºÂž‹ Ÿ P ƒ ¯ œ 9 q º ± k  %.y s7Á° ypX7˜lOZÎ/48ŸÐ]5:© qÀé.nÎS¢'£š}é.1rê à   ÷ ¿oþºý]®‹¨Jù³vCÿõÿ×ÿ¿ÿ«ÿœÿ‘ÿ‰ÿ„ÿ‚ÿƒÿ…ÿ‰ÿŽÿ“ÿ˜ÿžÿ¤ÿ©ÿ°ÿ¶ÿ½ÿÄÿÊÿÐÿÖÿÜÿâÿèÿîÿôÿùÿý %+3:CKT]hr}‰•¢°½ÌÛëü -=LZgs}„‰‹‰ƒvcG$õì‘bUëOV‹ã4Š®Ø[Þ "½Tç{¯ ) Á º œ ê0À[ݾßWô<Ä¥÷ ÿwþýîýzþþæÿƘ½gW9é @  Õ ¤ † ó Í á › ' Ò ” GÞ£ËlÃ$JUéqêã¸D‡H‡¢²L®xD(U(.-N†áWß‚0IÇÞƒíK g ¾  ¿ v|–¬‹à$jÌFÎc´o4ÿØÿ·ÿœÿ†ÿuÿiÿ`ÿ[ÿYÿYÿ\ÿaÿhÿoÿvÿ}ÿ…ÿŒÿ”ÿœÿ¥ÿ­ÿµÿ½ÿÅÿÍÿÔÿÛÿâÿéÿñÿ÷ÿü %,3;CKT^hr}‰–£°¾ÍÜìü -<JWcmuz{yrdN0É~(eŽ m-ÿÀÿ†ÿaÿ4ÿÒõàÍ$§[­JàhƇ 3 À › dòrÿ T û†§ @ÛÑq¦ÉQªš%‰ãI  Z C 2 þ © ~ ð È ø   • ûÝòÔvÜ^dœàjRªj¤wÅDŽs3#½W¨ŒQšû2+"(^±#º„Ìog& ê j  G ¡ V hi=å?¡Ô~ý‡¿n)ÿïÿ¿ÿ—ÿwÿ_ÿLÿ>ÿ4ÿ.ÿ,ÿ,ÿ/ÿ5ÿ=ÿEÿOÿXÿbÿkÿuÿÿ‰ÿ“ÿÿ¦ÿ°ÿºÿÃÿËÿÔÿÜÿåÿíÿõÿû %,3;CKT^hr~Š–¤±¿ÎÝíý -;IT_gmpnh[G*Ï(ÿñÿñÿüÿ³ÿGþ¿þ]þ‹þOþ„ÿ"ÿÒÿÁÿ¢Î{2ÞY¹SÌ/ue $ ’ ì ô “ {3èrÇ)Ô  ºáÓÀ.ˆ­Q @ÒÒÄ ž î “ ß à þ l 8 ? > * ÿ Ÿ)˜”‘šv"ðb÷¸ {+ú Ct„Ô6Á8´ V¯éè‹ ÄÅúÙ½¦ÅùHÅŒ¯CØ© Q ¦ F Á Ê E ul ²,ž.µ?Ôv&ÿáÿ©ÿzÿTÿ6ÿ ÿÿþýþúþûþþÿÿ ÿÿ"ÿ-ÿ:ÿEÿQÿ]ÿiÿuÿÿŒÿ—ÿ¢ÿ®ÿ¸ÿÃÿÍÿÖÿàÿêÿòÿú %,3;CKT^hs~Š—¤²ÀÏÞîþ-:GR[bffbXF, Ü¥i<ÿéÿÚÿòÿ¹ÿ4þ_ý˜ý«ýüÃýZýLýxý7ýæÿM{Iæ³€4ÜsªwÞ » V “ ‹ Ÿ N /ì>Cn ` § >âD¤gbUqìÍ v e2 „ { 6 w þ 9 à Ô Ð³Ú°Èk†Õnbßßl¦¦ÕrV/ÛY­¥ F ¸JKµK¹ê/Hfýô32 ‚ ) d Ù3P ) 3 O Ñ Œ G Í ÒïòPðmôˆ,ÿÜÿ˜ÿ`ÿ3ÿþòþÞþÑþÉþÅþÅþÉþÏþØþãþðþþÿ ÿÿ)ÿ7ÿEÿSÿaÿnÿ|ÿ‰ÿ•ÿ¢ÿ®ÿºÿÅÿÐÿÛÿæÿðÿø %,3;CLU^is‹—¥³ÁÐßîþ,9EOW]_^WI3뺂QÿùÿÃÿ«ÿ¿þ›ý]ü™üMüû½ü üû²ûïü´þ\ÿ Œb5 ôúÃ%˜z B  Õ „ ü ”  Û ? ZÃj # NÒ—‰ydäƒÀ*Šø ” N 3€ ” C .  ¾  ² ’ — ÉçF i LþÛœýì`/ìLîôˆ\5äq&èx = g Ë š ‡ ¹ ù@P¯4èI x e é Å · F l È6   à Q O B Úñžœ®=²%¡:ÿßÿÿMÿþéþÇþ­þ›þ‘þŒþ‹þþ•þŸþ«þ¹þÉþÚþêþûÿ ÿÿ-ÿ=ÿLÿ\ÿkÿzÿ‡ÿ•ÿ£ÿ±ÿ¾ÿËÿ×ÿâÿíÿ÷ %,3;DLU_it‹˜¥³ÁÐßïÿ+8CLTXZVL;!ýЗ_'ÿùÿÅÿ}ÿ:þ ýÊüˆûŸûpû5û(ûeû!úâûšüµýÌþïÿÙ¶…IJ³Ñù@ " E ú ¼ w  &  ; F õ 5 ®ÏÌ \ t…§é)7µn¦ w í (  ¶%$ © ª m  Ö i  f  öZ x % ¶ y½Û_nÌI%û´i/H‚¢k* ¥  6 Ô ß û ” « º ß Ó F è ‰ ý ã˜B ü Ñ 3 ) B  e (  r+p;,‚ìn®Gÿéÿ‘ÿCÿþÉþžþ}þfþWþOþMþPþWþaþnþ}þŽþ¢þµþÉþÜþïÿÿÿ&ÿ8ÿIÿZÿjÿzÿ‰ÿ˜ÿ¨ÿ¶ÿÅÿÒÿßÿëÿö %,3;DLU_it‹˜¦´ÂÑàï*6AJPTTNA-è·{-ÿðÿŠÿþ‡ýäüäûËûúòúùûúÝú°ú¨û“ü™ý‚þ<ÿ: Ð’=g _ m e g Ë  \ S Ð è Úc Õ Þ % Ç ®çbh|f>¾XïZC¹ €  • Å L ¹ € ©²ª t - Õ e : Æ â P _ <4’M’YáU¢Ñ ö £0Ý–L  [ · \ % Ö j • • ¦ Ñ ] ¾ /  i ±§ ¾ d ¢ = / Z ø r­(ÎÍÈå;Ÿ}6ÿîÿ™ÿDþõþ²þ{þQþ2þþþ þ þþþ+þ<þNþcþyþþ¦þ¼þÑþæþûÿÿ"ÿ6ÿHÿ[ÿlÿ~ÿŽÿŸÿ¯ÿ¿ÿÎÿÜÿéÿõ %,3;DLU_it‹˜¦´ÂÑàð)5?GMOME6üÐ`)ÿùÿÇÿ<þŸþýüûbûúèúöúÎú™ú|úÖû|ü]ý#ýÙþÿMÿþ¢Ó¤ ä ? 1 / ˆ = RÊ¡ WÄã Õ I Z 7h0]“öw‰À®ì ý × > ùuŒS â ó  9{ J  ¿ f – º ¥ .  ` ̬ÿþ³,ðXЇ} ó Í ñ£øm ó h ® » ¯ gß™BЂYLs ) Q  ì¢6ŒÀ¤ “ ' Ì ü Ò ŒoNgÏÝÿÝÿªÿMþôþ¤þaþ+þýåýÒýÈýÆýÌýÖýäýõþ þþ7þQþjþƒþœþ´þËþâþøÿÿ#ÿ7ÿKÿ_ÿrÿ„ÿ–ÿ§ÿ¸ÿÉÿØÿçÿô %,3;DLU_it€Œ˜¦´ÂÑàðÿ(3=DIKG=*ç¶~GÿÝÿyþçþ8ýVüZûŠû#úÛúêú}ùòùàú@ú¿ûdüüËýLý»þƒÿCÿ­½Ò@ o ® ¾ ø Ç ÿP°ªE[ Ž “0ᬞAèl P n ‹ bDzÖN £ ù äû&e i  Ù · ž > › | Ê  Õ1ÕyðDhïÖïV - 5=bõ) g | V Êšî5ÿ‰™”Iz ! € ‰j&Ÿ-Û± k » … ý½=•Öí8jŒÿâÿvÿþþOþ ý×ý°ý•ý…ýý€ý‰ý—ý¨ý¾ýÕýïþ þ'þDþ`þ|þ–þ°þÉþâþùÿÿ&ÿ<ÿQÿfÿyÿÿŸÿ²ÿÄÿÕÿäÿó %,3;DLU_it€Œ˜¦´ÂÑàïÿ &1:AEF@3ûΕV"ÿ÷ÿÉÿ4þ“ýåüóûÙû>úóúÉúVù¯ùùùÒú‡û0ûÓülüÔüÚýÍþŸÿy¸“:¤ ß  È  fÒlã /T— * ïhðÊÛè…sù q S·¼$yÉ Ü 7 ýrY  Ÿ • Š Š  Ý  ©«šy ².’ 9#€';…Duq† w + ÙÍ›¨ðXðþІ£Aä &3d,Í•Vú¯  Ðñ~Û>™¨ÆT’ÿÐÿJþ›þ<ýóý´ýý\ýDý7ý3ý9ýEýWýmý†ý¡ý¿ýÞýþþþ=þ\þyþ•þ±þËþåþþÿÿ-ÿCÿZÿoÿ„ÿ˜ÿ¬ÿ¿ÿÑÿâÿò %,3;DLU_it‹˜¦´ÂÐßïþ %/8>B@9( å±t.ÿûÿßÿ}þîþFý¦üÙû¾û#úæúù×øÇøWøØù•úUúùû‹üüpüçýBþžÿw1 K ª  Ü z' ¡xgñ)kb h )ÆGá7  §’ì ¯ + ¨B­6„Ÿ I ¥ 3 #7a ¿ Š ; { Œ s hI‡õºVëpÉ´Pi÷Ù±Ù ä   C ûÈÄâé`oÂÓ{‚ æ_²°ÛñrˆœOjWl´…ª"8…"ÿþ»þ ýÓý“ýXý(ýüñüçüçüðýýý0ýNýmýý²ýÕýùþþ<þ\þ{þ˜þµþÑþìÿÿÿ6ÿNÿeÿ{ÿ‘ÿ¦ÿ»ÿÎÿàÿñ %,3;DLU_it‹˜¥³ÁÐßîý #-5:=:0ûÍ“OÿõÿÅÿ6þ–ýþýsüãûéûúÝú_ù^øFøø¹ù‹ú7úÉûHû©ü-üÄþþÓ÷@ÅV« P  x?nñ[0ïMÍö s ’ £Ë|ù¦ÝHf· Ô … ÿ Ÿ:.0 + ´ ÛÀóÇq « ø V s „ bçjýØ÷2„l†·Y1vÛ’«”W ú m ïÝ#q7dˆ{×®eñÀ5É^s¬÷xwæÞ N,S¿í>ÿ¬ÿþ ý¨ýoý-üöüËü­üœü–üšü§ü»üÕüôýý9ý_ý†ý­ýÔýùþþ?þaþþŸþ½þÙþõÿÿ*ÿCÿ[ÿsÿŠÿ¡ÿ¶ÿËÿÞÿð %,3;DLU_it‹˜¥³ÁÏÞíû  *1684&ç²u7ÿýÿãÿˆþõþOý±ýjý'üû£û[úKøãø9øøÙù—ú1ú©úÿûRûý þ7þÅÿ}Tè’f«à r ” ªñv¸×ä°U×!  ­ ?Q_Kmžÿê Õ Ž × û µ& ò Ž I  œqÃå„ä Á ¡ Ž ¯ˆ¦O£ìMë  °ð›ÀU¬¾io ù s ó w (°EŽå:Z‰iY­  à '<4DÿºÄ¤n. ÿèÅÆÚþgÿÉÿ þUý±ý]ý ü½üŒüküSüGüEüMü^üvü”ü¸üÞýý/ýZý…ý¯ý×ýþþ#þGþiþŠþ©þÈþåÿÿÿ7ÿQÿjÿƒÿ›ÿ²ÿÇÿÜÿï %,3;CLU^isŠ—¤²ÀÎÝìú'.22+ÿÒ–Y ÿùÿçÿVþªþ ýýcý0ýüÃüú|øöø1ø˜ù"ùÆúJúªúÐúàûÀüäýªþ4þ¸ÿUÿîsáñÛºŠ § ¥š†m»j ¾  ð Wn…Qm†—šˆ …  j H Ð . ¢Šì£>æ0 N Éö«óÖºu¥½Ú›Ûuœµ Š¾æ «ù Õ ‡ ª | Ö Éi@CÞ;uÇLRd”eŽä¢ ¾Ù(»dTrè ¬"‹¦ÿëÿhþŸýÇýcý üˆü1üüûùûñûôûÿüü1üTü|ü¦üÒýý.ý]ýŠýµýßþþ-þRþuþ–þ·þÖþôÿÿ,ÿHÿbÿ|ÿ•ÿ­ÿÄÿÚÿî %,3;CKT^hs~Š–£°¾ÌÛêø#),*!î½:ÿýÿÁÿ!þhýÂýqýhýiý|ýcülú«ùø»ùù’úúŠúõúöúíûºüÃý$ýtýÕþFþ¼ÿ)ÿTÿHn9• b é Óë׫@ ö ² ‡ ’ S £»!+®ÛzO}Å Z O ³   ¶ Ä ¨“IW³|´3q  † šW癋*-Më ‹îä7‡ Rh,¿ 7 Û Î ƒ C • iðˆ[„tÄJž.±…×äå4ØÑ6ª·f:£µÿÞÿ-þVýfüÇüUû´û¦û¬û§ûŸûû¤û³ûÌûîüü@üoü üÑýý5ýfý”ýÀýëþþ;þ`þƒþ¦þÇþæÿÿ"ÿ>ÿZÿuÿÿ©ÿÁÿØÿí %,3;CKT^hr}‰•¢¯½ÊÙçõ $&"ÿÛ¨d1ÿþÞþ-ýˆýUýOýoýýû÷úŒùøõù€ú ú‡úðûlûÃû^ûìüü£üüÃýýŽþþXþ¦ÿ½l¿¬ Æ ´ ½ š ¢ ‚ @  ú 1 Œ ÿ ] o½|²Ú˜Ÿèº[w C â I « À {nT2ØVOô@‘i ™ AT¡.ôï kïÜ6µvZ6xº‚C²w1  ± 0 Æ  É ÀCà©nûr1õƒß¦T¹þE’)›Õw6›ì¤ÿŸÿýêüêûçûKû$û0ûKûMûIûKûUûiû†û«ûÖüü:ünü¤üÚýýCýtý£ýÐýûþ$þLþqþ•þ¸þÙþùÿÿ6ÿSÿoÿŠÿ¥ÿ¾ÿÖÿì %,3;CKT]gr}ˆ”¡®»É×åòþ ïÈ’O ÿ÷ÿRþ ýìý~ýIý4ýný]üÄû_ù©ø¥ùúúªûûwûôü[ü3üŽüœüû…û]ûÃüaýýÅþ$þü¼­ š W 3 ‹ Ÿ « • r \ u ² : â ¯ ½†ýQòø‡ á } ¸ ½ aBHVòï›(*ýi–Ã ß "7L’²Ú]púêËœJJ‘Kë> ² Ë I ç S t Y ~ *‡“½â{ÃC2%Ç@OYÔw·T“/<+DÿCþ#ýü‚ûzúíúÖúîúüúúúöúûûû ûAûjûšûÎüü?üxü±üêý!ýUý†ý¶ýãþþ8þ`þ…þ©þÌþîÿÿ-ÿKÿhÿ…ÿ¡ÿ»ÿÔÿë %,3;CKT]gq|‡“Ÿ¬¹ÆÕâïû úݳz5 ÿÿÿÁÿ&þiýÆýQýLý^ýhýUüŠúîùø8ùŒúáûŒûÏûÙü<ü–üÿý"ü«û1ù¥ù[ú!ûIü?üÃýþd"¿œ ÷ í w Í ø  æ µ „ ’ h » x';G"nÍâ” ' W y „ò2ŽÏ.AˆßYJÇ Ï ~ m 1?9½9@˜ ËMÁrÂd¼z5kŸ W y Ä  Ù " P ¨¡–Ò%[&ƒG—âFöôþ—–—ã‡5¯®—üz’ÿÌþÒýËýüeûûúÛúÅú¾ú­ú¥ú«ú½úÙúÿû,û`û™ûÕüüNüŠüÆýý7ýkýýÍýúþ&þOþvþœþÀþãÿÿ%ÿDÿbÿ€ÿÿ¸ÿÒÿê &,3:CKS\fq{†’žª·ÄÒàì÷  ÿêÊžeÿÿÿÿþQýŠýLýaýuýlý"ülúÎù8ùWúþüVüÙüÆü<û³üRüÊüjûXù,÷öíø«úkû¶ü1üBýÓ°düà  ù · , u Ÿ †  ƒ  ¼ uó-\•ÎÒË3WbD½ Í ÂŠ·xXì ,ž]ØÎù“Ë ! * 8 ï ã ¨ ³ íE§d^Ö[TD5 ð o ¹ Y Ê Œ V i ÉÌ+Y> Α84¤4`¶ñ÷bðx/Ìëÿgþý ýüvû¼û$úãú§úwúXúRú\úsú•ú¿úòû*ûgû¦ûæü&üfü¤üáýýRý†ý¸ýçþþ?þhþþ´þØþûÿÿ=ÿ]ÿ{ÿ™ÿµÿÐÿé  &,3:BJS\fp{…‘œ©µÂÐÝéóüòÚ·ŠQÿüÿûÿšþþþJý¤ýTýaýyý^ü»û—úéúíûïý‚þ˜þ¿þ!üôûÉûëûªúÔùJ÷õƒõÃ÷çùõûqü6üýƒvmw© › e ¦ ) … Ð ¶±®ê¶8¹~ÕvÃ–Æ ½ Åá^Û=ó!ÞdÇPšÕS ;þj  w b Ê Ò ï  V “ Í ý   8 o N ò G  ~ ^ â À¶cc/|ë¥Ü˜ÕÀ¤N†›Ûµ”Êÿyÿ¡C°“{æÿþÇþ!ý“ý>üvû«úûú{ú&ùñùñùùúú,úTú„ú»ú÷û8ûzû¾üüDü…üÄýý:ýpý¤ýÕþþ0þZþƒþ©þÎþòÿÿ7ÿWÿwÿ•ÿ²ÿÎÿè  &,3:BJS\eoz…›§³ÀÍÚåï÷ýÿýôäÉ£u= ÿþÿûÿ­ÿ&þ\ýÅýPýaýxýü0û'û ü¥þ‹}ÚÌÿþZü’û³ûùÍø#ö®õ²öqøHùïûûÿü<þ¤MiQë „ ³ n  µ ð  4òï 7Ä%®0ÏŸí¾}È 1 ï J ÀN³É;ñ¸0¥½«ÄÜ:®ßº¾¼ N ª â 7 a † Œ µ ~ ï | ü  8 7 å » S¯dý¬”yf[í0ui?¿>µÏÿ7ÿ•gFãÿýýýßý­ýüLûnúùœùùQùyùùÂùêúúMú‰úÉû ûRû™ûßü$ühüªüèý#ý\ý‘ýÄýôþ"þNþwþŸþÅþêÿÿ0ÿRÿsÿ’ÿ¯ÿÌÿç  &,3:BJR[eoy„𦲾Ë×âëó÷øôéÖ¸\&ÿôÿöÿôÿÚÿ[þÒý¾ýbýnýgüýûíûHü5ýáfË#KþÐýNûôúûùëøø ÷þørùbúfûû•ýCþî<[£  Ž Ó W  à 2 Ð « ™  U × ¸>ÊxZƒílð § z Ø 5¶SM”×›_Šk Ñ©+–ÉäŒq–š´ç M[‚ˆ^  t ” â € Ù ,fT:'é—Q"§ ,æ‹u™=F7ÂZ ~mÿþpÿmÇä5Îþäý¾ý‘ýiüÐûåûú%ùøø²ùùHù}ù®ùãúú\úŸúæû.ûxûÁüüNü’üÒýýIý€ý´ýæþþBþmþ–þ½þãÿÿ*ÿMÿoÿÿ­ÿÊÿæ  &,3:BJR[dnxƒŽ™¥°¼ÉÕßèîññëÞÉ©}H ÿûÿòÿ¸ÿŒÿ ýÎý[ý|ýüÞû¢ûÇüæþÇ2›%€ÿÆþ—ýOüFûúÈú¡úœúœú˜úµû6üüøþIúAñ P ž ñ p  ä  Ð V  Z Ð  XÁ>æÅÅÈ$Í ¾  ³ Ð ‚5üVפ⤡%Æ*g_»Ÿá5w~|$V?ÊÕ  ±  cïå©))ñç](â1RßõǤg†ÿèþƒýðþáS•:ÿýÌýqý$üwûYúžùËøÁøVøYø¶ùùCù|ùµùóú5ú{úÄûû[û¦ûïü7ü|ü¾üüý8ýpý¦ýÙþ þ7þcþþµþÜÿÿ%ÿIÿkÿŒÿ«ÿÈÿå  &,3:BJR[dnx‚˜£¯»ÇÓÝåêìëãÔ¼›n7 ÿáÿ¥ÿVþüýÉý`ý}ý„ü•ûhû¢ý-ÿ4Vå,þIýSüÊü’ükü„üåý,ýUüEûØü¦ý|þrÿÍYhVvG  ­  q  Å á Ð p   Ý î ø /ƒìáµÓ  Œ Ø ã±$“y;ÅÕgOÖ)ÇDaûQzWFÅjÀìW¦¤ #‡ Z 1å¾ '€†~˜“-rÜU•Q“±#-(ùÆyœ’-ÿ£ýÒýqþˆÿ÷a xÿƒþýwýü<û'údù»ù#økøJøŒø×ùùTù‘ùÒúú]ú¨úõûBûŽûÙü"üiü¬üìý(ýbý™ýÍýþþ-þZþ…þ®þÕþûÿ!ÿEÿgÿ‰ÿ©ÿÇÿä  &,3:BJRZdmwŒ—¢®ºÆÑÛâçèåÜ̲c, ÿØÿšÿLþ0ýßý‰ýuýü!û,û¯üêþ•…i©þõý<ûÞû±ü•ý]þþàÿÐþäýÝýÜþ–ÿ? þ$ÎqÀÝ € ÷ $ ` Ö v ™ Ñ å ‹ N ¹ “ ‚ n ‰°ÈÒ´w Y y { ì ° ; ± YÏ“¡c„Rïc…Š›ëû˜›=åÑòîXŽÛw!’º‹N'™ˆ°ª ºÿ@¾A9|©;/ÁM®ãï ÿmþýkþFÿ¢ÿMÞUþsý“ý)ü$û2údùÇù3ønøHø~ø¼øùù6ùvù¸ùýúFú’úàû.û{ûÇüüXüüÞýýUýýÂýôþ$þRþ}þ§þÏþ÷ÿÿAÿdÿ†ÿ§ÿÆÿã  &,3:BJRZcmw‹–¢­¹ÅÐÙáåæá×Å«ˆ\(ÿ÷ÿûÿÑÿ‘ÿ?þèý÷ý¡ývüèûÑûûvü7ýMþ±ÿ~ÿFý®ûìûûqüöþ9ÿCyh ÅP¼ ¿Tª¸ « v ƒ   ‹ . 4 p  Ž þ ² Ñ ½ ×ð ¥ 9  ç ½ n À  þ A  > E i«ª$ÝüÿŽÿfÀï„Ýoo*u€;áY™¯©œÞú⾡h˜L[d¤á¢'ýSŸâ.JEÿ>þ8ýºþ*ÿ@•É(”þ§ý¿ý'üJû%ú€ùµøÙøPøNøxø¬øåù#ùcù¦ùìú5ú‚úÐûûlû¸üüKüüÒýýKýƒý¸ýëþþJþwþ¡þÊþòÿÿ>ÿaÿ„ÿ¥ÿÄÿã !'-3;BJRZcmw‹–¡­¹ÅÐÙàääàÕÁ¥V' ÿÆÿ‰ÿFþúþ ý«ýnüöûåûû1ûtû~üxþý€üûúüý´ÿ+o´æu’Xœc· ]  ¹ û < w m < â o › ù j ¼ ÷ ¶ Ð â ' mØÙ = ƒ ø “ [ 2 */ : ù M Ô » d_ |úp5¶ÿ}þ¿ÿNlq% и(«‰ˆ‚‹0IË’º› ˆ´Î ÿ Tƒ—f’¦‰{^tÿŽþºþýœýÍþ—ÿÿ|’þ·ýÊý&ü6û&úhù³øÙødøOønø øÙùùXùœùâú+úwúÅûûaû­ûøü@ü†üÈýýBýzý°ýäþþDþqþœþÆþîÿÿ;ÿ_ÿ‚ÿ£ÿÃÿâ !'-4;CJR[dmw‹–¡­¹ÅÐÙàääàÔ¿¢}Q( ÿøÿ»ÿzÿ)þ7ýÈý“ýoüÕûßû1ûúìúÎûVüCû˜úƒù‚úWüšþ—$zâF‡ƒ“\A’d È Ò L p Å ˆ®õ R ä  z ‡ ¼ ñ ² R Þ s (  _ ‡ v ~  Î š ®À Æ ï ë é 9ýIEFæÓíS`ˆ\â‚ÿ€ÿ8 ‘IЗÚ(èïB s‡Rùª‹e„oóÂa k ´  àÓ¤«b„uÿ€þ¶þ1ý“üèüˆý®ÿ{K„þ¥ýÆý+üVûGú…ù×ùø€ø>ø\ø“øÓùùXù›ùàú(úsúÀû ûZû¦ûðü8ü~üÀüÿý;ýtýªýÞþþ?þlþ˜þÂþêÿÿ8ÿ]ÿ€ÿ¢ÿÂÿâ !'-4;CKS[dmw‹–¡­¹ÅÐÚáåæáÕÀ¡yL ÿ»ÿFþèý´ý]ýnýRüµû›ûúêúËú¹úÕú¨ùáøžøÝú€ýÿ{³Ïy~ 1 ¥ \ ç ˜  6  4   Þ ìõM2 ! Ì „ × ê Ç p æ V û ´ ¢ × … < à L 9 8 Ü 0 Î   õ 7¡˜º×\ÇÝŠ-z‚BÿJšÖ?Ít0";yƱN—íà^ÆÈõDÏŒªºþº¼ Å f Æ  S š(©i†ÿÊþWþý·ýü.û˜ü‚þª#¹Dþ–ý›ýbüÁûœúñú'ù;ørø(øAø‚øÕùùaù£ùæú,úuú¿û ûWû¢ûëü3üyü»üúý6ýoý¥ýÙþ þ:þhþ”þ¾þçÿÿ6ÿ[ÿ~ÿ¡ÿÂÿá "(.4<DKS\enwŒ—¢®ºÆÑÛãèéåÙãxJÿõ ÿÌÿ\þcýÞýgýLý=ü§ûiúáú×úÉú©úcùÓø¿÷V÷úsýwÿ¸Ñ!l± b : E Ñ × ¹ Hÿÿ Lþ[Àl} ‰ › [ º # N ´ g T p © 4 ] — ì é ˜ Ð ( ê Ö é ¦ ° h“?è¹ßŠÔõìÑ]U8 êøñ)ŠI¼ë°‚”Í‚ÈrÜ7” j Y0 [ K ¢ ¢ ŠÈÈ8SvÊÿÝþTýÎýpüÄûÛúüû’ý’ÿÉó þmý•ý”ý>ü‚ûúùsørø#ø$ø…øíù7ùwù´ùóú6ú|úÄûûXû¢ûêü1üvü·üöý2ýký¡ýÕþþ7þeþ‘þ»þåÿ ÿ4ÿYÿ}ÿ ÿÁÿá "(.5=ELT]fox‚˜£¯»ÇÓÝåëíêßÊ©zD$ÿêÿ–ÿ(þsý§ýZý6üûcúÓúßúãú¬ú;ùƒø`÷G÷çú{ý.ÿU#à>† Õ Î a œ s¡ó˜Ò–i¢Ê Ô ñ † $ Û … ‰ ¼  • d ø ò u l — œ Å ¸ Ñ ÿ } +¬Ì>/‘2éH­=9#ñ«m~Âøàþ;…Õd¹’²• ÿ<‰‚÷á¸ÍH L v ¢ Ä ¬ ¿]Ú™9@þÌýîý`ü­ûÁúÆúzü\þÿâÿ»þ0ýgý ý˜ýLü;ûùßøÏøiø\øÒù%ùcù™ùÐú úFú‰úÎûû]û¤ûëü1üuü¶üôý/ýhýžýÒþþ4þbþŽþ¹þâÿ ÿ2ÿWÿ|ÿŸÿÀÿá #)/6>FMU^gpyƒŽ™¤°¼ÉÔßèïóñèÔ²F ÿêÿ‘þ¨ýÀý[ýIüïûÜû'û5û.úñúgùšø¢ø)ùûüÔþ¼5/”¯© z ?­Öô- Ãîð!êí e § E ¦¶’À  ¤ _  / ð Ï  % a  Î À z Õ´Xû@Ò¨•a*’©Ž[Úÿ™Õ›¤§½çPx;ÐG#IÿÛÎåê³ íÞ©úå q z ˆ Ü ø ç ` o>øš(ZåÿþýiüÝûæú‰ùÊû€ýÐÿLÿ…þ'ý^ý`ý‡ýZü±ûCúSù­ù ùRù[ù|ùŸùÆùòú$ú\úšúÛûûeûªûïü3üvü¶üóý.ýfýœýÐþþ2þ`þŒþ·þàÿ ÿ0ÿVÿ{ÿžÿÀÿà $*07?GNV_hqz„𥱽ÊÖáêò÷øñß¾ŒQÿ÷ÿö<Wÿþ_ý¡ýuýaýü®üû¾û©ûûú$ù3øÒùÕû5ü¤ýçÿÿd¢7§,Íô¥ÎÜìS·íT娗 , jÝÁüi ø > m Š á ­ R o C Ñ <pr!Ÿ›Z~v¡PDê†]»-jvTYp‘¶ÕßÅyÿöÿKþ—þÌà±x¿ˆ"¡ ‡qÞ ° ˜ F £ Ä s § t ‚Ü6ûÿ+ýîýœý4üSúùwû.ýtÿ$ÿ†þwýWý<ýLüøûãûAú­úKú<ú+ùúùÜùãùùúúDúvú¯úìû-ûoû²ûõü7üyü¸üôý.ýfý›ýÏþþ0þ^þŠþµþÞÿÿ/ÿUÿzÿÿ¿ÿà $+18@HPX`ir|†›¦²¿Ë×âëôûýùêË™]4ÿåÿÀrHÿMþ ý¤ýýsý^ý3ü¶üQü+üKüXûoúZú+ú¿ûpüDýlýPýÃÿ‘ˆ Н·Òp¯´ÂžÒ.Z·–(µ%ßæ&œL E ƒ 3 s= ' ´ Œ î jnˆ…aåÙš}ƒ·üUÊPÓNÈBÿùÿÝÿìÿó<ZlkHÿûÿxþýÈþRÿ£²X>ÃÖÇ…ß¾[ª S _ n l J ÷ Z V o Z„˜¸sÿ—þlþ ý±ü·ú®ùöû±ýþôÿŒþŒýjý4ý!üyû–ûúÓú·úÌú´úfú3ú%ú-úDúfú“úÇûû=û|û¼ûýü=ü}ü»ü÷ý0ýgýœýÏþþ/þ]þ‰þ´þÝÿÿ.ÿTÿyÿœÿ¿ÿà %,2:AIQYbkt}‡’¨³ÀÌ×âìôüþñÒ—YÿÑÿÓÍ‚ÿþ ýªýˆý}ýƒý\ýü®üŽü¸ýü›üŸü1ü ûÛûÁü2ü”ý+þ³*ŽðùzÚ =ótrÝs×G»%tŸ±Âè4¯bV – ÿ § •] } Ó V u ½¦_NÀª§“­Ò±S¶&›ÿ»ÿ}ÿfÿkÿ‚ÿ¡ÿÅÿê ÿÅÿZþ²þ-þaÿfÅìò‰Š¿‰Há… R Ø ³ j ” ®}ö ¤ •†zɰÿpþóþWý6ü(ûçü²ýùÿ ÿhþ|ývýVýüû‹û úåúÜúçúÛú¨úuú^ú]úmú‰ú±úàûûOû‹ûÉüüEüƒüÀüúý3ýiýýÏþþ/þ\þˆþ³þÜÿÿ-ÿSÿxÿœÿ¾ÿà  &-4;CKS[dmv‰”ž©µÁÍ×áêóúÿýð·%ÿÿÿÝKðzÿÏþ0ý·ýˆýhýrýdý#üÞü¾üÓüÖýeýéþ`ýYüsûÖû²üzý+þ=ÿ19³bË VÿÊÿª"ÚŠóM®wÔ"Z‚¨Ü-§S:\ ± ô ° ž å  '§xw±ão좆”£–H¿qÿ×ÿWþüþÍþÆþÞÿÿ9ÿmÿžÿÈÿæÿôÿìÿËÿÿ6ÿÿÿ‹ÿ–°;-‰ÐžO P ? ” + ù ^2æÜþ ‚ i!Ê´îÿ0þHý¤ýýìþ•ÿFÿQþ5ý¢ý\ýSüšû˜ûúèúÝúÞúëúËú¨ú‹ú‡ú“ú¬úÎúúû+ûbû›ûÖüüNü‹üÆüÿý6ýlýŸýÑþþ/þ\þ‡þ²þÜÿÿ,ÿRÿwÿ›ÿ¾ÿß !'.5=EMU]fox‹• «¶ÂÍ×àçïõøõå¿sÿøÿús]"Äþ‹ý»ýwýaýdýdý-üòüÎü¼üñýþ»ÿeþIüõügüsü¿ýNýÈþ`þïÿa;ÿºÿ'þ•þEþdþôÿÍ}òL¨`º KwœÌ‡'ý; ž ü ú % z  {çÆø1æã/‘†˜wø7uÿ·þûþaþýîþþ<þ‚þÍÿÿZÿ”ÿÄÿæÿùÿûÿìÿÙÿÑÿèÿùYÉLYŒÌâÜÑ Ï › |   n tdclG V °0 ÿJþÉþ£þÏÿ4ÿ™ÿ_þ!ýdý+üõüjûsûúìúËú×úÛúïúÁúªú¨ú´úËúëûûBûuû¬ûäüüYü”üÍýý;ýoý¢ýÓþþ/þ\þ‡þ²þÛÿÿ+ÿQÿvÿšÿ½ÿß"(07?GOW_hqzƒ—¢¬·ÂÌÕÝãèììåѨa$ÿðÿòc#ÚcÿåþJýªý„ýzýcý]ý7üþüÔüÂýýÏÿÿ¥þý[üùüôý5ý9ýhýªýôþ=þsþ~þQýêýiüòüµýDþ@þøÿ§wÕáI|™§¾óRᥚ¸ì  5 Z î HûמD)­½œ7¼Ž‹ƒ €§ÿñÿ ýïý$üÍüàý"ý‡ýôþ`þÄÿÿmÿ³ÿíDay«Ø.l®a–¨¬ÄÙÛ Ý ÷ M ä ó4©%¢3µ Ð {ú>ø;E©ÿûÿÿ^ÿmÿ³ÿõÿyý÷ü®üfü)ûƒû/ûúðúáúÕúØúØúÌú¿úÃúÑúçûû,ûXû‰û½ûóü+üdüüÔý ý@ýsý¥ýÕþþ0þ\þ‡þ²þÛÿÿ+ÿQÿvÿšÿ½ÿß #*19AIQYajs|†™£­¸ÂËÓÚßááÝѹPÿóÿÞ;®°`ÿiþ ý”ý}ý~ýzýlýAýüäüÄüüýÞÿÿþ±ý»ýPý2ý"ýýýý.ý8ý/ý üÅülûáûuû¤üvýýÀþ•ÿXÿð?¶ÆõîDzÁ~3!7Mo + † ^U  >ê¨ ¢sV vÆCÿFþ,ü¶ûŠûmû¢ü*üÉýiýùþzþìÿRÿ¯R›ßVžßDëï³²Óú÷ Ö €  ´ Õq¾FÁ®¦X Š Q‚êEÆò[ÿûÿËÿÆÿø+ÿYýhûéû4û)úùúßúîúòúïúçúáúÌúÇúÎúÙúêûûûDûnûœûÎüü8üoü¦üÜýýEýwý¨ý×þþ1þ]þˆþ²þÛÿÿ+ÿQÿvÿšÿ½ÿß $+3;CKS[dmvˆ’œ¥¯¹ÂËÒ×ÚÛ×ν t;ÿæÿí5ÿäÿ7þý·ý£ýˆý…ýsýPý,ý ü×üíýåÿ=ÿ±þ¾ýéýƒýCýüöüÕü¸üü{üCûõû˜û3ûúÈúôûÃü[ü™ý|ÿÿ¦ÿý*ˆðs•Y™pˆò¦‘“œž‚0œAhîpK_V8¿M¥ÿâÿ"þMýû ú™úúaû+üüîý¢þ=þÇÿCÿ¶#ŽùdÐ6~€r±'Eûè¿)^ Q Ø W Ï f Q >@‡\ers  * Ö&K³ó|/ÿóÿ!ý,ûnúÒúÈúÕúÈúÙúäúõûúÚúÀúÎúÜúìûûû6ûYûû®ûÞüüDüzü¯üäýýJý{ý«ýÙþþ2þ^þ‰þ³þÜÿÿ+ÿQÿvÿšÿ½ÿß %-5=EMV^gpy‚Œ•Ÿ¨±ºÃËÑÕ×ÕÏì‹_-ÿáÿ÷ÿ‘þ°þ.þýÒý—ýrýXý^ýhý4ýþÿ^ÿÞþºýìýˆýSý!üæü­üuü<ûüû¬û4úÅúmúBú‘úÂûQüütüÁþjÿ§ÿÉ\«üËèÿrþäþ½ÿÿûåŠìÀ\ÁaÈiì–Øÿþ¯þýCüLûFúOù$ùCú‚ûü“ýbþþ°ÿ>ÿÄGÍXë… Ž¨(,µ~!Jî o B í o  Î ÛÖæ+² š ¤ ya‰cë8Àn7 ÿËþ‡ü¸û<úýû ûúÓúÑúÝúïúøúäúÓúÛúìúþûû,ûIûlû“û¿ûíüüQü…ü¸üëýýOýý®ýÛþþ4þ_þ‰þ³þÜÿÿ+ÿQÿvÿšÿ½ÿß '/7?HPYbkt}†™¢ª³¼ÄËÑÔÖÓ̾¥Nÿýÿýÿîÿù ÿçÿ„ÿJÿþfýÇýdýpýªý÷þýøþ±ÿˆÿØÿ þ ý¼ýý:üêüüSüû·ûZúÉúùsùcù­úUúÓûÕüEü£ý’þÃÿÒ+__7ÿûÿWþÜþüüü+üêþ#ÿ𦵮…-›Ë³iMvÌGÉz¾rÿþ«ýÈýxýüœûâûù¿ø®ùú*û[üdýBþþ©ÿDÿ×k®e7ónPñ/Îãs:O 3 Á { Q [ ‚ Æ E  Ë g Ä € $ Ùû€8Á•hJ$ ÿýðûùúçú«û.ûúÛúÌúÝúïúßúÙúéúóúþûû#û<ûZû}û£ûÎûûü+ü]üüÁüóý$ýTýƒý±ýÞþ þ6þ`þŠþ´þÜÿÿ+ÿQÿvÿšÿ½ÿß !)19BKS\enxŠ“œ¥®¶¿ÇÎÓרÖϪ„J ÿìÿï ÿöÿÍþÝþý“ýýýþ×ÿBÿŽÿSÿ°ÿéÿ³þäþuýØý`üýü¤üPûüû£û@ú­ùbø}ø”ø¾ùBúOúäû‚ü"üøþ#ÿ–Ó°$ÿžþÍýåüÖûÒú…ùùîü£þ ÿOu{\Ùà¾ë%¦qÿÝÿÞÿÆþÝýwüEûÕüUü#û«úÕùøŠù úûYüdýDþþ²ÿSÿíŠ0ìӬލ6rô5ûéä¾¼¥ ­ z W ø ³ 0 b æ ¶ s % ° ½ Ï 4´Wÿç%ÿÍÿ«ÿ¸þâýVû[ùùù¼úú„úuú”úõúÑúÐúäûûûûû0ûIûhûŠû±ûÛüü8ühü˜üÉüúý*ýYý‡ý´ýàþ þ7þbþ‹þ´þÝÿÿ+ÿQÿvÿšÿ½ÿß #+3<ENW`is|…˜¡ª²»ÄËÒØÝßßÛÑÀ£bÿÎÿàOC)!%ÿîÿ8þ1ý«ý·þ>ÿ7¿ÿÉÿ²ÿøÿiþ¸þý€ýü¹ücüû·ûRú«ù¿ø†øYøFøaù.úú¹ûyüfý˜ÿ(å÷8ÿ>ý÷ücû6ù‚ø3÷÷ãúGü¢þÿbzg)¼ZQ ƒþ(Gÿåÿ­þ’ýûú¬ûdûúûãû ùÌøÍøäúhû–ü‘ýeþ!þËÿj¡Häð)*Œ†¬±œz| # B ½öüEÚž œ t  { + *ùðInÿ¾ÿÑÿêÿ´ÿuÿþ‚ýöü…ú›øÔø£ùbù„ùÑú.úfúŸúÇúøû-ûûû#û8ûSûrû–û½ûçüüBüqü üÐýý/ý]ýŠý·ýãþþ9þcþŒþµþÝÿÿ+ÿQÿvÿšÿ½ÿß $-6?HQZdnwŠ”¦¯¸ÁÊÒÚàæêííëåÞÓaD pµÂƆ7$ÿæÿ]þYý®ýÌþQÿ7ÿ³ÿãÿ¿ÿÌÿçÿîÿNþšþ ýŽý,ü×ü†ü7ûçû‘ûúPùXøÍø)÷ÆøqùeúúÚûÅüéþVÿ¥Ù@ÿ[ýŸûìú(ø_ö†õÐö»ùûrý-þˆÿ­¦u”íQÍeê@ŸŒ—ˆNþáüôûaúCúØüƒü_ûŒúˆùƒúûü üãý¢þPþñÿ‰±Lô³7~ztj>¦bÑq)9Z   e¿æ‹¯Ùà ‹ Ö K +r³wÿÂÿ¸ÿ=ÿnÿþqýÆý;üú4ø°ø“ù:øàù0ùùêúQú¬û ûû ûû$û<ûYûzûŸûÇûñüüJüxü§üÖýý3ý`ýý¹ýåþþ:þdþþ¶þÞÿÿ,ÿQÿvÿšÿ½ÿß &/8BKU^ir|†š£­¶ÀÉÒÛãëòù (D˜ÜHn~7¸O†Iÿƒþ^ý¯ý×þKþºÿþàþçÿ)ÿ~ÿpþáþQýàý‡ý?üþü³üdü ûîûÁû=ú“ù‘ø‰÷fø;ø÷ù”úEûüý>þuÿi^ÿ’þ…ü?ú=ødö¢öjöÿøÚúëü’ýîÿî¤;¨Æª_ Ÿ`{¡²)ÿùþü>û?û…ý üâü3û~û2ûTûõü ýNýôþÿ#ÿ¯6¼CÍK¨¼¿¶ tô|ñtßé_  þq­µ ö38ö ƒ 1Ø2U…ÿ¾ÿ”ÿnÿþ·þýý*üEúÆù¡ù„ù„ø«ødøþùxùçú}ú©úÇúðûû û;û[ûû¥ûÎûøü$üQüü­üÛý ý6ýcýý»ýæþþ;þeþŽþ¶þÞÿÿ,ÿQÿvÿšÿ½ÿß (1;EOYcmw‚Œ– ª´¾ÈÒÜæïù !1Gk³ç ÖÇü=AzPp;þýÏýêþOþþžþDýOþþ¾þ”þJýêý ýpýNý5üôüxü1üBüjüUûQúFøâøOø@ø´ù'ù½úxûSüDý7þ1þÓÿJþ0ü]ú‹øû÷ù÷z÷Ùù7úÖüKý’þ²ÿ¯ŒMðU{vx< d~jJ/ÿÃþ,üçýwý\ýMüÛüüSünüÃý>ýÇþRþÛÿ^ÿÜTÇ7¡Ta2$D‡ÿwü™ZUR3¡jÎ1Ãð«^¤Ãâ[€ÿßÿ‡ÿ=þÞþlýîýsý>ümû*úÒú³ùýøÈø+ø‹ùùdùÁú3ú¯úìúýûû7ûZû€û¨ûÒûýü)üVüƒü±üÞý ý9ýfý’ý½ýèþþ<þfþŽþ·þßÿÿ,ÿQÿvÿšÿ½ÿß *4>HS]hr}ˆ’¨²½ÇÒÝèóý .?Uu¢Þ8ˆFVÃã.ÅZ#G1ÿbþþ/þ†þ¢þ‰þý€ý\ý»ýÞý«ýkýKýKý_ýcý5üQûrü-üþüIûù øÇøcølø{øÊùEùãúœûdü-üÞýtý‘ýûâúšù…ø°ø^ø¾ù¾ûüBýkþzÿpK ²ê¯ˆhRWi†™¤BÝÿŠþÅþDþý»ývý<ý$ý8ývýÓþBþ¸ÿ/ÿ¢x×/~ÅCÐÚö1†òn¯zzãáýãsÈà<gw>§`‚³rÿÐÿ^þôþŽþ(ýÊý‰ý(ü8û6úéúÖúWùøGøpøøôùyú úÞúßúñûû/ûUû}û§ûÒûþü+üXü†ü³üáýý;ýhý”ý¿ýéþþ=þfþþ·þßÿÿ,ÿQÿvÿšÿ½ÿß",6ALWbmxƒ™¤°»ÇÒÞéõ(6H^yË e¨‡˜ —Øáñ§º¨ï2þÈþìÿÿþ¹þTýíý ýyýzý üËüËý)ýeýaüãûkúGûjüxû¼úNøs÷•ø.ø#ø8øwøàùhúú¬ûNûÙü2ü<ûçûDú‚ùÆùø¾ùPúFûNü_ýjþgÿR'â|×7i›Œ|bEAbŸv—‹ÿŸÿþ–þDþý×ýÈýÛþþ[þ¹ÿ ÿˆÿîN¥ò2fºÄ­ƒtŠ»`ÏQè˜np{BR-ÿ{þâÿ|Ÿ+þ{¢)Ni4ÿ¦ÿ$þªþ;ýÚý›ýzýûÖúúúùáøÝøkø_ø’ø¶ù-ú ú~úÇúÜúþû#ûLûwû¤ûÑûþü,üYü‡üµüâýý<ýiý•ýÀýêþþ=þfþþ·þßÿÿ,ÿQÿvÿšÿ½ÿß$.9DO[gs~‰•¡¬¹ÅÑÞë÷ />Od}›Áî'm•œÝNíÖªÉçªÿåÿŸIÿÿþÕþ€þUþ ý’üÞûòüý$ý\ýû¿úšúúÉûúöù’÷ã÷U÷5÷¶÷ëø2ø“ùùšú*ú±ûû\ûbû0úÒúbùñù}ù)ùÙú»û£ü“ý…þpÿNÏgá=}¡«œr0ü-S4öþ<ÿ•ÿþÂþþYþMþ`þþÖÿ,ÿ‰ÿçB–ÞE^f\Aüñ/pÁ"’žLŽrÿpþ–ýûýµþ>ÿµ1:Þ$ÿg‰ï‚ÿrþßþTýØýwý.ýü“ûRùµø²ù5øôøtø;øVøTø…ùùÚúYú•úÁúèûû@ûoûžûÌûûü*üYü‡üµüãýý=ýjý–ýÁýëþþ=þfþþ·þßÿÿ,ÿQÿvÿšÿ½ÿß&1<HS_lx„©µÂÐÝëù$4EVk‚ž¾ä ;i³1ËÚË6¹µC.ÿèÿ¡ÿ™ÿtÿþ®ýèýü“ü³ý,ýTümû4úšú¥ú½ú“ùøí÷‹ö.ö´÷S÷µøøgøÜù_ùäú[ú´úãúçúÅúúPúùìúúqû/ûüüÕý³þŽÿ`"ÑgäFŽºÉ¼”<ôF÷rP© ÿ‘ÿ1þêþ¿þ´þÊþýÿDÿ˜ÿòKŸé&SmpW!Ö\Pe’ÏmÊ-œ÷ÿÿ{ýlý6ýhýPýöÿ…×·"7 pÏL7ÿåÿCþýðýcýü¯üLüú±ø˜÷µø7øjø3øø!ø=ø`ù&ùïúKúsú úÎúÿû1ûcû•ûÆû÷ü'üVü…ü´üâýý=ýjý–ýÁýëþþ=þfþþ·þßÿÿ,ÿQÿvÿšÿ½ÿß (3@LXdq~‹˜¥²¿ÍÛêù(9K]qˆ£Áã 0Sh‹Ó²BÐ;j²æL#3,c­(ÿ.þ‡ý ý ýýJýûïûPúöûûúù\øE÷Œöhö¸÷O÷¬÷þø_øÖùZùßúQúžú½ú´ú“úmúQúGú[ú˜ûû£ü[ý#ýðþ½ÿ‚;âtïS Õìã»wCs<ßk÷lÿóÿÿ:ÿþøÿÿWÿ©\´J¢µ·}ÿèÿ—ÿÿ´ÿë(l´Fƒ±.ÿlý¯ûÿü`ý'ý¥þšÿ¢ʛQ'F1 ÿÔþôþ'ý|üáüeüGûúÜùÎøöä÷­÷ü÷ø÷Û÷çø øgù,ùûú)úGúxú®úæûûVû‹û¾ûðü"üSüƒü²üàýý<ýiý•ýÀýêþþ=þfþþ·þÞÿÿ,ÿQÿvÿšÿ½ÿß *6CO\iw„’ ®»ÉØèø*<OcxލÆç 5]~‚Šëw÷}æ5Ë/ì³* ‚G|® o@›ÿ†ýéüåüÌý?ýüÒûuûLûSûú†ùÅøêø÷÷]÷š÷Õøø~øûùŒú!ú¨úöúóú¼ú~úbú_úyú¯ûû}üü¿ýyþ:þùÿ³`þˆþ^ªï"ë–ns–t"±9ÁJÿØÿqÿ%ÿÿIÿ§ jÈ"t¸êÚÿßþìþ‡þ©þÿÿ@ÿÿ¾ÿþ;l0ÿ.ýÞüOû§ükýQþ5ÿjó“ ÄÿÑÿªÿ—ÿ/þpýžüúübûØû5úØùùø“öÏöë÷¢÷€÷`÷T÷÷ÙøHø÷ùŒùÊúúFúˆúÊû ûEû~û´ûèüüNü~ü®üÝý ý:ýgý“ý¾ýéþþ=þfþŽþ¶þÞÿÿ,ÿQÿvÿšÿ½ÿß  ,9FTao}‹š¨·ÅÔäõ+=Qf}”®Ìí=k™Âàåcá`ìC<x¤ÿ•zÿÿ°ì({ß"¾þüˆûõý<þ–þ5ü—û±û>úüú°úIùŸøðøhøø ø"ø\ø¼ùFùîú¦ûQû´ûdú˜úgú_úuúµûûpûðü…ý*ýÙþŽÿBÿî#£g©Û2T㞌”‘@æ„¢#ÿÿÿ ÿkÿûoÕ5”í;l€te\+ÿAýæýuýüþUþ˜þÖÿÿMÿƒÿ¬ÿ´ÿkþ”ýËýµýDý.þþ±ÿr‡²”0ðÿyþñþ^þ þýŒüôünûíûeúéú|ùm÷—ö/ögöøöáö^ö¸÷'÷¥ø/ø’øÄùEù³ú ú_ú«úñû3ûpû¨ûßüüGüyüªüÚý ý7ýdýý¼ýçþþ<þeþþµþÝÿÿ+ÿQÿvÿšÿ½ÿß !.<JXgu„“¢±ÀÐàñ)=Rh˜³ÑòBsªä OÑîI©â.*hÜ«t#ög›à;¡†þ„ü²üuý¡ÿCÿ,ýæüšû½û)û5úàúEù ùø¶ø‡ø†ø±ù ù¡úû\ü(üAû$úDúú$úûûpûæüküþýœþCþìÿ“3ÈNÃ#mž´´ç¸Š‚m-ßrÿÚÿÿÿÃiÝA¢qÐ!Þ÷ þóþý|ý}ý¹ýñþ0þnþ£þÕÿÿ8ÿ€ÿÒÿùÿÊÿŠÿ"ÿTÿYÿ5¤`ÿtþ«ýâüóü[üwü„ü7ûáûû*úæúNù+÷õÝõùöHöõÍö5öÖ÷yøøWøDøËùcùÔú5úŠúØûû_ûœûÔü ü?üsü¤üÕýý3ýaýŽýºýåþþ:þcþŒþ´þÜÿÿ+ÿQÿvÿšÿ½ÿß #1?M\l{‹šªºÊÛìÿ&:Pg€š¶ÔõEw¯ñ;Œå8 e+|à [‚ÇQXy#$g C£gLÿJýèýöþÈÿiÿ`þ¨ý½ý üü)û§úáú1ù¡ù;ùøöùùcùöúäüNüæüãûmúù?ú4úêûxûöürüöý„þþ¶ÿSÿí€ç:u–s{ic†em ©ŒT M)ÿëqøW­qðˆã þoŽ~ÿRþTý•ýüþý1ý™ýÓýþþ)þhþÖÿ¿ jpJí³ÿØÿ…ÿ´ÿrÿHÿ'þÎþZýuü›û˜úïû;ûƒû…ûbû#úóú×úXø¹öÆõ³õÌõëõÈõ õñöo÷÷òøø ø‡ù%ù¤úúkú¾û ûNûûÈüü6üküžüÏýý/ý]ý‹ý·ýãþþ8þbþŠþ³þÛÿÿ*ÿQÿvÿšÿ½ÿß %3BQaq’¢³ÄÕçù !6Ld}˜µÔöFv®ð>˜lú„Þ9ª{®“å ? Vf÷¤¥y€«Óí©ú}ÿ”ÿ¹ÿüÿ§ÿþþþ ýµü{ûmú¬úù·ù€ùpù‚ù»ú0ûüAý¥ýxüMú”ú3úšûbüü›ýý•þþ¢ÿ1ÿÀLÑJµU„™iD6„riÛ ä¨Vá—‚T_žÖ^ÂQâS¸,f-$þÚýÏüËüüÂýýGý]ýtý«þGÿ~ºÉµ~åiÿ–þÇþTýÌýýüŸüûTúžúúhúÀúóúÿúçúÓúáú4ø‰ö˜õ¸õËõ×õ»õ³õÌöö|÷'÷˜÷ìøeøþùùîúOú¥úôû<û~û»ûõü-übü—üÉüúý*ýYý‡ý´ýàþ þ6þ`þ‰þ²þÚÿÿ*ÿPÿvÿšÿ½ÿß '6EUev‡™ª¼Îàó0F]w’°ÐóDsªé3ŒõqÇy÷?¯` Ž ¢ ©  8MéÑû#A0‚ᎥF¿ÿ÷ÿ„ÿ"þñþíþwý ûÙûú|ú(úùöúúúWúæüý;ý„ýü}ûíû˜üaüÍýDýÓþHþ»ÿ4ÿ²2¯&‘î:s—¦£’zOTz  о®’h/*hJGQi˜ërU¨Ý˜<ÿ·þLüñü“üüÆüÌü»üŸüÆýfÿi-/üÔËJÿþüèüdûúû^ûúÆú=ù†ù™ù·ú3úŒú¿úÐúÞúºùüøLötõ·õÎõÞõ¼õÀõÁõ­õçö*÷=÷Ëø`øëùfùÓú6úŽúßû*ûnû­ûéü"üYüüÂüôý%ýUýƒý±ýÝþ þ4þ^þ‡þ°þÙÿÿ)ÿPÿuÿšÿ½ÿß )8IYj|Ž ²ÅØëÿ(>Un‰¦Çê=l¢Þ%wÚOÛ6ð<hþ Æ - 2  / ` RõbEºÚ°S‰é¸ð¥;ÿÍÿ¦ÿ‰ÿ=þdý:ü û9úÁúú…ú“ú‘ú’úJú–ûvüÍý˜ýÈýúýðþIý…ýrþþ¨ÿ ÿeÿÉ5¥{Ù(h•¯¹´¤gšQ܃”hU>÷ÆU澪³áEî•yL(èȆÿ÷þýüãü¡üyürü2ûïûü¬þG ¯…Y9ÿéÿOþtýZüRû>ú&ùÆùÈù²ùPøÍørù$ùÖúUú¤úÕúçú»ùÉ÷æö,õÍõàõêõÌõÎõ½õ…õuöc÷C÷íøeøâùTù½úúyúËûû^ûžûÜüüOü†ü»üîýýPýý­ýÚþþ1þ\þ…þ¯þ×ÿÿ(ÿOÿuÿ™ÿ½ÿß +;L^p‚•¨»Îâö 2H`z—¸Û/`”Ð`º%£8â˜=•‹[ – Ù ÿ ˆ   Y /Å4ûÁpÔ´Jü—+ƒ›eÿéÿÉÿÿÆÿDþ,ý*ûðû.úãúäû%û3û;úÉú³úGúùü¶ý’ýáþÎÿ|ÿ‡ÿšþ…ÿÿ“ÿÑ]µsÎc–¸ÉËó§uIÄtSug0 &" â¤NåxЩ¨Ñ(qÒïôäðÿÏþ¦ý°ü÷ü|ü4ûüü"û`ûCûý[ÿAÿéÿêÿšþúþdýÊüëûÉúfù!øŒøÊøîøºø)÷âøµù½úTú©úÚúùú”ù:÷Qõ¼õ~öõôõ¾õ§õ™õ‹õØö®÷›øøwøÛùDù©ú údú·ûûMûûÎü üEü}ü³üçýýJýzý©ýÖþþ/þYþƒþ­þÖþþÿ'ÿNÿtÿ™ÿ¼ÿß->Pcuˆœ°ÄØìÿ&:Pg‚¡ÄìJ¼þH›ûmò;ñšëÙ   € à ^ ö D ® ‘þì0 4õp£ËVfREÿnþéþÆþÆþ3ý½ü\ûNúËúàû$û”üûKúðúÕûXûÂüáý×þÿ9ÿø‹†`„“²æ+{ÎdœÃÚàÛÏ¿«²ŸïvkŸÆæ(:4Üfª÷V×}F11Gg¥-žîNÿ†þ•ý•ü¶üûÂû¾û”û3úvûü]ýõÿgÿ‹ÿ™ÿGþVýÏýZü–ûuúøŒø2øNøŠøk÷ü÷Èø®ùÍúúœú¬úÛú"øbö(ôôúõÌõ×õ}õ7õEõ‹ö÷!÷ÖøNø{øÐù2ù•ùõúOú¤úóû<û€ûÁûÿü:üsüªüßýýEýuý¤ýÓþþ,þWþþ«þÔþýÿ%ÿMÿsÿ˜ÿ¼ÿÞ/ATgzŽ£¸Íáô,>Riƒ£Ê÷*bŸâ*zÔ:±<ÛMÔ G 6 G Ä à ü L  _ ’Ã-Þô¸Õ^¶Š›„ þ ý–ýKý$üÜüûAú(úeú¼û(û®ûÔû^úúàûiüFýIþ•ÿÿȹTÄÍœ^?>[Ôf¤ÓîøóæÕ´¦ JìÈ·<ŠyH@N]GKq¾1Èw8Ý¡bÿÿÿîÿˆþžýQüû^ûûûúÊú‹úyüýùÿ 9AÿãþðýÙüöü–ûÓú øâøbøƒø…øVø$÷ÿøøúúeúUúMú#ùw÷“õCó¯ô]õGõ?ôÅô®ô©õCöN÷øSøHønø¼ùùùßú:úúàû+ûqû³ûóü0üjü¢üØý ý?ýpý ýÏýüþ)þTþþ©þÒþüÿ$ÿLÿrÿ—ÿ»ÿÞ 1DWl€•ªÀÕéü.>Oc|œÆù4uºT« wò€"Ù¢u # e ¤ m  © µ ð ® — R É’¬QVCŒï‡ÆF&aýÇüGûäü!ûÃû-úNùõùýúzûûAûú6ùŽùjúOû›ý*þmÿeEâ<‚ è´Þa¦á ÿçѾª¿øöØX½òMuS1Ð̉ef~Ê6³:ÿÄÿMþÞþwþ£þúÿœÿÕþÆüþûQú=úúUúˆúŠú|úÿü)ýÁÿµÅ3øþÓý¬ý ü0úÏù„øúøöøÜø¢øø÷ùqùôúùÙù€ù[ø5ötôhóbóìô¥ôôô ô8ôçõ²÷ ÷¾øøGøžùùfùÈú$ú|úÎûûaû¥ûæü%ü`ü™üÐýý9ýjý›ýÊýøþ&þRþ}þ§þÑþúÿ#ÿKÿqÿ—ÿ»ÿÞ!3F[p…›±ÇÝñ"/:DRgˆ¶ñ7ƒÓ&}Ú@±0Ádæ¿ ƒ ñ û µ Ê Ñ L *  ¬ F Mˆ# ˆPÙ¢d*R!þüÛüqûïûéûUúgùáú$úúQúêùêøûø÷øCúUüÎþ€ÿ5ŠVû#8|äæ K”Ù'W[-ýÝ욎žñ”¥+éoZËhònlr.+ O™ÿîÿDþýÒý!ü¸ü´þMþÌÿbþÊüåúÞùrùYùÎú&úNúœûLüoýæÿZVAAuÿý¹ü†úÓù¤ù·ù»ùeù@ù€ù¶ùûú!ùîùløÊø=÷FõjóÂó7óªó¹ó~óBó¥óðôfõDö~÷:÷¦øøyøãùKù°úúhú»ûûRû—ûÚüüVü‘üÉüþý3ýeý–ýÆýõþ"þOþzþ¥þÏþùÿ"ÿJÿqÿ–ÿ»ÿÞ"5I^tŠ¡¸Ïåù %-003@_”Ü1‹çD¤tékþ¡Wï ¸ P o   ã.²| D  ¾]Ž _¥(µJ6mþöýÌývüÑûÑû;û&úvùÎù[ùXùX÷tö¼ö×÷“úüœý™þ¤x_ikÜw•éê_¸;¦häéo?üÖÞ%ÈÖ©ÏÕgá,Æ™D'sœÃÿúÿ4þbýyüpûMú—û4üfý‘þþ)üÂú®ùzù&ùyùÒú,ú£ûÓü þ þÁÿÒg0¦4ÿšýíü§úqú$útúMúùÆúúsú“úqúùTøy÷Æö¢ôÐóxóOóxóGóó?ódó‡óÛô±õïö·÷N÷×øQøÄù0ù˜ùùúTú¨ú÷ûBûŠûÎüüMüˆüÁü÷ý,ý_ý‘ýÁýñþþLþxþ£þÍþ÷ÿ ÿIÿpÿ–ÿºÿÞ$7Lbx§¿×í(*$þW·%‘ûbÊ4¥¤8Ü‘S  é ˆ ü ‰ c €L~ËtC Û ¸ Y¬d’Üø9 å+†E†”ÿhþ…ý³üåüXûòûùäøßøÆø^÷{ö¾÷2ø¶úåûëü¸ýâÿTyÖa+dß°ºóOÄ/LéÒδš€b8ïpµw神¤¨Í«õGý0ÿcþý¤ü‘ûEùºøsøˆùäûûìüyû£ú[ùù-ùqù|úûüEý¢ý_þ7þåÿ¨§fÿÚþü7ûfúDúÇúÌú™ú^úÃûMûkûú}ù´ø‡÷‘ö!ôóxóMóTó!ó ó=óeóOó:ô@õö_÷ ÷ªø/ø§ùùùäú@ú–úçû4û}ûÂüüCüü¹üðý&ýZýŒý½ýíþþIþuþ þËþõÿÿGÿoÿ•ÿºÿÝ%:Of}•®Çßõ &,(üΞ¨ûŠ˜€ï`ÕSÛqËŽ \ ( Ý ú  ߺ'/«Þ² ² KªÎÚaP«ž†·“yvÿ…þ°ýçý.üZûmúWù†øêøtøø1øcùŸú‘û³ü&üÆýÛÿ´¢R'‘®U5Rž¨>GÐ{|vfH&Ö4ËœÌ1Ü2ñ‹ö ñASOFÖSÿŸþÝþ ýûìúwøŸöÿöüöýøZùJù}ùƒøªøÂù&ù‘ù¬ùêú¸üýlýBýfþþÒÿ€=°ÿíþ¤ýyü…ûàûÞûåû-úäûrüRüƒüû5ú=ø–öüõ­ô$ó~óKó,ó òøóQó¥ócópôDõ„ö4öé÷‹øøùùmùÑú.ú†úÙû'ûqû·ûúü:üwü±üéý ýTý‡ý¹ýéþþEþrþžþÉþôÿÿFÿnÿ”ÿ¹ÿÝ'<Rj‚›µÎçþ#/3,ì¢K0¬e¥' ‹…©PÏ ¦ „ N  ) ÙµZÈf•ßl “þPüÕt±ÿ`‚ÈeDb—ÿÐþôýòüÙûÚûú5ùhø¸øxø€ùù¥úû$û°û¤üýÃÿÆF…IJr~´I|…0-2½¦yê6† `D¡[HŸ\©£î‹›)ÿ²ÿþqýªü¼û“úø@öcôÞõõö ÷5÷1÷÷øù9ùåùˆùtú ûJükü‹ü«ýDýÓþeÿÿaÿfÿþðþôþCýü®ûvûRû÷ýý¹ý_ü-úƒøµöÄôÖóªócókóBó ó óŽôô/óÇô¡õ{ö;öà÷{øøøñù]ùÁúúxúÌûûfû­ûñü1üoüªüãýýOý‚ý´ýåþþBþoþ›þÇþòÿÿEÿmÿ“ÿ¹ÿÝ(>Un‡¡¼Öï.;?7ïœÿìkg#¾FÃ<µ2¶CÞ‰D  ù ò þ ÿ ë™nJ5ü«ž‰í ü p—[?ï`œ¬í~Û`Û*;þæýüSûµúåù¡ø¨øø4øÕùéúŸûúÊú&ú”ûÐý²ÿ&ÿ*ÿNÿÿ_ÿ”ÿè]ò¨mÎè¢Ð#†ÿÇÿSÿù†m„ë4}b€ô,ªÈÿœÿ/þ´þ$ýuüœûŒú4øögõ ôŒõ õBöbö8öÛ÷êøÎùKùEù ùpú‹û ûYûòünüÙýDý·þ4þ©ÿ2®kþ–ü‘ûOû\ü2ý•ÿBÿ ü¼úÅøÞöôZó*ó3ópóDóóPóÝôˆô‘ô•õ õªöLöè÷w÷úøsøåùPù´úúlúÀûû[û£ûèü)ügü£üÝýýJý~ý°ýáþþ?þlþ™þÅþðÿÿDÿlÿ“ÿ¸ÿÝ*@XrŒ§ÂÝø';IOK7 ÅJÿ}³˜Lålêdß]ãs¾~ U K { ¿ ü_ ÷ä6~µŽ–^ œ N"Ù5éƒM˜JÚG+â0þ|ýLüCû9ùÓø`÷™÷–øªùþû@úáúù+øÖúûäüÙýRýý þþþûÿ~Íç®§µtV¢”ÿrÿ3ÿ}UaÛª«Zq¯KÜÁÿþÿ€ÿþÄþgýöýiüµûÎúªù<÷²öIõæõÏõòõ©öcöå÷ôø¡øëøÉø«ù^ù¬úkúìûOû®ûéûüügýþÿ‰ÌïþÅü+úþûPü)ý‚ÿAþ×ýúÑøçöbó÷ó"óEóFó+óóqô,ôêõ|õoõyõéönö÷÷{÷øønøÝùGùªúúbú¶ûûSû›ûàü!ü`üü×ýýEýyý¬ýÝþ þ<þiþ–þÃþîÿÿBÿkÿ’ÿ¸ÿÜ+C[u‘¬Èå3IZef[AÅÖ1ñŠ™‡ @ï´ ‘ “ Ô |Z°\É+ â¿ß ø gëð  ƒ²žv!ÌiÙ •£Æ”ÿêýîü¥ûpúød÷•÷øMù½úðú½ù¯ø]÷•ølú9ûƒûtûRûÔüîý‡ýÿþ‚ÿ ÿ׆÷¦P‘žœ‰`ÿ¸ÿ´ Þ&ï)Ûb¥kÿ–ÿþÉþ–þgþ/ýçý…ýüNûhúQùø ÷FößöuöBö²÷øSøÿø®ø\øhøðùèú]úÄúöûûúüúØüRýþ™9geþ&ûªúÙûMûîüÌýYý.üú™ø©ö=óÜódóóTóòùó¤ôkõ<õÝõÕõÔöö÷ ÷„÷ûøløÙùAù£úúZú®úþûKû“ûÙüüZü—üÑý ý@ýuý¨ýÙþ þ8þfþ”þÀþìÿÿAÿjÿ‘ÿ·ÿÜ-E^y•±Îì %@Xl}†ˆvw˜æVÔPÉ?¶/¯6Éjá Â Æ ZsÊýíœÄvŸï ‚ â , T ' còÜ(ìâÑftê“øÌþ³ýû§ùùør÷v÷T÷Îùúúù•÷½ö÷=øeù½ú0ùîúñû÷ü¤üÿý^þ þÓÿž#`mßUt7Äfÿî H••nZüÿåþ°þAþþ þþþ ýñýÁývýü_ûŒú£ù¢ø¸÷ê÷Qöõ÷)÷˜ø ùø¿÷®÷Åøzù`úUúÉúwúzú^ú"ûûèý þ"þäÿ¦ý;û–ûGû`û§ûëüû¸ûúøõlóêó‚óŠóRóóXóõô´õaõÍõÔõõöHö®÷÷øønøØù=ùžùûúSú¨úøûDûûÒüüTü‘üÌýý<ýqý¤ýÖþþ5þcþ‘þ¾þêÿÿ@ÿiÿÿ·ÿÜ.Ga}š·Õó0Mh€–¨¶ÁÎæY´‰ùiÝUÓ[íŽ@  å å JSÙñߘ܇Q<nã% c  2š  5—ÁF­nNÙNþ§îÿ¼þ#üCúJø§÷Vö”÷«øSøÅùø±öÌõõö‰÷ƒøÉùaù†úû~üûÉüüÐýÑþÏÿ«Xý¨ëýEW•ß6ÿðÿÃÿ´ÿÿâsðÿçþ>ý@ü§ýýUý ýØýþþþþ ýÿý¡üôüû!ùÔøåø*÷Œöö÷ø6øÆø™÷Ö÷1÷¡øÂùŸùùúùßùñúiûûôü±ýþÛÿiÿýƒüMûÆûŽûtûlûZû úvù‡÷–ôÓóólóuó4óóyôJôèõcõ¦õ¾ööaöÅ÷0÷œø ørøÙù<ùœùøúOú£úòû>û‡ûÌüüOüŒüÇýý7ýmý ýÒþþ2þaþþ¼þéÿÿ?ÿhÿÿ¶ÿÜ0Idž¼Ûú:Yw”¯Éáú<o±\¿&‘wõ{ ­^ ! ü ò  -I¯øÃväâÛËû~ß ‡ : ¨y ±‹w¥x”ëÛ}¼©»› ÿbýOûùc÷Ì÷B÷â÷þ÷òø÷\ö‰õáö±÷ÐøÑù$ùPúûû,úúmûrü×þ1ÿm—gÏ»Æá©E{|ÿÈÿ>þIþ þ©þüÿgÿ;þ`üÂû©û”üüÈýKý´þþDþvþ§þõÿ1þ<üõû¤úuù†ø÷Ó÷‡÷›øøPøsø/÷¦÷žø@ø½ùMùbùîúúXûEûöü”ý=þ:ÿDÿþüþü<û«ûRûûúÝú4øÁöžôIó3óGóPóò÷óŽô)ô³õ%õlõÀöörö×÷?÷¨øøxøÜù=ù›ùöúLúŸúîû:û‚ûÈü üJü‡üÃüüý3ýiýœýÏþþ/þ^þŒþºþçÿÿ=ÿgÿÿ¶ÿÛ1Lg„£Ââ"Df‡§Çç)O}³ó>“îO·$—™*Èv 5 ô ö ðpâtÊïïæºœ ý ˆ!dj û ¦¢hžDt¸R‹qÜ>þ ü;úžùøîøƒø+÷öî÷C÷-÷÷Žøxùù6ù†ùÁùÆù)øŒø¥ú ûøý¼ÿ]Þ=^<ù¸uJ¥ÿÒÿýíüûýšþMþþ"ý)üúrú½û§ütýý­þ#þ…þÝÿ7ÿ¶ÿîþ³ýfü-úöù²ø¦÷ð÷âøø5øsøwøƒøøJøjø|ùsúBúÒû#ûûÄüüzýDþÿÿþýsülû«û!úäúÁú¦ùÏ÷ÚõóDóó]óWó ó9óŒôô‚ôãõEõ¸öö€öæ÷M÷´øø~øàù@ùœùõúKúúëû6û~ûÃüüFüƒü¿üøý/ýeý™ýÌýýþ-þ[þŠþ¸þåÿÿ<ÿfÿŽÿµÿÛ3Njˆ§Çè *Mq•¸Ü'O|®æ'oÀtØC´/³BÞ‰ C  ï ã æ ÷#9Í>šÈôõO:TŠ;%ï) ƒ ßç).ŸDTéÍu~¸ªÿ=þü¦û“úÏúùø÷Ùø…ùùGùAù)øëøðøÕø3÷@öÙö®öÙøæûAýoÿmLÌþZ¶ö‰‡3ÿ_þFýPýRýÚþýüú¹ú@ú¤ûƒü`ýýÇþZþ×ÿFÿ°&ÿý‚ý3ü$úgùøŸø¢øIøÆøÊøÒùùøúù ùQúûüýýûþürüPüÔþ ÿ!ÿ¨þ¡ýQüQûzúÑúJúbùÃøÒö`ôòEòÓó¤óló@óNóšóøô’ôÌõGõ¸ö&ööô÷Z÷Àø$ø†øæùDùžùöúJú›úéû4û{ûÀüüBü€ü»üôý,ýbý–ýÉýúþ*þYþˆþ¶þãÿÿ;ÿeÿÿµÿÛ4PmŒ¬Ìî2V{¡ÈïBoŸÔP—ä9”ö^ÎHÊWñ˜ M  ê Ô Ô õF`$ÆÀÌð  £Ý—¹!¢ E Œ Å 7å)9}U3p%È2aÿˆþ†ý˜üúüTûzúŽú@úµû”û€úÍù–øo÷pöŸõtô[ôPõöø'úÝýNÿ–É`X~í<Z® ü2ÿ&þˆþ3þýÇüÍú¹ù9ùåúÝû°üýEþþ¬ÿ?ÿ´rsÿdþ«þ®ýBûôúîú€ú ùÏù®ù›ù±ú úùßùÇúTúÿü¦þ,þÔýñüßû³ûõüœý}þ”ÿþ üßûêûúcùµø·ø^÷4õò1ñzò^óiósó5óNóyóÒôôØõPõÃö2ö›÷÷h÷Ìø.øŽøìùHù¡ù÷úKú›úèû2ûyû½ûÿü?ü|ü¸üñý)ý_ý“ýÆý÷þ'þVþ†þ´þâÿÿ:ÿdÿÿ´ÿÛ6Rp°Òô:_…¬Õ,Y‰¼ó/p·W°væ^ßi¤ V  æ Ê Ê óY¸X¶ØÜÚ ãìö‘mq àb | ; A ¥ N Æ Zñ HX›vÍ5ÿ|ÿ"ÿ6þ{ý$üvüŽüíüaúôù÷:õ¤ôróqò]òóîõÖøú¿ýYÿÎ:ɼ  …à_ú‚·ñx„ÿÔÿJþÂýóü5ùÒøÚúû)ûþüÃýˆþPÿ&ÿÅ9yÉóÞÎÿˆþ¾ý]ü×ü±üiû×ûpû<ûCûnûpûúÕû½üÅýgþ¥ÿ@þŠüÄûÇû–ûÊýýÉýÅýü-û[ú¢ùñùøU÷öóœñjð§ñ¹òìó)óó>óSóGôôÚõgõ×öDö«÷÷v÷Øø8ø—øóùMù¥ùúúLú›úçû0ûwû»ûýü<üyü´üîý&ý\ýýÃýôþ$þTþƒþ²þàÿ ÿ8ÿcÿŒÿ´ÿÚ7Ts“´×úBgŽ·â<lžÓ I‹ÒpÈ&Œûqñz¯ ]  ä à À åG±IÔì>8ÿÁòèY¿$ _ — K õ ƒ  ú ÒîQ|ÎJ¦à2î(®ÿ,ýçýdüû~ú ø\öYô¥óò®ñ©òó‡õZøúáý‹ ˆ;g Ï ý\³SREZäê>ÿ¨þ·üýúÁúuúëû¼üoý!ýÜþ¤ÿ~oÉ|'¢°ÿUþ«þqþzþaýïý_ýüòýýüÁüÁýþ'þšÿÿ2þüû*û?ûáü­ýVüÑü ûPú¨úùƒøéø>÷AõYò’ðšðXñˆòƒòãòðóLóóFôôüõ‡õñöYö¾÷"÷…÷åøDø¡øûùSù©ùýúNúœúçû0ûuû¹ûúü9üvü±üëý#ýYýýÀýñþ"þRþþ°þÞÿ ÿ7ÿbÿ‹ÿ³ÿÚ8Vv–¸Ü$Io—ÁíK|°ç!`¢é5‡Ý;¡ƒ‰¹ c  â ¾ ´ Í3n¹fÀð•#&q¤è¶u€ À ” Ù  @ º &Nƒ¦Dì9Z¿4ð¹bþ·ýFûýú´ùF÷Íöô¸ô?óbó"óHôjõØøGû\ýÜ?£6R ¨ ðPRîÎ  ë` ÿéþ üïü"ü6üƒüýýþ7þîÿ½XÆÿJ°Ëy°ÿ¥ÿdÿ_ÿ†ÿmþÉþËþ>þZþËþ›þ,þþ¾ÿˆÿ|þ²ýûDútúÙû üZü¸ûÛúçúEùÌùnùø¼øö×ôÒòkð¶ð¾ñÇò‰ò±óó.óó`ôjõ.õ¨ööqöÓ÷4÷”÷óøPøªùùZù®úúQúžúèû/ûtû·ûøü7ütü¯üèý ýVýŠý½ýîþþPþþ®þÜÿ ÿ6ÿaÿŠÿ³ÿÚ:Xxš¼à*Pw Ëø'X‹Áù4s¶þIšñN³”–' j  â ¹ ¨ ±ÍåÙŽÊY½7­š VHzÿ¾i  AÿR Ð z  š í šN©=æK/ö)’ƃþÔýû—úaù÷xöØö<õÚö–ö/õÒõ™÷6ùÅüþKpŒÀ: bô}ð#…FÓÌ©rÿöÿ”ÿ¨ÿOþWý ýLýUý“þþ’ÿ4ÿÔdÔ)l”ƒ w+ÿÏÿÐÿüÿÇÿÿGþçþíÿÿnÿ!þÿÿ†ÿ2ýØûáúLùÙú2úñûÒû­úxùˆøôø¼ø¬ø®øšøöŒôoòÐòñüò2òbòìóWóYócô ôÔõfõÏö.ö‹öé÷G÷¥øø\øµù ùaù´úúSúŸúèû/ûsû¶ûöü5ürü­üæýýSý‡ýºýìþþMþ}þ¬þÛÿÿ5ÿ`ÿŠÿ²ÿÚ;Z{Àå 0W©Õ3e™Ð E…È[¬`Ä0¤£2Ì q # ä ¶ ™¥³¬€HŽ'´;®3iο{ô!µMÆ'ºR Û û \  ˆ [¡CV?'•þÕýû°úïù¸ùøÔøÏøËøîø—÷÷ÓøÂúÄüöþÙ¦Zþ¤‹©.¥TÚÿÄÿ(ÿ þ˜ýùý¹þgþìÿcÿþwþ>þþþmþéÿw[–®¢1l]3ÿÿÿ÷2ÿºÿþ¶þ²þwþÚÿIÿÿ+þ¯þü°úòùˆù9ùpú^úÎú ù÷˜÷2÷I÷âø?øf÷ßöNôSó8óDòÐò©ò³óNóÂóÕóâô†õ?õœõôöMö¦÷÷[÷¶øøhø¿ùùgù¹ú úVú¡úéû/ûsûµûõü3üpü«üäýýPý„ý·ýéþþKþ{þªþÙÿÿ4ÿ_ÿ‰ÿ²ÿÙ<\~ Äé6^‡²ß?q¦ÝT•Ø l½pÔ@²-°>Ö y ) ç ¶ — ŠŒ—”W½PÐI0”?òêÞ6ÎQÕUÆVC º ý £ à ´ ² f 2PèÝ6É+ÿ0ýøýü–üdûŠû^û#ûQûùüùœùÊú“üGþÿŒï+9øCŸUÑÿ;þFýÇýü]ü–ýþþ·ÿÿNþÇþpþxþÃÿ5ÿ»HÏG¥ãÿþÜBÄeÿîÿöÿÑÿZþ¢þý‘ýàþ*þ¾ÿ?þÇýøüùûÌúWùøñùhúbùçù0÷fõÈô’õòöû÷ÉøZ÷¿ö3ôgóÌógóLóóhóÔôUô”ô“õõrõËöölöÁ÷÷o÷ÆøøsøÈùùnù¾ú úXú¢úêû/ûsû´ûôü1ünü©üâýýNý‚ýµýçþþIþyþ©þØÿÿ3ÿ^ÿˆÿ±ÿÙ>^€¤Èî<e»éJ}²ê%b£è0|Ì#€ãNÁ;½Já ƒ 1 í ¹ • ƒ‚›ˆL…˜÷cÐ ù›kE Ø.¤çA‘àçôÚÍž& * „ 42ëürž§ÿÄÿkþYýóýfý\ýUý,üÁüqü”ý4þ*ÿSdV¦Úœ [$GþðýÎýü,ûnûºüùýpþ þÖÿþºþŠþ©þýÿpÿùŒ¤X„•lqÆÿ÷ÿíÿhþZýÓý“ýMýýlýÐþ@þ-ý3üIûIúùù%ú%ùêùRø!öIôHóWô~ö!÷Rø"÷Óö?õkôaóäó}ó¡óùôjôÞõLõrõsõ°õòö=öŠöÚ÷-÷÷Öø*øøÒù$ùtùÃúú[ú¤úëû0ûrû³ûóü0ülü§üàýýLý€ý³ýåþþHþxþ§þ×ÿÿ2ÿ]ÿˆÿ±ÿÙ?`ƒ§ÌòBl—Äò"Tˆ¾ö2p±ö>‹Û2Žò]ÏHÊVì Ž ; ö ¿ ™ …„˜ÃC*šúlå3Þžr%Ò>ˆÂ"€Ä¼C[#ô ® ¥ Õñ¿yD’­“ ›ÿ‰ÿ=ÿÁÿÅÿÿuÿ{ÿ¸-Ã[à@f/™¸|Öó¢ÿãþ¢ý®ü¾ûœûûyüüÑý¦ý¹ýÛþþ_þ±ÿÿ™*Ìt¦ý3I2öi|Þ‘Aÿgþý~ý‘ý}üðüÈü°üŸüÄüIûšûúùJùÇúù~ø†÷õTóòÁó×õbö£÷£÷€öžöõ˜ô†óæô1ô„ôàõWõ²õ¿õ¾õâöö\ö¤öñ÷A÷’÷äø7ø‰øÚù+ùzùÈúú^ú¦úìû0ûrû³ûòü/üjü¥üÞýýJý~ý±ýãþþFþvþ¦þÕÿÿ1ÿ]ÿ‡ÿ±ÿÙ @b†ªÐöHržÌú+]’É>|¾L™é@kÜV×cù š G É ¡ Œ¨èXî¯@žÆ;]üå©PbôuÛ-‹3âÑ3 ªÜ ¦ ‹²Kz«D!µ¸„ð‡pÃg ‚=ÿ:jŒy?§µÎ·jÿ¬þœý¾üßû¾ûûDû§üüJü•üªýpþþŸÿ&ÿµT ј^óêö1&Ó‰H-þþþCþyþýƒü©û¡ûvû‰û.úÍúzú]ùøù«ùø÷+õñô„ó òœó£õö ööÊöiöËöSõUôÉô»ôöõCõ–õÆõ»õàöö9öwö»÷÷R÷¡÷ñøBø’øâù2ù€ùÍúú`ú§úíû0ûrû²ûñü.üiü£üÜýýHý|ý¯ýáþþDþuþ¥þÔÿÿ0ÿ\ÿ‡ÿ±ÿÙ Bdˆ­Óû#Mx¥Ó4gœÓ IˆËY¦÷Mªxêcåp  § T Õ ® ™™¶ùxÞ:~æg1à°“w$mŒÞF¿T ÍG õ¥‰¼ Î Ÿ ¤ßæ ‰ U„_¾[ÛÖ[»`î€&㲈W ®§­[K¯ÿáþÝýêý%üpûdû$ûGûdûvû³ü/üóýÏþ‡ÿ-ÿÒ›P.Çž‚î‘$í{ü>ãÞŠÿ}ÿþnýDûìû]úÓúùÇú"úLúJù«øº÷õçôµó¹ò¼ò½óÔõõìõÞõ¹ö2öDö§õÖõSõ;õOõ†õÂõÃõÔõïööPö‹öÎ÷÷`÷®÷üøLø›øêù8ù…ùÑúúbú©úíû0ûrû±ûðü,ügü¡üÚýýFýzý­ýßþþBþsþ£þÓÿÿ/ÿ\ÿ‡ÿ±ÿÙ!Cf‹°×ÿ(S~«Ú <o¥ÝT”×f³Z·…÷qò~  µ b  å ½ ¨¨ÃýT³ÃšNÕLºê%÷ðÏrÍ U¸9áÑ¢°}’¨“ s _  À ¬ V ã y Ñ HIÊk¦Y—Ù1§&´B®O*-Q¿³6þ÷ýëý>üwûsúõúêúâúÌúÙû¦üªý˜þsÿ:ÿüÅŸƒzw5WG@œTAø·ÄôG’ÿºþ‹ýû ú^ùø‰ùÄúŠúLùjø$öZôgó¶òàòËóWô;õCõæõ¿õ¤öö_ö"õÞõ“õyõŽõ¶õÌõÊõÙõûö&ö\ö˜öÚ÷!÷k÷¸øøSø¢øïù=ù‰ùÔúúdúªúîû1ûrû±ûïü+üfü üØýýDýxý«ýÝþþAþrþ¢þÒÿÿ/ÿ[ÿ‡ÿ±ÿÙ"Dh³Û-X„±áDx®æ!^žâ(r¿gÄ(’~Œ " Ä r - ö Ï ººÑMžØ+×G§7zÓòùëõp©Ô' M?[vœtNLdŠ ü G · ÝÓ‘ S Ú è – € à Ò z Ò Z F 1]•ãQ ûN0‰ð È-nþÏý•ü¨ûëû2úÑú®ú]ú&ú!ûBüiýqþeÿJ* ùÖ¶Æ¾é ¬]=‹ÈK@DžÿìýÅûœù¡÷õ÷¬øìú ùÕøø÷Áõ¢ôòÏó ófó÷ôÌõ„õàõÅõÏöö7õüõÀõ‘õ{õœõÐõÈõµõÉõóö%ö^ööá÷(÷r÷¾ø øYø§øôùAùŒùÖúúfú«úïû1ûqû°ûîü*üdüžüÖý ýBývý©ýÜþþ?þqþ¡þÑÿÿ.ÿ[ÿ‡ÿ±ÿÙ"Ej¶Þ1]‰·çK€¶ï*h¨ì3}ËsÐ4Ÿ‹ ™ 0 Ó ‚ =  â ÎÍâX¹"‹AˆRÃò™Tó¥¶$s9>Z–üšu'ütB8óO9CâùÈ‘È+ µ U D « Ž Þ ¸ G  QÄ-QÀJ˜‚m3þ7üàûòû?úÿúÚúŸú"ùwúûü?ýSþZÿYSICJúÛ¡¨)~õO‹_l70qÓd‰±ýûúêø]ö”ö•øZùøßø÷/õÏô‚óÝó¶ôôˆõ9õèõÞõ«õäöõìõÔõ õgõ=õ>õõWõiõ õÝööYöœöâ÷+÷v÷Ãøø]ø«øøùDùùØú!úgú¬úïû1ûqû°ûíü)ücüœüÔý ý@ýtý¨ýÛþ þ>þoþ þÐþÿÿ.ÿ[ÿ‡ÿ±ÿÙ#Fk‘¸á 5a޽íR‡¾ø3q²ö=ˆÖ'Ü@«˜§ > á ‘ M  ô áâ÷%oÚ_ûšúž®n)êNÿ–ŒóúÿNÖ€Gͺå‰,úw¹Õ®-—28Ÿäó–ò& ªE Ø   ¿ /ôqÊ|¯JRèÈÿCý:ûÍû8û úóúÔú¾ú=ù‘ú ûü!ý5þKÿ`q{‚kV]‡¾W½Y`C¢ p“×ùkNý)ù¬÷köö?÷Žøaø!÷ öäõîõ$ôžômôŠôðõoõ×õ£õ£õúöõáõ°õõô­ô{ô,ôtôæõeõ½ööNö•öß÷*÷w÷Äøø`ø®øûùFù‘ùÚú"úhú­úïû1ûqû¯ûìü(übü›üÒý ý>ýrý¦ýÙþ þ=þnþŸþÏþÿÿ-ÿ[ÿ‡ÿ±ÿÙ#Gl“ºã 9e“Âò$YŽÆ<z»ÿG’à2ŠçK·)¤'³ K ï Ÿ ] )  õö=‰ø‹Gó4Ø—J„ÿY^лiaš «[<Ôy¼7š¼fÎmUtlï ;^’ÚÌ})ùg ¤ z Z ¸¤¹ØpAoÍ´ÀYýõû÷úÇú”ú¾úíúòúéúˆùÑú#úþûúýþ3ÿ_Ь¸«°nk€®.²×M2_¿4ÿrþÆûÛù3öúõÌõ»öâ÷\÷Y÷ö„õîõbôúôÂôÄôüõVõôÂõLõÔõéõ£õ§õqôÀóñóSógó–ô„õ)õ˜õîö=öŠöØ÷&÷u÷Äøøaø¯øüùHù’ùÛú#úiú­úðû1ûpû¯ûëü'üaü™üÑýý<ýpý¤ýØþ þ;þmþžþÏþþÿ-ÿ[ÿ‡ÿ±ÿÙ$Hn”¼æ<i—Ç÷*_•ÍDƒÄ P›ê=”òVÂ4¯3¿ W û ¬ k 8  "T¢©qEN]Ú¡a¹¯‰Ö £ÊÄß>ÑŠIíˆ&/àâÙQÈ_)ÖU¤!1ä«;^~‚ Ÿ Ž H z 6üìõ˜þ:oÿ[ý.úùúúúXúŸûúýú°úúúÀû¶üÕþ ÿO¡ëùÆX›¾¿™"†x{rŠŠ Í¼ýÛû5øMöô—ô£õžö{ö³ö•öHõâõ|õ&ôäô¬ô•ô9óÈôAôðõtõÅõ˜õƒõôdóxóóó¡ôOôüõsõÓö)ö|öÎ÷ ÷q÷Áøøaø°øýùIù“ùÜú#úiú­úðû1ûpû®ûëü&ü`ü˜üÏýý;ýoý£ýÖþ þ;þmþžþÎþþÿ-ÿ[ÿ‡ÿ±ÿÙ$Io–¾è?m›Ëü0e›ÔKŠÌY¥ôGžü`Ì?º=Ê b  ¸ w E #3f¶%¼‚2±~šyiRÖí¢ $ Æ í Ÿ "iòŸ[G!ÓƒKt§‚ Žö` H™—õûBcœ ‘ C } ;êÍ®âhµ|þÊüÕúäùPùoùîú}úãûú›ùÐùŽú.ûMü‚ýÂÿ¢?˜kÒúÚËím¤M™av‚¯ã7_ÿü«ú÷Sô´ó¥ôBõQööZöTö"õØõ‰õ;õôƒóÂóóô-õ;ö7öjöRõmõó÷ó[óóó®ôOôÛõRõ¸öömöÃ÷÷k÷¾øø`ø¯øýùIù”ùÝú$újú®úðû1ûpû®ûêü%ü_ü—üÎýý9ýný¢ýÕþþ:þlþþÎþýÿ-ÿ[ÿ‡ÿ±ÿÙ$Jp˜ÀëCpŸÏ5j¡ÚR’Ôa­üP§iÕHÃGÓ l   O . %?sÂ1Äw9ßF +2 / í ¬ Ø ê!J!m!l! !4‡ ¶€r¼Qõ0¨º®/[±¹°çH±ÓùÜ £ G  š ¤u+ï›ï6Ãÿàþ‚üÖúÕùø¯ùÇú¸û%úûúmùøxù`úÉüýHþ–p_Íx€xl‘ÿðÿsþÝÿ(—êÇ^Mý¸ûløàö·ôóÌôÍõµö(öJö;öõÔõõ`ôñôŠó)òÌó–ôö¹÷ÒøG÷¥ö¹õôó0óóKó·ôAôÁõ4õžöö]ö¸÷÷e÷ºø ø^ø®øüùIù”ùÝú$újú®úðû1ûpû­ûéü$ü^ü–üÍýý8ýlý¡ýÔþþ9þkþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%Jq™ÂíFt£Ó9o¦àX˜Û iµX¯ qÝPËOÛ s  É ‰ W 6',FzÈ6År?!€ž±à Ð!¨"!É!Å!’!§!‘!j ã 0–Ï¥¥Õ6·  NþNLf€Ó=y¢ð·ã !ô¦;¨i ë s [ ƒ èI¬A´Ý‚ÿ¸þýû;ù2ø–ù§û;ûlúýùåø†øøâùõûðü˜ý–,Ž–¹I¼Ýžÿ’þÕþ0ýrüýý÷ÿ[o¸ÿõþ×üŒú ø&õ˜ôÅõõÖö]öpö`ö;öõÓõ¬õLõóóóxô†ödøùáúKøòöƒõóÓóóóYó¹ô-ô¦õõ†õíöNö¬÷÷_÷¶ø ø]ø­øüùHù“ùÝú$újú®úðû1ûpû­ûéü$ü]ü•üÌýý7ýlý ýÔþþ9þkþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%KršÄïIw§× =s«å ^žá'p¼ _¶xäWÒUâ z  Ï Ž \ 9*.HzÇ3ÀnA!ãÒé '!A"3##"f"!!·!„!o!R! … +ðÁ»Û  j Ø!˜!’!‡ é…CVÚ³Ã>5ûTK[ú'0 Ž S † ¤¤n= Ä•šÉÿîþÙýšûçú øÞù‹úÀûrúõùåøÇøWùdú‡ûïüýmÿùTe² MYÿÑþvýóý[ü¢ûóüý ý“þ0þý$û)ø®öÊö@ö öŽ÷1öýöÀö…öFöõÑõµõ{óúó+óÄôÏöc÷Óùeútùž÷ÇöôÅómóòýó8óžôôŒõõqõÛö@ö¡öÿ÷Y÷²øø[ø¬øûùHù“ùÝú%úkú¯úñû1ûpû­ûèü#ü\ü”üËýý6ýkýŸýÓþþ8þkþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%Ks›ÅñKzªÛ Aw¯é%c¤ç,uÂe½ê]×[ç ~ ! Ñ ] 9)+Ct¿)´c5,ÎY !•"¦#Ž#¦"å" !­!j!e!!n!g!E! Ý Ê Û! !X!Ë!ô"µ#1"¢!P´‚ŒX8PäÙ@U-£²r S 4 g ©¸¥†t~ut`hÿYþü³úÖùù úgûXúçúùyù·úÃü'ýýTý¤þy)#· õ~[’ÿfþ!ýGüšûòûzû û9ûÅü]ükû‡ùñ÷áöz÷÷z÷Õ÷×÷÷ ö«öRöõËõ³õ?ô/ô9ôâö[÷Âùù“ù ø"öŸõrôóòNòwò÷óuóöôtôíõ_õÍö5ö˜öø÷T÷®øøYø«øúùHù“ùÝú%úkú¯úñû1ûpû­ûèü"ü[ü“üÊýý6ýjýŸýÓþþ8þjþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%LsœÇòN}­ÞE{³í*h©ì2{Çkà „ïaÛ^ê € " Ò Z 6#$:h°ŸJ}Ø!!è"Ô#¶#ñ#["9!!j!u!—!î"~""T!þ!Û!à" "d"Õ#c#¼$#¡"N ÆRß¡u?úáõˆœ[˜Ð— s ' £ ö ùäÖ÷(×Òÿúþ½ý úéùøüúAûúåú-ùÜú³ü3þþgþþ%þÞÿê¼NFêfÿïÿZþ{ý˜üÆüûúÚúú^úíûiûYúÐù`ø1÷µ÷Ôø‹øOøc÷Ê÷CöÌö^õøõ¯õ€õ2ô÷õÒöæø øíù1ø´ø÷õîô³óŠòRñpñàò¬óKóÚô_ôÜõQõÁö+ö‘öò÷P÷«øøWøªøúùHù“ùÝú%úkú¯úñû1ûpû­ûèü"ü[ü“üÊýý5ýjýŸýÒþþ8þjþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%LtÈô!P°áI·ñ.l­ð6ÌpÈ%ˆòdÞ`ì € ! Ï ‹ U .+Všý€%ìÚɬ "!W"6"î#—$#ç#%"0!À!¸" "œ#’$##!"ï"ì##|$$ø%u%T$#S!–÷¾Kæ³Oéþ瘣éåIð I ø ] œ  {W-/ì tÿHý2úÈøèù0úEû úãúdúOû\ýþºÿþýùÿXÿRÿZÿêÿâÿŽÿþ•þýbüÁü'û{úòúiúú2úÖûúÑúiúZøðøgøƒønø‡øG÷ô÷möéöiõôõŒõ8ô£õÚ÷Kø¬ù¸úøû÷å÷`önõ8óíòÓñ†ðÞñªò€ó.óÆôPôÏõGõ¸ö$öŒöî÷M÷©øøWøªøúùHù”ùÞú&úlú°úòû2ûpû­ûèü!üZü’üÉýý5ýjýžýÒþþ8þjþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%LužÉö#R‚²äL‚»õ1p±ô:ƒÐ tÌ(‹õfß`ë ~  Ê „ L # =~ÚVó¯ˆl :!¡"o##˜$ $K$!#}"c"O"É#E$$ä$±$<$#ú$%$%I&f'ƒ&ì%ì$z"u áD­g ËŠs6 gÑ”•Œ – ¤ ™ [ #¶{ö*ÁìIþÖüÖúoøòùmúiúýúèú¸úüûÆý9þÎþÇý&ýAþPþaþþ¿þ»þkýòý_üËüFûàû{ûú¶úTú<úlû`úîúœú9ù³ùKøÆøø|øhøCø÷‹÷öwõ÷õ‡õõ!öøNùáúèúfù÷ÔöÚõÃôªó.ñßðíñ2ñ¹ò|ó%ó½ôGôÈõAõ³ö ö‰öì÷L÷¨øøWøªøûùIù”ùÞú&úlú°úòû2ûpû­ûèü!üZü’üÉüÿý5ýjýžýÒþþ8þjþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%LuŸÊ÷%T„´æN…¾ø4s´÷=†Ó#wÏ+öfÞ_è {  à z @  úñýZ¯#¶f5!5 .!Á"â#f#Ô$/$©$ö$h##"#Â$‘%%´%¥%W%%%*%”&P'w(™(‚':%É$-"+ ~è#¼… åþ*)Ü­Ëø&@ ý Žù¨J¶Š'sÿ´þ$ü~úœùŒùïúšúÿúæúíû8ûÕüÕýìýÕüÅüüýýdý±ýâýÒý…üýüLû}û&úìúôú újú‰ùãùèùýú¬úù¢ù|ù ùø°øøkøQø ÷§÷5ö öõ õQõé÷eù<ú úÀù øƒ÷Iö1ôûóbò^ñNññ`ñöòó,ó¾ôGôÇõ@õ²ööˆöì÷L÷©øøXø«øüùJù–ùßú'úmú°úòû2ûpû­ûèü!üZü’üÉüÿý5ýjýžýÒþþ8þjþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%Lu Ëø&V…¶èP‡Àú7u¶ú@‰Õ%yÐ,õeÜ[ä u  ¸ m 0  ã×ßû/}ço×¾Ó !©"è#Ô$$„%%ª%t%P%%‡&&f&›&ž&[&&&(&Œ':(5))<(¿'f%Î$!"$ [§«*á:i‰Š‘â}P× ) Z zäaàO8´ÿcýÖüpûUú½ú úâûúèúçûû†üü ü­ühü0üwüÈý ý:ýLýülûuúoù›úuú/ú2ùíù]øßø÷gøçøõùùPùÇùø¢øvø[øcø ÷À÷€÷!öCõÐõÏö øÕùýú<ù¡ù)÷pöTõ!ó»ñŸðãð¶ññ–òò­ó=óÉôMôËõBõ´ö!öŠöî÷N÷ªøøZø­øþùLù—ùáú(únú±úóû3ûqû­ûèü"ü[ü“üÊýý5ýjýŸýÓþþ8þjþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%Lu Ìù'W‡¸êR‰Âü9w¸ûAŠÖ&yÑ,ŒóbØVÝ m  « ^  ì ʹ»ÒþD¤ ¸nHNT!Y"Ã#„$Z$è%’&&‰&ý'!'A'’'Õ'•'5'&î&ð'#'}((ñ)Î*Z*)O'ê%ì#ë"q ¢ã&eBëà $÷‹úhà ÷ è `ìræ*Ã-þ€ýYüRû¦ûOû'ûúÝú¤ú¾úìûiû¹ûºû‰ûüüÞý#ýüÙýjüGúÒùäù%øîù‡ùjøÞø2÷öUöUöÀ÷¥øù ùEøÕøxø;øUøEø÷×÷É÷›ö²ööö÷øTù‡ùmøè÷íöäõŽôDñÔðÓððeññ¶òDòÌóTóØôYôÓõIõºö&öŽöñ÷Q÷®øø]ø°ùùNùšùãú*úoú³úôû4ûrû®ûéü"ü\ü”üËýý6ýkýŸýÓþþ8þkþœþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%Lu Ìú(Xˆ¹ëT‹Ãþ:x¹üB‹×&yÐ+Šñ^ÒOÔ b ú œ K  Ò ¬–’£ÈZÉTûÁ¢  Ÿ"m#Ó$œ%U%ï&˜'g(?(Û(É(ó)$(—()'–'y'Ò('(|))ü+ +Ä,+)Æ'Ë&$:"º Ã÷.D ;ù›Xhr¿ 6#¤]MÍ̼þÿ½þCý1ü`ûÉû]ûúÏúpùÃúZû ûLû+úßúÀûÀýxýÀü×ýUüéü úªùø øNø~ø…÷½÷*ögöQöyöÑ÷ öþ÷«ø=øoøVøRøkø/ø÷ûø!÷ï÷4ö<öö«÷¸ø{ø÷ù÷õÕôûòÒñ$ð‡ðtð½ñGñßòhòëómóìôhôàõSõÂö-ö”ö÷÷V÷²ø øaø´ùùQùùæú-úrúµúöû5ûsû¯ûêü$ü]ü”üÌýý7ýlý ýÔþþ9þkþþÍþýÿ-ÿ[ÿ‡ÿ±ÿÙ%Lu Íú)Y‰ºì UŒÄþ;yºýB‹Ö%xÎ(ˆìXËFÉ U ë Š 6 ï ¶ ‹ofoŒ¿ mé€2þâã"#¡$÷%£&D' () )Í)ü)ñ**)(Š(S(µ))}*'+-,‚-‹-},4*ê)Ø'ì&$M"¯ ó_zhßC¸g½£g“  ‚ Ä”@¶n&¥)hþöýËüÞü û„úüúÒúTù€ú+û?û”û&úKú=úÑüDý†ýOüÉüû<úcù6øl÷Ê÷ó÷’öÝöö·öà÷'÷ª÷öâöö÷øøYøLø[ø4÷øøø@ø9÷ö.õÒöA÷*÷æøöööõ óòkñð„ðÓñ&ñ•òòó ó‡ôôzôîõ_õÍö6öœöþ÷]÷¹øøfø¸ùùVù¡ùéú0úuú¸úùû8ûuû±ûìü%ü^ü–üÍýý8ýmý¡ýÕþþ:þlþþÎþþÿ-ÿ[ÿ‡ÿ±ÿÙ%Lu Íû)Y‰»í!VŒÄÿ;y¹üBŠÕ#uË%ƒçQÃ<½ G Ú w  Ó – fE57Lu´ y X+!##,$›%ž&r'Z(_)È*„*²*—*ë+‰+*d)¸)Ì* *+8,u./>.²-Q,:+')c'ú&e$¼#!¢þ©q ÍÆ¢­ôs J • °žp8}ÔÜ´ÿQþ)ý*üQû›û%úÙú‡úRúbûgü°ûpùÿøÓøÙúXüü—û§úûú8ù|øÙøP÷¹÷öÃö6ö>öæ÷T÷¤÷¿÷•öÔöò÷x÷åø5øGø.ø0ø,÷÷æ÷ÉöÝõþõ…õköo÷¢ö¿õèõôWòðñÁðñðâññmñÒòAòµó+ó£ôôŽõõnõÚöBö¦÷÷e÷Àøølø¾ùùZù¥ùîú4úxú»úüû;ûxû³ûîü'ü`ü—üÏýý:ýný£ýÖþ þ;þmþžþÏþþÿ-ÿ[ÿ‡ÿ±ÿÙ%Lu Íû*YŠ»í!VŒÄþ:x¹û@ˆÓ rÇ ~àI¹/¯ 6 Ç a  µ s >û'[¥| ³rN E"%#Ñ%G&¢'¢(©)³*É++‰+Ä,,,E+Â+?+,+w,--\/[0a/.Š-z,O*Á)š(ö&ï$²#!yõϺýŽUïK _ ` @±’ŒÿtþVýLü_û›ûúíúÊúŠú²ûpûúûÐùÚø÷[ø*úJú‰úRùÎùDøºøcø<÷iöNõñõ¹ö3öÇ÷Y÷À÷Í÷¾÷•÷‰÷÷ýøøø)ø8ø÷ù÷möÜömõáõ>ôÿõ„õÇõBôeóòó0ñßñðúñ ñQñ£òòlòÚóKó¾ô1ô£õõõèöOö²÷÷o÷Éø øtøÅùù`ùªùóú8ú|ú¿úÿû>û{û¶ûðü)übüšüÑýý<ýpý¤ý×þ þ<þnþŸþÐþÿÿ-ÿ[ÿ‡ÿ±ÿÙ%Lu Íû*YŠ»í!VŒÄþ9w·ù>…ÏmÂwØ?­"Ÿ $ ± H è ” M  çÉ»¿Õÿ;Žöt ¸~T!1# $ô&´'Þ(»)¨*g+h+Ò,,s,Ì---k,Ý,b,w--â/G0Ø0©/~/ -Ì,L+x*¢)•'$H"¬!käßxk/Ò[Ã.Ü – å œ«ÈOrÿ€þvýFüCûsûúïúÌú²úÁúúûAûù÷Ýöº÷ÍøsùùøÑøkø÷µ÷möÏõðõjõööŸ÷÷d÷ˆ÷Îøø?øøøøø)ø/ø$÷•öÚö5õ¬õ ôÅô ô˜óÿóÓòxòñ—ðûðÄðóñ3ñ|ñÑò/ò”òþókóÚôJôºõ'õ’õùö^öÀ÷÷z÷Óø)ø|øÍùùgù±ùøú>úúÃûûAû~û¹ûóü,üeüœüÓý ý>ýrý¦ýÙþ þ>þpþ þÑÿÿ.ÿ[ÿ‡ÿ±ÿÙ%Lu Íû*Y‰»í!U‹Ãü8uµ÷;Ëh»nÏ4   š - Ê r % æ ³ytŸÏmÜ`û­t S"S$ƒ&Ž'Ô(Ó)U**û+¾,,Â--ˆ-Ü-¼-Y-s--ó/0.1 0ó0b/ª.K-(,H*ö),&„$!!ó aÓQºFüœ[ÙAO 6+Þ„öçEÿ¥þ°ýoûòûVú÷úéúæúÇú¡ú©údù„øøø÷œ÷d÷Äøø÷þ÷¯÷LöÝö[õìõLõDõ»öö†öâöõ÷e÷Å÷ûø%ø=ø7ø:ø/ø#ø÷eöÅöõmôÛô_óïó’óœó’ò{ñ[ð×ðÅð©ðËñ ñSñ¢ñøòUò¸ó óŠó÷ôdôÑõ=õ¥ö önöÏ÷,÷‡÷Þø3ø†øÕù#ùnù¸ùþúCú†úÇûûEû‚û½û÷ü0ühüŸüÖý ý@ýuý¨ýÛþþ@þqþ¢þÒÿÿ/ÿ[ÿ‡ÿ±ÿÙ%Lu Íû)Y‰ºì TŠÁû6s²ó7}Æa´ eÄ'‘zù  ª M û ¶ }R5')=b™äC¶?ß™s!|#Î&0'‡( (û)Ó*§+z,†-?-å-ù-ý-î-÷.-ì.T.Ù/ü0ù1Í1´0×06.˜- +è*i(%n# ò¡…ç(ð ZËÎË– f *ê2UxÿÁÿ7ý·üFûXú¼úíûúµúSú0ùñøéø7ø÷›÷X÷W÷u÷}÷`÷ö¾ö$õ•õõõ{õçö&öPöß÷(÷]÷›÷Ó÷±øø@øHøxø÷Lö¡õòõRôÑôó•ò‘ò‰ò‘òGñjðÅð€ð˜ð¾ðìñ-ñuñÅòòyòÛóAó©ôôôêõTõ»öö€öß÷;÷”÷ëø?øøßù,ùwù¿úúJúŒúÍû ûJû†ûÁûûü4ülü¢üÙýýCýwý«ýÝþþBþsþ¤þÓÿÿ0ÿ\ÿ‡ÿ±ÿÙ%Lu Íú)Xˆ¹ëSˆ¿ø3p®ï2xÀ Y«Z¸ðeâ f ó ˆ ' Ð … FïØÑÙóZª†¾‹ †"Æ% &¦'r(”)‹*i+l,p-˜.…..9..(.G.J.š/%0U1|22ñ2<1;/—-í,ƒ*(&_$<"3 k…ÓÇì! ѧ Y Áhé.ÿñÿÌÿkþOüÓû/úÕúèúÿú“ù¾ùIùøf÷‡÷g÷÷÷÷)÷(÷öÖöpõñõ9õAõ ööölöföDöé÷c÷¤÷¡÷íøøJøgøO÷¿öZöHõ‹ôÿôAó£òhñöñžñ€ñðâð‚ððŸðÔñ ñNñ—ñçò>ò›òüóaóÈô1ôšõõlõÑö4ö“öñ÷K÷£÷ùøKøœøêù6ù€ùÈú úQú“úÓûûOû‹ûÆüü8üpü¦üÝýýGýzý®ýàþþDþuþ¥þÕÿÿ1ÿ]ÿ‡ÿ±ÿÙ%Lu Ìú(X‡¸êQ†½ö0lªê-r¹Q¢öN« pÜOÉ J Ó d ÿ ¢ Q Ó§ˆwuƒ¢ÑgÏMåœ{!‚#‚%2&Û(")*C+W,i-©.».ñ.¦._.u.q.¢//õ1L1ó2×3—3E1õ0|.Õ,ç*œ(Ç&Ü%&#y!£Ù$¨ˆ~»&[J! » %´BQ\ÿöÿªÿ^þéý7ûxúŸú¿ú½ú+ù÷š÷CöÈöpõÝöxöÑöþ÷÷÷öæöˆõüöö!ö‹öù÷÷ö”ö7öY÷÷ÿøø ø0øSø‹øDöûöõõRô‰óŠóò7ñqñðÂð¿ð“ðð“ð·ðíñ*ñmñ¸ò òaò½óó‚óèôPô·õõ…õéöJö¨÷÷]÷´øøYø¨øöùAùŠùÑúúYúšúÚûûUû‘ûËüü=üuü«üáýýJý~ý±ýãþþFþwþ§þÖÿÿ2ÿ^ÿˆÿ±ÿÙ%Lu Ìù'W†·èNƒºò,h¥å'k²ûH—ëBœû_È8® , ± ? Õ t  Ñ ‘]6&I}È ®m D" #í%œ'l(ã*C+_,u-‹.í/r/,.ï/*/;/–/¦0Ý1*2633<2î2V1 /¾-«+{)G'Z%¶$w"» ¿âQ Ôaegu‡H þ Ä•=ÇÑÿpÿþýMû¤ú¡ú<úTù<÷Êötõæõzõ0õ[öö¼÷ ÷9÷U÷`÷U÷ö¾öÍ÷÷–ø!ø~÷Îöõöõ¡öÛ÷Ûø?ø<ø7øGøM÷Òöaõ‹õ ôÕóÇò¨òRñÑñ'ð½ðƒðQðwðšð£ðÊññFñŒñÙò+òƒòàóAó¥ô ôoôÖõ<õ ööaö½÷÷o÷Åøøhø¶ùùMù•ùÛúúaú¢úáûû\û—ûÑü üBüzü°üåýýNýý´ýæþþHþyþ¨þØÿÿ3ÿ_ÿ‰ÿ²ÿÙ%Lu Ëø&U…µæK€¶î'c Þ c©ò=ŒÞ3êL²“  ª D ç • NäÁ«¤¬Ãé!kÈ<Çl( ô"À$±&â(£*+ž,\-j.˜/Ä00 /ô0+00¿0Ú1;2832Ø2C1µ1S/Ë.,)±'³&+$»#r!j~ÜdöTpn~xX ' öá’Io)ÿþNýƒülû#ùìùœøÄøTöàõäõUõKôüõ¬öMöÞ÷C÷Œ÷¼øøø÷Ó÷•÷Õø_ùIùrø½÷öZõú÷6ø:ø’ø†øwøL÷Ìöüöôÿô‚óÅócòŒñÛñ\ðÞððbð^ðoð{ð¨ðÝññbñ«ñúòNò§óóeóÈô,ô‘ôõõZõ¼ööyöÔ÷-÷ƒ÷×ø(øxøÅùùYù ùæú)úkú«úéû'ûcûžû×üüHüüµüêýýSý†ý¸ýéþþKþ{þªþÚÿÿ4ÿ`ÿŠÿ²ÿÚ%LuŸÊ÷$S‚³äH|²é"]™×[ è2Ð$|Ø8œví k ð ~  ± X È‘eF51=W‚¾ oéz$å!¾#Â%ä'ü)k*×,^-$.;/®0G0Ö0©00‘0¦11ß2a2{21T10{/b-­+ª) 'Å&N%,#œ!º `¹8N`5æ Ÿ ±¿§Z¿Qþšý‡ügûwúAù÷”÷ÁöÎöAõ®õzõnõ¶öö­÷+÷ŸøøXø}ùKùoøŸøPømøäùmùìù‚ø-÷?÷“øaùùTù4ùøq÷‰ö`õ³õó÷ózòüòmñÅñ3ð»ð|ðuðyðUð|ð±ðññ6ññËòòròÍó*ó‹óíôPô³õõyõÙö7ö“öì÷C÷—÷êø:øˆøÕùùgù­ùñú4úuú´úòû/ûkû¥ûÞüüNü…ü»üðý$ýWýŠý¼ýíþþNþ~þ­þÜÿ ÿ6ÿaÿŠÿ³ÿÚ%LužÉõ#Q€°áEx­äV’ÐQ–Ý&rÂkÄ#…ìYÌ G È P á z  Æ |= âÆ¹¹ÈæU©”/ä ¸"­$Ë&Ó(*+Û,þ-æ.Å/Í0Ã10¾0¤0¸1s1Ð2<1ú0ñ0›0†0"/ -)*ë)'–&l%:#Å" ” 4@A5Þx  Tv«øpÿõþªülû½úÄùøöÌõ¡õîõŽõXõXõ³öö“÷÷øøœøüù[ù¾ùù$øÕøåù#ùeùrùø«ø—øçù¥úSúCúùcø¯÷ƒöwõÜõPô=ódòÒòuñíñ\ðÞð¥ðxðMðZð†ðÅñ ñRñžñîòBòšòõóSó³ôôvô×õ9õ™õ÷öSö­÷÷Z÷­÷þøMøšøåù.ùuùºùþú?úú¾úüû8ûsû­ûæüüUü‹üÀüöý)ý\ýŽýÀýñþ"þQþþ¯þÞÿ ÿ7ÿbÿ‹ÿ³ÿÚ%LtÈô!O}­ÞAt¨ÞOŠÇG‹Ñd²X° lÑ;« ! ž " ® B Ý ‚ 1 ê¯~YA7;Mp£éCµ@è®!–#Ÿ%¶'Ó)£+n--¡.(/(0 0Ò0ý0¸0º0È1Ÿ1ä10Ó00m08/a-F*i(‚'¿&¶%$"œ!OçýÛ£Z*óß´ 9 õ PØBŒÿÒþüœûcúaù!÷Æö=ôéôÿõô–õ0õÀöoöô÷c÷¹øKù>ù­ù©ùºù”ùPù7ùCùhùsùùUùdù›úú‚úú¯ú¼úPøÒøöÒõÿõ=ôeó:òüò«òDñšñ ð¤ðqðDð_ðœðÞñ&ñrñÂòòkòÄó ó~óÝô=ôôýõ]õ»ööqöÉ÷÷r÷Äøøaø¬øöù>ù„ùÈú úLú‹úÉûûBû|û¶ûîü&ü\ü’üÇüüý/ýbý“ýÅýõþ&þUþ„þ²þàÿ ÿ8ÿcÿŒÿ´ÿÚ%LsœÇòL{ªÚ <o£ØH‚¾ý=Ä U¢ñD›õSµˆû t ô { Ÿ = å —TíË·°·Íô,yÜWï¥ |"w$š&Ô)2*ù,x-Š. .§/i00¯0±0®0£0é11&0ÿ0¿0œ0\/…-Þ+})Ÿ(E'/%â$~#!Í ¡'¡N WÁ p MÌo0ªöÿÕýØü¹û‰úLù÷¤ö;õJô¢ôô•õõÀö‰÷i÷y÷Æøsù/ú-ùôùÀùŸù‚ù€ù—ù»ùÇùãùöú'úcúÉúýúÞúŸúÑú·ùï÷ëöqõ¸õ%ôjóÎó#òéòpñtðÐð†ðPðQðtðµðýñIñ˜ñëò@ò˜òòóNó«ô ôgôÆõ$õ‚õÞö8ööæ÷:÷Œ÷Üø*øvøÀùùNù“ùÖúúXú—úÔûûLû†û¿û÷ü.üdüšüÎýý5ýgý™ýÊýúþ*þXþ‡þµþâÿÿ:ÿdÿÿ´ÿÛ%Kr›ÅðJx§Ö8jÒ@zµò2s·ýE‘ß0…Ý9˜üeÔ I Å G Ñ a ú š E ú¹‚W9'$.It³sùa!K#]%'ê*H+É,ï-½.M.á/s/ø0›0£0Ð11T1C10Ø0Ë0]/d.,*¡)-'Ä&Z$ô#"8 ÜGЍ ¸n= Í €ˆ»VrŒ™þÀý!ûäú~ù÷¬ö|õ€ôµôkôŽõ$õ¿öy÷÷.÷©øyùùÆùâù¼ù«ù©ù»ùàúújú¾úÖúÍúËûû ú»ú}úfú¡ùT÷)õÎõ`õ ô»óÛóGóòœñNð£ðeðQðað”ðØñ$ñtñÆòòpòÈó#ó~óÚô6ô“ôðõMõ¨ööZö°÷÷V÷¦÷ôø@ø‹øÔùù`ù£ùåú&úfú¤úàûûWûûÉüü7ümü¢üÖý ý;ýmýžýÏýÿþ.þ\þ‹þ¸þåÿÿ<ÿeÿŽÿµÿÛ%JqšÃîFt£Ò3e—Ë7p«ç&f©í5~ËmÄ{ÜB­  •  ˜ # ¶ P ô ¡W弡’’ ¿ð5‘—G "$3&~(¾*è,b->..n.è/t/õ01[22 1À1$10Þ0p/r.&,a+,)å(O&ï%†$"£!mRñoá©s ;  2keG¢ÿ´ýðüLûù÷Ðö§õ°ôûôô¦õIõñöPöuör÷Hø¬ùùvùŠù›ù«ùÄùæúúkúîûŸûÌû5ûú÷úªú&ùBù“ù[ø6öõ.ôÜõ ôAó¶ókó1òÀñ»ðÆð{ðrððÂññUñ¦ñùòMò¤òýóVó°ô ôfôÁõõvõÏö'ö}öÑ÷#÷s÷Áø øXø¡øèù.ùrù´ùõú5útú±úíû(ûbû›ûÔü üAüvüªüÞýýBýsý¤ýÔþþ3þaþþ¼þèÿÿ>ÿgÿÿ¶ÿÛ$Jp˜ÁëCpŸÍý-_‘Äø.f ÜXšÝ#l·Vª]»…ó f ß ^ å r  £ H ø±tBøú 1g³“.é Æ"Ç$ê'5)™+¦,þ-h..m.æ/®0^1™2!21Ü1ô1p0ý0³/Š.?,¡+7)Å(Ú'&J$×#M!”¬Oÿ²o3ý Ð µ ²¼ †6 ‡þ’ü˜ú›ùR÷æöÔõöõ"ôªôYõ«ö¥öõæön÷nø"øºùùBùqù ùÓúú7úiúýûºûîûÛûºúûú8øÙøÈøD÷²öËõŒôŒôKó÷ó§óIóLó6ò¼ñºñð¶ð®ðÊðÿñCñŽñÞò1ò…òÜó3ó‹óäô=ô–ôðõIõ õ÷öLö öò÷B÷÷Üø'øpø·øýùBù…ùÆúúEúƒú¿úûû5ûoû§ûßüüKüü³üæýýIýzýªýÚþ þ8þeþ“þÀþìÿÿ@ÿiÿÿ·ÿÜ$Io—¿é?lšÈø'Xмð%\•Ï JŠÍX¢î=å>šú^Ç 6 « % § / ½ S ñ ™JÊšwaX^tœØ*“¸y!Z#`%•(*¨,,Ä-M-×.]/0T0·1c1?12)1»0Ø/÷/..,¹+-)¿(Ó(V'?&$["j BÚ–QÕ¡w ] Wkœék(•þZü"úƒù÷í÷(öNõ‰ô¨õ‰öpö„öCöföÓ÷c÷õø^ø´øúù@ù‹ùÖú%úNúùôúûÖü£üŸûAù¡ù›øn÷Šöƒõ­ôÝô-ó¡ó&ò²òŽò«òÄò7ñžñ%ðòððññBñ„ñÍòòmòÁóókóÂôôpôÈõ õvõËööröÃ÷÷a÷­÷øøAøˆøÎùùWù™ùÙúúVú“úÏû ûCû|û´ûêü üUü‰ü¼üïý ýQýý±ýàþþ=þjþ—þÄþïÿÿBÿkÿ’ÿ¸ÿÜ$Hn•½æ<h–Ãò!R‚µèR‰Âþ;z»ÿD×$tÇxÕ7œ  v ì i ë t  › ; å—Tí̸²»ÕA—Œ/ñ!Ö#æ&1(n*†+¼,L,æ-Ç.h/0/ø0C0ñ1610(/. ,î+ô*›)M(t(h( '9% #V!Ù‡EÊ‘\/   '^²Jýàûòú\ùø=÷[÷õäõ~ö3÷5÷öé÷÷F÷“÷âø*øjø¬øþùlùäúúù3ùvúRû®üµü­û´úùªøk÷0õûôöôPóÂó1òsñÅñ²ñÂñîñÇñsñ<ñ&ñ0ñSñ‡ñÈòò\ò¬òþóQó¥óúôOô¥ôûõPõ¤õööHö˜öç÷5÷÷Ëøø[ø¡øæù*ùlù­ùìú+úgú¤úÞûûQûŠûÀû÷ü+ü`ü“üÆüøý)ýYý‰ý¸ýæþþBþoþœþÇþòÿÿEÿmÿ“ÿ¹ÿÝ#Gm“»ã 8d‘¾ìJ{¬ßG}µð,jªì0v¿ X©þU°pÖ B ´ + ¨ , ¶ G ß +ßf: .\ŸöeìŽ N".$'&3(')ñ*Ð, ,Ê-Ž.-.–.Ô/i/ð0=/Ê.é.$,Ú+˜*?)( '¶'è('%Ý$"Àl'Ú¦n4þ Ñ µ ­ºÚ7@þ2ü4úºù‰ø‡÷û÷~÷ ö öõ÷f÷¡÷–÷ž÷µ÷Ð÷ç÷üøøOø¢ù7ùðúSùùmù÷úµûTûîü>ûIúAù-÷ïövõlô’óîóŽò÷ñ½ñNññEñkñoñ\ñOñSñkñ•ñÌò òSòžòìó<óóàô3ô†ôÚõ-õ€õÑö"öqö¿÷ ÷W÷¡÷éø0øvø»øÿùAù‚ùÂúú>úzúµúïû(ûaû˜ûÎüü8üküžüÐýý2ýbý‘ý¿ýíþþHþtþ þËþõÿÿGÿoÿ•ÿºÿÝ#Fk‘¸á 5`Œ¸æCs¤Õ<q¨áY˜Ø`§ð<‹Ý2ŠåD§  { î f ä h ó …  Ám"᪀cSP^{«íD°3Í ~"B$%Þ'~)?*‚+Ð,ˆ-<-•..Î.Å.º.d-¹,©+¬)ÿ(n'&]&‰'='I&ì%Å$&"‡ p‘Ý´y4ë¨ w _]l„ ¸þÑýûuú@ùzø«ø0÷á÷À÷Óøø*ø8ø5ø'ø ÷ê÷Æ÷ ÷Íø3øÖùäú^úúúSúoúûgû@ú0ùlø"÷Höõ1ô]ó«óPòóò@ñðîññ3ñJñXñhñ€ñ¥ñÖòòPò–òàó-ó{óËôômô¾õõ`õ°õÿöMöšöå÷0÷y÷ÁøøNø’øÖùùYù™ùØúúRúúÇûû9ûpû¦ûÜüüEüxü©üÛý ý<ýjý™ýÇýõþ!þNþyþ¤þÏþùÿ"ÿJÿqÿ–ÿ»ÿÞ"Ej¶Þ1[‡²ß ;jšËý0e›Ó G…ÄHÕl»c¼xÛ C ± $    , ¾ Y ü¨^éÀ£“‘Ÿ¼ê*|áYâ z"#¶%X&ê(‚*&+~,1,Ï,Ø-5-¥-f,û,$+=)Ó(d&ï%ª$×%e&I&m&6%_#é"P צäù÷Ñz F  "6UÿˆýÝüjûHú_ù¯ù(øßøÇøÐøåøñøïøÞø®ø^÷ø÷‰÷öÑ÷ÕøÂù½únú ù»ùSù[ùåúrúùøv÷µöØö4õPômó‰óòáòFñKðíññ$ñGñgñ‰ñ°ñßòòRò”òÚó#ónóºô ôXô§ôöõDõ’õàö,öxöÂ÷ ÷U÷œ÷ãø(ølø¯øñù2ùrù°ùîú*úfú úÚûûJû€ûµûêüüRü„üµüæýýEýtý¢ýÏýüþ(þSþ~þ©þÓþüÿ%ÿLÿsÿ˜ÿ¼ÿÞ"Dh³Û-W¬Ù3a‘Áò$XÃû6r¯ï1tºLšê=“ìH¨ u ã W Ð O Ô ` ò 1Þ”TöÚÉÇÒíQ›õ\Ï J!È#H$Ë&Z'î)™++•+·,,i,q+u*±)ã(Ý'Ñ&S%$F$²%—&+%Á$½#r!Û ¶zÕ 1Þv Ý âÜÑÙþ8þ§ýdügû™úãúVúùíùõù÷ùæùÆù¤ù|ùø„÷ ö•ö`÷7øºùûùåù¦ù<ø¨øù9ù‹ùAøqø÷Tö©õýõlôÅóòÒòrñ¿ñBñ ññ5ñ\ñ‡ñ´ñåòòVò•òØóóeó¯óúôGô”ôàõ-õyõÅööZö¤öì÷4÷{÷ÀøøHø‹øÍù ùMù‹ùÈúú@ú{ú´úíû$û[ûûÅûùü-ü_ü‘üÂüòý!ýPý}ý«ý×þþ.þYþƒþ®þ×ÿÿ(ÿOÿuÿ™ÿ½ÿß!Cf‹°×ÿ(Q|¦Òþ+X‡¶çJ~³ê#^šØZžä-xÅi¿uÕ 9 ¢  … þ ~  Ž ! ½` ÃM$óî÷ 0b ë?œþ!f"Ô$I%Ë'c))þ*Ô+@+§+<*t)Š) (×(&À%$$2%œ&t%£$/#?"S!hÙQ‡††:z } ²ž\†¤Êÿ@þ4ýªýüWûŠû"ûAûVûXúôú¬úxúeúfù•øögööÐø2ù{úù³ù'øËø·ø¾øåøø÷‡öþö_õÄõ>ô«ó‡òPñõñŒñ<ñ(ñ7ñXñƒñ³ñçòòYò—òØóó`ó¨óðô:ô…ôÏõõdõ®õøö@öˆöÐ÷÷\÷¡÷åø(øiø«øëù*ùhù¥ùáúúWú‘úÉûû7ûmû¡ûÖü ü;ümüžüÎüþý,ýZý‡ý´ýßþ þ5þ`þ‰þ³þÛÿÿ+ÿRÿwÿ›ÿ¾ÿß Bdˆ­Óû#Lv Ëö"O}«Û =o£ÙJ…Áÿ?‚Æ U î?’èBžþ c Í ; ¯ ( § , · J å‰5é¨rF& 4Z‹ÅPŸ ö"U#º%1&©(D)*+*‡*j)®)8)6)(&„$¢#{$†%Õ&Å& $Ñ#|"$ §Fõ­o—{}Ç ¹ Üâ5Kÿ§þÆþœþ¿ýºü˜ü5ü~ý%ütûæû7ûûFûúKø öVõÉö÷¬ù9ú:údù«ùbø¸ø±øºøƒø ÷Eö³ö7õ©õô&òýòXñØñ‡ñYñRñfñ‰ñ¶ñêò!ò]òšòÚóó_ó¤óêô1ôzôÂõ õSõ›õãö*öqö·öü÷A÷…÷Èø øKø‹øËù ùHù„ùÀùûú5únú§úßûûKû€û³ûçüüKü{ü¬üÛý ý8ýeý‘ý½ýèþþ=þgþþ¸þàÿÿ/ÿUÿyÿÿ¿ÿà @b†ªÐöFo™ÃîEr Ïþ.`“Èþ6oªæ%e¨ì3{Çe¸hÄ $ ‰ ò a Ô M Ì P Û mªUÅŒ]9 ";]‡¸ï- t!Ã#$•&$'º(Ð))5)6)(ã(’'ù%Ú#ß#$}&[' &’%#R!§¾}‘×÷@„'A  ©soÐ*ÿFÿ…ÿjþöýðýˆý–þýbüû…û~ûSû7úµø‘ö˜ö%õÈ÷øÄùÛú¥úùøÅø~ø<øæ÷ý÷4öpö õÂõóªòíòUñëñ¨ñˆñ‰ñ ñÅñóò)òbòŸòÞóó`ó£óçô,ôsô¹õõGõõÒöö]ö¢öå÷)÷k÷®÷ïø/øoø­øìù)ùfù¡ùÜúúOú†ú¾úõû*û_û“ûÅûøü)üZüŠüºüèýýCýpýœýÇýñþþEþnþ–þ¾þæÿ ÿ3ÿXÿ|ÿŸÿÀÿá?`ƒ§Ìò@i‘»å;g”Âð Qƒ¶ë!Y’Í H‰ËVŸê8‰Ü2‹æ F «  ‚ õ m ë n ø Š"Ãlךg>úöû3Sz©á!'"‚#ó%n&×'%'°(‚(\(c'Õ&Ð%Ç#È#›$ñ&&^%ë$*"9 W{)5ˆ{™Ùù 2 = ‘œF–×Å,mÈ ÿ2þ{þ¥þ4ý‹ü·û¬ûFû1û'úïùîø)ö½ö1÷ø°ù^ù¸ù‚øÂø˜÷÷¿÷½÷ï÷ö4õêõ·ô÷óåòüòuòñÜñÇñÌñäò ò9ònò¨òåó%óeó¦óèô+ôoô´ôùõ=õ‚õÆö öMööÒ÷÷U÷–÷ÖøøUø“øÐù ùIù…ù¿ùøú1úiúŸúÖû û@ûsû¦ûØü ü:üjüšüÈüöý#ýOý{ý¦ýÑýúþ$þLþuþþÄþëÿÿ7ÿ[ÿÿ¡ÿÂÿá>^€¤Èî;bгÜ1\ˆµâAr¤× Cz³î+jªì1wÀ Y©üRª  e É 1 ž  ˆ  †  Ÿ6Ôz'Þd5 î×Ç¿½ÀÊÛò? y!¼# $%% &&ô'1'&¬%í$¯$e$%°%—%c$Œ#k!$4•Úd‚µ\ ‹  60'|;©/QÇÏ÷ÿýÿþý”ý üûNúÙúÎúýúõúù¤ø#÷…÷—øxø§ø¼ùøK÷ƒ÷ ö…öÉöµögõèõ½õeô¬óÞó&ò£òOò òòò/òTòƒò¹òòó/ómó¬óíô.ôpô²ôöõ8õ{õ½õÿöAö‚öÂ÷÷C÷ƒ÷Âøø>ø{ø¸øôù/ùjù¤ùÝúúLúƒú¹úîû"ûVû‰ûºûëüüLü{ü©ü×ýý0ý[ý†ý±ýÛþþ,þTþ|þ£þÊþñÿÿ;ÿ_ÿÿ£ÿÃÿâ<\~ Äé5\ƒ«Óü&Q|¨Ô1`‘Ã÷,bšÓJ‰É P–Þ)wÆnÅ  â J ¶ '  ˜  ¬AÜ~(Ù“Tìá†p_TNOWhž ¸!Æ"Ì#ë%%Y%1%K$›$…$Ã%%"%$O#Ú" 8nì»™é~© ‰ ÜyîAâÜSéž…–*:ÿäþýþü—ûÙû/únù÷ú úuúqúfú'ù~ø4÷Ò÷È÷´÷»÷š÷;ö…öõèõÉõéõ½õÁõcôòôcóÄó=òÔòŽòhò]òfòò¥òÒóó?ó{ó¸óöô4ôtô´ôöõ7õxõ¸õùö9öxö·öö÷4÷r÷°÷îø*øfø¢øÝùùRù‹ùÄùûú3úhúžúÒûû:ûmûžûÏûÿü/ü]üŒü¹üæýý=ýhý’ý¼ýåþ þ5þ\þ„þªþÐþöÿÿ?ÿbÿ„ÿ¥ÿÄÿã;Z{Àä /U|£ÊóEp›Æó O~¯áI€·ð+g¦æ(l²úD‘à2†Ü 6 ” ÷ ] È 8 ¬ % £ ' ²CÛxÉ|6ö¼ˆ[2ïÕÀ°¦¡ž˜Ž ƒ!‰"W"ó#›#$&$^$³$¬$h$#}"p!C˜[†š3sà Á œˆIZᄟ&pýÿ¡þíþý’üÔû»úðùÖùøâù”úùúùÃùø÷U÷öÝö±ö]ö'õïõ¨õ•õ˜õ²õõCõô˜ô'ó·óRóòÏò³ò­òºòÔòøó&óXóóÉôô@ô}ô»ôúõ9õyõ·õöö4örö¯öì÷)÷f÷¢÷ÞøøUøøÊùù<ùuù­ùåúúQú…úºúíû ûRûƒû´ûäüüBüoüüÉüõý ýKýuýžýÇýïþþ>þeþ‹þ±þ×þûÿ ÿCÿfÿ‡ÿ§ÿÆÿã:Xxš¼à)NtšÁé9c·ã=k›Ëý1e›Ó F‚ÁB…Ë\¨öGšï H ¥  l Õ B ´ + ¦ ( ¯<Ïh­X Á}>ΜnDüܽœxPÒ ‚!!¤":"×"÷"õ##4"µ!Ò N‚ó…ELØ€j rƒTÚe˜Gì$­ïqÿçþÏý¨ü”üÊü|üÕü}ûúø¢ø¢øÔø÷ùùø÷öpöRö9öõåõÏõšõƒõ|õcõLõ,ôïô¬ô^ô ó·óoó7óóóóó*óOó{ó¬óáôôQôŒôÇõõ@õ~õ»õ÷ö4öpö«öç÷"÷]÷˜÷Òø øGø€ø¹øòù*ùbù™ùÐúú;úpú£úÖûû:ûjû›ûÊûùü'üUüü®üÙýý.ýXýýªýÒýúþ!þHþnþ“þ¸þÝÿÿ%ÿHÿiÿŠÿ©ÿÇÿä8Vv–¸Ûÿ#Gl‘·Þ-V¨Óþ*X†µæKµì%_›ÙYœá'p»Xªþ V ²  t Ü G · * £ ! ¤-»Næ…(Ñ~/äZÝ¢j3ûÁ„?ð“&±AÙ i æ!!½"9"Œ!˜ãìÏô/ô• – ?ÜÞ´Ç2ÛRùÿîÿþ+ý4ü ûûRûæüûöû úùøqø7÷ú÷Ö÷NöŽõõ•õÅõíõáõÎõ¯õõdõAõ#õôáôµô~ôBôóÈó•ópóXóOóTófó‚ó§óÑôô4ôiô ôØõõLõ‡õÂõýö7örö«öå÷÷X÷‘÷Êøø<øtø¬øäùùQùˆù¾ùóú(ú\úúÁúòû#ûTû„û³ûáüü<ühü”ü¿üéýý=ýfýŽý¶ýÞþþ+þQþvþ›þÀþäÿÿ*ÿLÿmÿŒÿ«ÿÈÿå7Ts“´Öù@d‰­Óù!Hp™ÃíDqŸÎÿ0c—Í<v±î-m¯ó9Ëe¶ ` ¹  x Ý E ² " —  œ)ºQëŠ-Ô})؈;ï£V³Xô‡•—’)ý ø!8 tö0Af†Od¢f Y -:àD_*­:þ¥ý™üÆüû%úœúkúÃûXúáú]ù¦øÞø ÷uöÿöpöôûôåõHõ³õäö õ·õ”õrõJõ!ôÿôßô¾ô˜ônô@ôóéóÆó®ó¡ó óªó¾óÜóÿô)ôWô‡ô»ôïõ&õ]õ•õÍöö?öxö°öç÷÷W÷Ž÷Æ÷ýø4økø¢øØùùDùyù®ùãúúJú|ú®úßûû?ûnûûËûøü%üPü|ü¦üÑüúý$ýLýtý›ýÃýéþþ5þZþ~þ£þÇþêÿ ÿ/ÿPÿpÿÿ­ÿÊÿå6Rp°Ñó8\€¤Èî;a‰²Û0\‰·åGy­âPŠÅ?~¿GŽ×!o¾  d »  u Ø = ¦  „ ú t òtúƒ£8Ðk§Gé‹-Íj—#¨&Ÿí_ïÄÎÃC+Çþ`âN—x!» Í ï•plgÿ©þ0üñüûû úšùþùnùXùpù»ùUøÎø÷.ö\õaôÚôšô‡ô“õ'õÓõøõÇõ¥õ{õZõ6õôñôÒô´ô•ôuôSô2ôôóóóïóôôôô5ôXôô­ôÛõ õ?õsõ¨õÞööKö‚ö¸öî÷#÷Y÷÷Å÷ûø0øfø›øÐùù:ùnù¢ùÕúú:úlúúÍúýû,û[û‰û¶ûãüü;üfüüºüãý ý4ý[ýƒý©ýÐýõþþ?þdþ‡þ«þÎþñÿÿ3ÿTÿsÿ’ÿ¯ÿËÿæ4PmŒ«Ìí1Swš¾â-Sy¡ÉóGrŸÌû*[Àõ+b›ÕNŒÌR—ß(tÁ  c ¹  m Ì / ” ý j Ú N ÆBÀBÇPÚgö‡ª<Í]ês÷tì_Ë3”óUÈeÒõ‡Ä®Ì›Îk?@"Ú  0 Yž~ÆÿÏýçü{û"úkú‰úúEù[øB÷`÷©÷Ä÷”÷möåõ¹ô óüó§óÝôôLõõˆõ²õ¥õ‡õlõNõ0õôôôÙô¿ô¦ôôuô_ôNôBô=ô?ôIôZôrôô²ôÙõõ/õ^õŽõÁõôö'ö[ööÄöø÷,÷`÷”÷È÷üø/øcø—øËøÿù3ùfù˜ùËùüú.ú^úú¾úíûûJûwû¤ûÐûüü&üQü{ü¤üÍüõýýEýký’ý·ýÝþþ&þJþmþþ³þÕþ÷ÿÿ8ÿXÿwÿ•ÿ±ÿÍÿç3Nkˆ§Çè*Km³ÖûDj·ß1\‡³à=mŸÒ;rªãY—ÖYã+tÀ ] °  _ »  { à G ² ’~÷sñrôwú~„‚ýsäP¶rÈk¿DCúiÀýNl…ÅÔˆï í  `(õUÿ/ý*ûÂúšú ùíúcú4øÑ÷)öOö&öEö|önõÃôÊóùóhóCóÍô3ôœõõ[õ€õˆõ|õgõOõ6õõôîôÚôÇôµô¥ô˜ôôŠô‹ô“ô ô³ôÌôêõ õ0õYõƒõ°õÞöö?öqö¢öÔ÷÷8÷j÷œ÷Îøø3øeø—øÊøüù.ù`ù’ùÃùôú$úTúƒú²úàûû;ûhû”û¿ûêüü?ühü‘ü¹üáýý/ýVý{ý¡ýÆýêþþ1þTþwþ™þ»þÜþýÿÿ=ÿ\ÿ{ÿ˜ÿ´ÿÎÿè2Lh…£Ââ"Cd…¨Êî6Z€¥ÌôEošÅòN~¯áIµî'bžÜ\Ÿã)qº  R ¢ õ K £ þ [ »  ‚ ê U Â1£‰ÿvìcÚOÂ2Ÿ mÎ(~Í]œÕÈ_Ô6ˆËÿ3[b- ®  V’ªeÜÿ¦ý’ûýúüú…úkú†ú.øªöáõÿõ¼ö&öNö)õ¼õôŠôôôBôžôëõ-õ_õ}õ…õ€õqõ^õJõ6õ#õõôõôéôßôÙôÖôØôÝôèôøõ õ&õCõdõˆõ®õ×öö.ö\ö‹ö¹öé÷÷H÷x÷¨÷Ùø ø:øjø›øÌøüù-ù^ùŽù¿ùîúúLúzú¨úÖûû/ûZû†û±ûÛüü.üVüü¦üÎüôýýAýgý‹ý°ýÔýøþþ=þ_þþ¢þÃþãÿÿ#ÿBÿaÿ~ÿ›ÿ¶ÿÐÿè0Je‚Ÿ½Üû:[{œ¾á'Ko”¹ß.W€ªÕ.\Œ¼î Tˆ¾õ-g¢ß\ß#h¯÷ B ß 1 … Ü 5 ì K ­  v ÝE¯ƒîYÃ,“÷X¶d´þB¸é'*Ù ƒæ:µ×Ù ³ c ò kÏ 'þuýü ûbúþú¥ùøøç÷Àöëö§ö ö§özö)õÃõ\õôïô÷õõCõiõ‡õ—õœõ—õ‹õ|õlõ]õNõBõ7õ.õ'õ"õ!õ#õ)õ2õ?õQõgõ€õœõ¼õÞöö*öSö~ö©öÖ÷÷0÷]÷‹÷¹÷çøøDøsø¢øÒùù0ù_ùŽù½ùëúúGútú¡úÍúùû%ûPûzû¤ûÎû÷ü üHüoü–ü½üãý ý.ýSýxýœý¿ýâþþ'þHþjþŠþ«þËþëÿ ÿ(ÿGÿeÿ‚ÿÿ¸ÿÑÿé/Hb~›¸Öô1Qq‘²Ôõ;^‚¦Ëñ?g¹ä<i˜Ç÷)[Äú1i£ÞX–×[ å - w à  a ´  ] ´ g Ä ! € ß@ ÿ_¾wÐ&yÇV–Ð/RktlNÈbçYº Iq  o @ ö•‘ïE®ÿ@þýü7ûúîú9ùnø§ø ÷¢÷d÷1öõö«öWö õÊõ¥õ—õœõªõ¸õÄõÉõÈõÁõ¶õªõõ‘õ†õ|õuõpõnõmõoõtõ|õˆõ˜õªõÀõÙõõöö4öXö}ö¤öÍöö÷ ÷K÷v÷¢÷Í÷ùø&øSø€ø­øÚùù6ùcùù¾ùëúúDúqúœúÈúòûûGûqûšûÃûìüü;übüˆü®üÓüùýýBýfýŠý¬ýÏýðþþ3þTþtþ”þ³þÓþñÿÿ.ÿLÿiÿ…ÿ ÿºÿÒÿê-F_z–²Ïí )Gf†¦Æç*Mp“·Û'NuÆðFs Ïþ/`“Æû1h ÙOŒÊ JŒÎ  Y ¢ ì 8 … Ô $ u Ç  o Å  r ÉtÈl»O”ÔEt¿×åäÔ²|2ÕeäP¬ õ ) G M : Ö‡*Ã]ÿÇþ¬ý¶üàü"ûnú¼ú ùhøÜømø÷Ë÷‚÷6öëö¥ököAö'ööööö öõûõðõäõÙõÏõÇõÀõ¼õºõºõ¼õÁõÈõÓõàõðööö1öLöjöŠö¬öÏöõ÷÷C÷k÷“÷½÷æøø:øeøø»øçùù?ùkù–ùÂùîúúDúpúšúÄúîûûAûjû’ûºûâü ü0üWü|ü¡üÆüëýý2ýVýyý›ý½ýÞýÿþ þ@þ`þþžþ½þÛþøÿÿ4ÿQÿmÿˆÿ£ÿ¼ÿÔÿê,C\w’­Éæ >\{™¹Øù<]€¢Æê5[‚©Ñú$Nz§Ô2b”Æù.cšÑ C~ºö4s²ô 6 { Á  P š ä / { Ç  b ° þ K — â+r·ú9tªÜ 0Phw|t_:¾h‡ þ d ¹ ü * F ND*Ϙc9 ÿ þ7ýfü¦ûòûFú¤úùŠùø·ø`ø÷Â÷x÷6öüöÎö«ö’ö€öröföZöNöAö5ö*ö ööö ö ö ö öööö+ö9öIö\öqö‰ö¤öÀöÞöÿ÷!÷E÷i÷÷´÷Ûøø*øRø{ø¤øÍø÷ù!ùKùuùŸùÉùóúúGúqúšúÄúìûû=ûeûŒû´ûÛüü'üMürü–üºüÞýý$ýGýiý‹ý­ýÍýîþþ.þMþlþŠþ¨þÆþãÿÿÿ9ÿVÿqÿŒÿ¥ÿ¾ÿÕÿë*AYsލÃÞú4Qo«Êé *KlްÓ÷@e‹²Ù*Tª×2a‘Âô'[Åü3l¥ßV’Ð  O Ó  Z Ÿ ä ) n ´ ú ? „ Ç J ‰ Å ÿ5g•¿ã)1/"á¬i ¶ E Å 5 — ç ' Wwˆ‡yhZTZÿpþ—ýÏýügûÃû*úúù«ùEøêø•øF÷ý÷»÷÷P÷'÷öìöÕöÂö±ö¡ö’ö…özöpöhöbö_ö]ö^öaögönöxöƒö‘ö¢ö´öÉöáöú÷÷2÷Q÷r÷”÷·÷Ú÷þø#øHønø•ø¼øãù ù2ùZùƒù«ùÔùýú%úNúvúžúÆúîûû<ûcû‰û¯ûÖûüü!üEüiüü°üÓüöýý;ý\ý}ýžý¾ýÞýþþþ;þZþxþ•þ²þÏþëÿÿ$ÿ?ÿZÿuÿÿ¨ÿÀÿÖÿì)?Vo‰£½×ó+Gc€ž¼Úø8Xy›½ß%In“¹ß.W«Ö/]Œ¼íPƒ¶êUŒÃû4m§â  [ ˜ Ö  S ’ Ñ  N ‹ È  ? w ® ã  C m “ µ Ñ è ù ý ë Î ¦ r 0 â †  ¥  Œ ë ;}³Ýü$4E\{ÿ¥þÜþ ýoüÉü.ûûú›ú*ùÄùgùøÁøyø7÷ü÷È÷›÷v÷V÷:÷"÷ öúöêöÛöÏöÆö¾ö¹öµö´ö¶öºö¿öÇöÑöÝöêöú÷ ÷!÷8÷P÷j÷†÷£÷Â÷âøø%øGøjøø²ø×øüù"ùGùnù”ù»ùâú ú0úWú~ú¤úËúñûû=ûcûˆû®ûÓûøüü@ücü†ü¨üËüìýý/ýQýqý‘ý±ýÐýïþþ+þIþfþ„þ þ¼þØþôÿÿ*ÿEÿ_ÿyÿ“ÿ«ÿÂÿØÿì'=Sk„ž·Ñë <Xt­Êè%Dd…¥Æè -Pt™¾ã 0X€©Óþ*W…³âAr£Õ;o¤ÙDz±è Y ’ Ê  < t ¬ ã  M € ² á  9 ` ƒ £ ¾ Ô ä ï ò ï ã Î ¯ † R  È q ž ! ™ d·?v¥Ñû&UŠÿÇÿþ^ý¸ýüˆûþû}ûú˜ú4ù×ù‚ù3øëøªønø9ø ÷â÷¾÷ ÷…÷l÷W÷F÷6÷*÷ ÷÷÷÷÷÷÷÷!÷*÷6÷C÷S÷d÷x÷Ž÷¥÷¾÷Ù÷õøø0øOøoøø±øÓøõùù<ù`ù„ù©ùÎùóúú=úcúˆú®úÓúøûûAûfûŠû®ûÒûöüü<ü_üü£üÄüåýý&ýGýgý†ý¥ýÄýâþþþ;þWþsþþ«þÇþâþüÿÿ1ÿKÿeÿ~ÿ–ÿ®ÿÄÿÙÿí&:Pg€˜±Êãý1Lgƒž»×õ1OoŽ®Ïð3VyœÀå 0V}¥Îø#Oz§Ô/]Œ¼ìN€²äHz®á  H | ¯ á  D t ¢ Î ù " H l ª Ã Ø é ô ù ø ð á É ©  L  Æ t  ­ :»3 ]®ù?€ÀEÿÛÿ0þŒýñý^üÓüPûÖûcúúú˜ú>ùêùùVùøÙø¤øtøJø%ø÷ç÷Î÷¸÷¥÷•÷‡÷}÷u÷o÷l÷j÷k÷n÷t÷{÷„÷÷œ÷«÷»÷Î÷ã÷ùøø+øEøaø}ø›ø¹ø×ø÷ùù8ùZù|ùžùÀùãúú*úNúqú•ú¹úÝûû%ûHûkûŽû±ûÔû÷üü;ü\ü~üŸüÀüßýýý?ý^ý}ý›ý¹ý×ýôþþ.þJþeþ€þ›þ¶þÑþëÿÿÿ8ÿQÿjÿ‚ÿšÿ°ÿÆÿÚÿî$8Md{’ªÂÛô &@Zu«Çä;Yw–µÕõ7Y{žÁä-RxŸÇðBl—ÂíFr Íû)X†µä@ožÌû ( V ‚ ® Ø ' L o ­ È à ó       ô Ú ¸ \ ! Ü 5Ógóuï_È*†Þ3†Ú/ˆÿåÿGþ°þý•ýü—ü#û¶ûQúóú›úJùþù¹ùyù>ù øÚø°øŠøhøJø0øø÷ô÷æ÷Û÷Ò÷Ì÷È÷Æ÷Ç÷É÷Î÷Õ÷Ý÷ç÷ôøøø$ø8øMødø|ø”ø®øÉøåùùù<ù[ùzùšùºùÛùüúú?úaúƒú¦úÈúêû û/ûQûsû•û·ûØûúüü<ü\ü}üü½üÜüûýý9ýWýuý“ý°ýÍýêþþ"þ>þYþtþŽþ¨þÂþÜþõÿÿ&ÿ?ÿWÿoÿ†ÿÿ³ÿÈÿÜÿî#6K`w¤»Óë5Ngœ·Òí &C`~œ»Ùù:Z|¿á(Lq—½ä 3\„­×*UªÕ,W‚­Ø-W€©Òù E h Š ª È ã û  $ 3 > E G D < .  ÿ Ý ³ H »h ©=ÉNÊ@°„éM±}ÿèÿWþËþDýÃýIüÕügüû ûEúñú¢úYúùØùŸùkù<ùøìøÉø«øøyødøSøDø9ø/ø)ø$ø"ø"ø$ø(ø.ø6ø@øKøYøhøyøŒøŸø´øËøâøûùù.ùIùdùùžù»ùÙùøúú7úVúvú—ú¸úÙúúûû;û\û}ûû¾ûßûÿüü?ü^ü~üü¼üÚüùýý5ýRýoýŒý©ýÅýáýýþþ3þNþhþ‚þ›þ´þÍþæþþÿÿ.ÿFÿ]ÿtÿŠÿ ÿ¶ÿÊÿÝÿï"4H]rˆž´Êáù)AZsŒ¦ÀÚõ-Ifƒ ¾Üû9Yyš»Üþ!Dg‹°Õû!Hn•½ä 4\„¬Ôý%Lt›Áç 1Uw™ºÙö  + B V g v € ‡ Š ‰ ƒ x h R 6 꺂Cü®Yü™.»CÅAº0¥‰üpÿçÿaþßþbýêýxý ü¤üBûçû‘û@úõú¯únú2ùûùÉù›ùqùKù)ù øðøØøÃø±ø¢ø–øŒø…ø€ø}ø}ø~ø‚ø‡øŽø—ø¢ø¯ø¾øÍøÞøñùùù/ùEù]ùvùùªùÄùàùüúú6úTúrúú®úÍúíû û+ûJûiû‰û¨ûÈûçüü&üEücü‚ü ü¾üÛüùýý2ýOýlý‡ý£ý¿ýÚýõþþ*þDþ^þwþþ©þÁþÙþñÿÿÿ6ÿMÿcÿyÿÿ¤ÿ¸ÿÌÿÞÿð 2EYn‚˜­ÃØï4Ld}•¯Èâü2Nj†¢ÀÝû7Vu•µÕö8Z} Äè 1VzŸÅê5Z€¥Êî7Z|ž¾Þý7Rk‚˜ª»ÉÓÛßßÚÑIJ›\3Î’O·` 7ÈUÝaäeäbáaÿãÿhþðþ|þ ý¢ý<üÛüü)ûØû‹ûDûúÃú‰úTú#ùöùÍù¨ù‡ùiùNù6ù!ùùøóøéøáøÛøØø×ø×øÚøßøæøîøøùùù ù/ù@ùRùeùyùù¥ù½ùÕùîúú!ú;úVúrúú«úÈúåûû!û>û\ûzû˜û¶ûÔûòüü.üLüjü‡ü¤üÁüÝüúýý2ýNýjý…ý ýºýÕýïþ þ#þ<þUþnþ†þžþ¶þÎþåþüÿÿ(ÿ>ÿTÿiÿ~ÿ“ÿ§ÿ»ÿÎÿàÿð0BUi}‘¦ºÐåû(?Vm…µÎç6Ql‡£¿Ûø3Qo¬Ëë *KlްÒõ:]¢Åè -Pr”µÖö4Rn‰£»Òèü *4<AB?9. ô×µ_+ò³n#Ò| ¿Yïž*µ>ÈSÿßÿmþÿþ“þ+ýÈýiýü¸ügüûÒûûPûúÝúªú{úOú'úùâùÅùªù’ù}ùkù[ùNùDù;ù6ù2ù0ù0ù2ù6ù<ùCùLùWùcùpù~ùŽùŸù±ùÄùØùíúúú1úIúbúzú”ú¯úÊúåûûû8ûTûqûû©ûÆûâûÿüü9üVürüü«üÇüâüþýý4ýOýjý„ýžý¸ýÑýëþþþ6þOþfþ~þ•þ¬þÃþÚþðÿÿÿ1ÿFÿ[ÿoÿ„ÿ—ÿ«ÿ¾ÿÐÿáÿñ.?Rdw‹ž³ÇÜñ1G]t‹£»Óì8Rl†¡¼Øô-Ifƒ¡¿Ýû9Yy™ºÚû<\|½Þþ<[y—³Ïê2G[m}Œ˜¢ª¯±¯«¢–†rZ=ôÈ–`$ãQ¬Rô“.Ç_õ‰°DÿÚÿqÿ þ¨þGýëý’ý>üíü¡üYüûÖû›ûcû.úýúÐú¦úú\ú<úúùíùØùÆù¶ù¨ùù•ùŽùŠù‡ù†ùˆù‹ùù–ùžù§ù³ù¿ùÌùÚùêùûú úú3úHú]úsúŠú¡ú¹úÑúêûûû7ûRûlû‡û¢û½ûØûóüü+üFüaü}ü˜ü³üÎüéýýý8ýRýlý…ýžý·ýÐýéþþþ2þIþaþxþŽþ¤þ»þÑþçþüÿÿ%ÿ:ÿNÿbÿuÿ‰ÿœÿ®ÿÁÿÒÿãÿò +<N_q„—ª¾Òæú#8Ndz§¿×ï8Qjƒ¸Óî $?[w”°Íê%Cb€ž½Ûù5Tr®Ëè ;Tn†œ²ÆÙêù#(++'! ùä˯h=Ú¢d"Ü‘Bð™@ã…&Äaþš7ÿÕÿuÿþºþaþ ý¹ýjýüØü•üVüûâû­û{ûLû úøúÓú±ú’úuú[úDú0úúúùôùëùäùßùÜùÛùÛùÞùâùçùîù÷úú úú&ú4úDúTúfúxúŒú úµúÊúàúöû û%û=ûUûnû‡û û¹ûÓûíüü!ü<üVüpüŠü¤ü¾üØüñý ý$ý>ýWýoýˆý¡ý¹ýÐýèþþþ/þFþ\þsþ‰þŸþ´þÉþÞþóÿÿÿ/ÿCÿVÿiÿ|ÿÿ¡ÿ²ÿÄÿÕÿäÿó )9JZl~¢µÈÛî*?Si~”ªÁØð6Nf˜²Ìåÿ3Ni„Ÿ»Öò+Gd€œ¸Ôð )E`{–°Éâù&:M_o~‹— §¬¯°®©¡–ˆvaH, 羑`+ñ³r,ã—Gõ Jò˜=á†+ÿÐÿxÿ þËþyþ*ýÝý”ýNý üÎü’üZü%ûòûÃû–ûmûFû"ûúäúÈú®ú˜ú„úrúbúTúHú?ú8ú2ú/ú-ú-ú.ú2ú6ú=úDúMúWúbúoú}ú‹ú›ú«ú¼úÎúáúõû ûû3ûHû^ûuûŒû¤û¼ûÔûëüüü5üOügü€ü™ü²üÊüãüûýý-ýEý]ýuýý¤ý¼ýÓýêþþþ.þDþZþoþ…þšþ¯þÄþØþìþÿÿÿ&ÿ9ÿLÿ^ÿpÿ‚ÿ”ÿ¦ÿ¶ÿÇÿ×ÿæÿó '6FVfw‰š¬¾Ðãö /CXl–«ÂØî2Jay‘©ÂÚó %?YsŒ¦ÀÛõ*E_y“®Èâü.G_vŒ¡¶ÉÜíý #-4:=>=93*ýèϳ”qIð¾ˆNÑFý²dÂoÈsÿÌÿzÿ*þÜþþFýÿý»ý{ý>ýüËü–üdü4üûÝûµûûnûOû2ûúþúèúÔúÃú³ú¥úšúú‰úƒúú}ú|ú}ú€ú„úŠúú˜ú¡ú¬ú·úÄúÑúàúïúÿûû"û4ûGû[ûnûƒû˜û­ûÃûÙûðüüü5üLüdü{ü“üªüÂüÙüðýýý7ýNýfý}ý”ý«ýÁýØýîþþþ/þDþYþnþƒþ—þ«þ¿þÓþæþùÿ ÿÿ0ÿBÿTÿfÿwÿ‰ÿšÿªÿºÿÊÿÙÿçÿô %3BQaq‚“£´ÆØéü!3GZn‚–«ÁÖë-CZqˆŸ¶Îåý.F_w¨ÀÙò $<Tm…µÍäú%9M_qž«¶¿ÇÍÒÔÔÑÍÆ¼¯Ÿx`E&ß¶Š[)óº~@þºt,â—Kþ°cÿÉÿ}ÿ3þëþ¤þ`þýàý¥ýký5ýüÎüŸürüHü ûúû×û¶û˜û|ûbûJû5û"ûûúôúèúßú×úÑúÍúËúÊúÊúÌúÐúÕúÚúáúéúóúþû ûû#û1û@ûPûaûrû„û–û©û¼ûÐûäûùüü#ü9üNüeü{ü‘ü¨ü¾üÔüêýýý-ýCýYýoý†ýœý²ýÈýÞýóþþþ1þFþZþnþ‚þ•þ©þ¼þÏþáþôÿÿÿ)ÿ;ÿLÿ]ÿmÿ~ÿÿŸÿ¯ÿ¾ÿÍÿÛÿéÿõ "0>M\k{‹šª»ÌÝî$6H[n•©½Òæû%;Pf|’¨¿Öì1H_v¤¼Óê.DZp†›¯Ã×éû *8DOX`gknpnkf^TG8&ùßÁ }W-Ò k3ø¼}<ùµp)â›T ÿÆÿ€ÿ<þùþ¸þyþ=þýÌý–ýcý2ýü×ü­ü…ü_ü;üûûûÞûÃûªû“ûûlû[ûMû@û5û+û$ûûûûûûûûû#û)û1û9ûCûNûZûfûsûûû û°ûÁûÒûãûöüüü.üBüVüküü”ü©ü¿üÔüéüþýý(ý=ýRýgý|ý‘ý¦ý»ýÐýåýúþþ"þ6þIþ]þpþƒþ–þ¨þºþÍþßþðÿÿÿ$ÿ5ÿFÿVÿfÿuÿ…ÿ•ÿ¤ÿ³ÿÂÿÐÿÞÿêÿö  -:HWetƒ’¡°ÁÐáñ%7IZm’¥¸Ìàô1EZo„™¯ÄÚï0E[q†œ±ÆÛð-AUgz‹œ¬»ÉÖâíöþ  üòåÖİ™€dE#ÿØ®‚S!í·DËŒL ʈFÿÄÿ„ÿEÿþËþ‘þYþ$ýñý¿ýýaý5ý üäü¾ü›üyüZü<ü!üûïûÚûÆû´û¤û•û‰û~ûuûnûhûcû`û_û^û_ûbûfûjûpûwû~û‡û‘ûœû¨û´ûÁûÏûÝûìûüü üü.ü?üQücüvü‰üœü°üÃü×üëüÿýý'ý:ýOýbýwýŠýžý²ýÆýÚýîþþþ(þ<þNþaþsþ…þ—þªþ»þÌþÝþîþÿÿÿ ÿ0ÿ@ÿPÿ_ÿnÿ}ÿŒÿ›ÿ©ÿ¸ÿÆÿÓÿàÿìÿö *7DR_m{‰˜¦µÄÓãô%6GXi{Ÿ²ÅØëþ$8L`tˆœ°ÄØí)>Rfy ³ÆÙìþ!2BQ`mz†š¢©®²µ¶µ³®¨Ÿ•ˆyhU?& îϬˆa7 Ý­zFÙ f+ï³w:ÿþÿÂÿ‡ÿMÿþÞþ¨þuþCþýæý¹ýŽýfý?ýüöüÔüµü—ü{üaüIü2üü ûúûêûÜûÐûÆû½û¶û°û¬û¨û§û¦û§û©û¬û°ûµû»ûÃûËûÔûÞûéûôüü üü(ü7üFüVüfüvü‡ü˜ü©ü»üÎüàüòýýý*ý=ýPýbýuýˆý›ý®ýÀýÓýæýùþ þþ1þCþUþgþxþŠþ›þ¬þ½þÎþÞþîþþÿ ÿÿ-ÿ<ÿKÿZÿhÿwÿ…ÿ“ÿ¡ÿ®ÿ¼ÿÉÿÖÿâÿíÿ÷'3@LYfs€Žœª¸ÇÕåô#3CSdu‡˜«¼Îàò)<Obt‡š­ÀÓæù 1CUgxŠ›¬½ÍÝìû"-8AIPV[^_`^[VPG=1"ÿêÓ¹ž€_=ñÈžqBà­yC ÖŸg0ÿùÿÂÿŒÿVÿ"þðþ¾þþaþ5þ ýáý¹ý“ýoýLý*ý üíüÒü·üŸüˆüsü_üMü=ü/ü!üü üûüûöûòûïûíûìûìûîûñûõûùûÿüü üüü(ü3ü>üJüVücüqüüŽüœü¬ü¼üÌüÜüíüþýý ý1ýBýTýfýxý‰ý›ý¬ý¾ýÐýâýóþþþ)þ:þLþ]þnþþþ þ°þÀþÐþßþïþþÿ ÿÿ+ÿ9ÿHÿVÿdÿrÿ€ÿÿšÿ§ÿ´ÿÀÿÍÿÙÿäÿîÿø$0<GS_lx„‘Ÿ¬ºÈÖäó />N^n¡±ÂÓäõ*;M^p‚“¥·ÈÚëü .?O_o~›¨µÂÎÙãìôû    üôêÝÏ¿­š„lR5÷Õ±‹c:â´…U#ò¿ŒY'ÿôÿÂÿÿ_ÿ/ÿþÔþ¨þ}þUþ-þýâý¿ýý|ý]ý@ý$ý üòüÚüÅü±üŸüŽüüqüdüYüPüHüAü;ü6ü3ü1ü0ü1ü2ü4ü8ü<üAüGüNüUü^ügüqü{ü†ü’üžüªü·üÅüÓüáüðüÿýýý.ý>ýNý^ýnýýý ý±ýÁýÑýâýòþþþ$þ5þFþVþgþwþ‡þ—þ¦þ¶þÅþÔþãþñÿÿÿÿ+ÿ9ÿFÿTÿaÿoÿ{ÿˆÿ”ÿ¡ÿ­ÿ¹ÿÄÿÐÿÜÿæÿðÿø",7BMXdo{‡” ­»ÈÕãñÿ )8GWfv…•¤´ÄÔäõ&7GWgxˆ™©¹ÉÙè÷$2@MZfr~‰’›£ª°µº½¾¿¾¼¸³¬¤šŽraN9# ðÓµ–tQ,Þµ‹`3ت|MÿðÿÂÿ•ÿhÿ<ÿþèþÀþ™þsþNþ+þ ýèýÉý«ýŽýsýYýAý)ýýüíüÜüÍü¾ü±ü¥ü›ü’üŠüƒü~üyüvütüsüsütüvüyü}ü‚ü‡üü”üœü¥ü®ü·üÁüÌü×üãüïüûýýý$ý2ý@ýOý]ýlý{ýŠý™ý¨ý¸ýÈý×ýæýõþþþ$þ3þCþSþbþrþ‚þ‘þŸþ®þ¼þËþÚþçþõÿÿÿÿ,ÿ9ÿFÿSÿ`ÿlÿyÿ…ÿ‘ÿœÿ¨ÿ³ÿ¾ÿÉÿÔÿÞÿèÿñÿù)3=GR\gr}ˆ” ­¹ÅÒßìú"0?M\jx‡–¥³ÂÑáð-<K[jyˆ—¥³ÁÏÜê÷&1;ENV]chlprssrplf`XNC6(óÝÇ®”x[<ùÖ²Œe=ëÁ—mBÿíÿÃÿšÿqÿIÿ#þüþ×þ³þþnþNþ/þýôýØý½ý¤ýŒýuý`ýLý9ý(ýý üüüðüåüÛüÒüËüÅü¿ü»ü¸ü¶üµüµü¶ü·üºü½üÁüÆüÌüÒüÚüáüêüòüûýýýý&ý1ý>ýKýXýeýrýýýšý¨ý¶ýÄýÒýáýïýýþ þþ(þ6þEþTþbþpþþŽþœþªþ¸þÆþÓþáþîþûÿÿÿ"ÿ/ÿ;ÿHÿTÿ`ÿlÿxÿƒÿŽÿ™ÿ¤ÿ®ÿ¹ÿÃÿÍÿ×ÿáÿêÿòÿú &/8AJT^is~ˆ”Ÿ«¶ÂÎÛçó '4BO]jx†”¡¯½ÌÚèö .<JXerŒ˜¥±½ÈÓÝçñú "&(*++)&"ûïáÒ°œ‡pX>#éÊ©ˆeBøÒ¬†_9ÿëÿÅÿ ÿ{ÿVÿ3ÿþîþÌþ¬þþpþSþ7þþýêýÓý½ý¨ý”ýýpý`ýRýEý8ý-ý#ýýý ýüÿüûüùü÷üõüõüöü÷üùüüýýý ýýýý$ý,ý4ý=ýGýQý\ýgýrý~ýŠý–ý¢ý®ý»ýÈýÕýâýïýûþþþ#þ0þ=þKþXþfþsþ€þþ›þ©þ¶þÃþÐþÝþéþöÿÿÿÿ&ÿ3ÿ>ÿJÿUÿaÿlÿxÿ‚ÿÿ—ÿ¢ÿ«ÿµÿ¿ÿÈÿÑÿÚÿãÿìÿôÿú "*3;DMV_is}‡’œ§²½ÉÔàë÷(5ANZgtš§´ÁÎÛèõ(4@LWcny„Ž˜¡ª³»ÃÊÐÖÚÞáãååäâàÜ×ÑÉÀ¶«žp^J5ïÔ¹aA ÿÞ¼™vS0 ÿêÿÈÿ¦ÿ„ÿcÿCÿ#ÿþæþÈþ«þþvþ]þDþ,þþýíýÚýÇý¶ý¦ý˜ýŠý~ýsýiý_ýWýOýHýCý>ý;ý8ý6ý5ý4ý5ý6ý8ý:ý>ýBýFýLýRýXý_ýfýmývýýˆý’ýœý¦ý±ý¼ýÇýÒýÝýéýõþþ þþ%þ1þ=þIþUþaþnþzþ†þ’þŸþ«þ·þÃþÐþÜþèþôÿÿ ÿÿ!ÿ-ÿ8ÿCÿNÿXÿcÿnÿyÿƒÿÿ—ÿ¡ÿªÿ³ÿ¼ÿÅÿÍÿÖÿÞÿæÿîÿõÿû &.5=FNW_ir|…™£­¸ÂÍ×ãîù&1=IU`lw„›§³¿Ë×âíù$/9CMV_gow~…‹•™œŸ ¡¡ Ÿœ˜“†~tj^QC3#þéÔ½¥ŒrX<ãŦ‡hH) ÿêÿËÿ¬ÿŽÿpÿRÿ6ÿþþþãþÉþ°þ˜þþjþUþ@þ-þþ ýùýéýÛýÎýÁý¶ý¬ý¢ýšý’ý‹ý…ý€ý{ýxývýtýsýrýrýsýuýwýzý~ý‚ý‡ýŒý’ý˜ýžý¥ý­ýµý¾ýÆýÐýÙýãýìý÷þþ þþ!þ,þ7þBþMþXþdþnþyþ„þþ›þ¦þ±þ½þÈþÓþÞþêþõÿÿ ÿÿ ÿ*ÿ4ÿ?ÿIÿSÿ]ÿfÿpÿ{ÿ„ÿŽÿ—ÿ¡ÿ©ÿ²ÿºÿÃÿËÿÒÿÚÿáÿèÿðÿöÿü#)07?GNV^gpyŠ”§°ºÃÍØâìö  +5@JU`ku€‹–¡«¶ÀÊÔÞèñû '.5<BHMRVZ\^```_]ZWRMF>5+ ùêÚɶ¢ŽxbJ2ÿäÉ®“w[?"ÿêÿÏÿ³ÿ—ÿ|ÿbÿHÿ.ÿþýþæþÏþ¹þ¥þ‘þ}þkþYþIþ9þ*þþþýøýíýäýÛýÔýÍýÆýÁý¼ý¸ýµý³ý±ý°ý¯ý¯ý°ý±ý³ý¶ý¹ý½ýÁýÆýËýÑý×ýÝýäýëýóýûþþ þþþ&þ0þ:þDþMþWþaþkþuþ€þŠþ”þžþ¨þ²þ¼þÆþÐþÚþäþïþùÿÿÿÿ"ÿ+ÿ5ÿ>ÿGÿQÿZÿcÿlÿuÿ~ÿ‡ÿÿ™ÿ¢ÿªÿ²ÿ¹ÿÁÿÉÿÐÿ×ÿÝÿäÿëÿòÿøÿü %+18?FMU\elt|…–ž§°¹ÂËÔÞçñú  *3=GQZdnwŠ“¥¯·ÀÈÑÙáèïöü   !! øïæÛϵ¦–…taN:%ùáɱ™hO6ÿëÿÓÿºÿ¡ÿ‰ÿqÿZÿCÿ,ÿÿþíþÚþÇþµþ¤þ“þ„þuþgþZþMþAþ7þ-þ#þþþ þþýûý÷ýóýðýîýìýëýêýêýëýíýîýñýóý÷ýûýÿþþ þþþþ þ'þ.þ6þ=þEþMþUþ^þgþpþyþþŠþ”þþ¦þ¯þ¸þÁþÊþÓþÜþåþîþ÷ÿÿ ÿÿÿ&ÿ/ÿ8ÿ@ÿIÿRÿZÿbÿkÿsÿ{ÿƒÿŒÿ“ÿ›ÿ¤ÿ«ÿ³ÿºÿÁÿÈÿÏÿÕÿÛÿáÿèÿîÿôÿùÿý  &+17=DKRY`gnv}…Œ”œ¤­µ½ÆÎÖÞçïø #,4=ENV_gow‡Ž–¥«²¸¾ÄÉÎÒÖÚÝßáâãããâàÞÚÖÒÌž¶­£™tfWG6%îÚŰ›†pZD.ÿìÿÖÿÀÿ«ÿ•ÿ€ÿkÿWÿDÿ0ÿÿ þúþêþÚþËþ¼þ®þ¢þ•þ‰þ~þtþjþaþYþQþJþDþ>þ9þ5þ1þ.þ+þ)þ'þ&þ%þ%þ&þ'þ)þ+þ-þ0þ4þ7þ<þ@þEþJþOþUþ[þaþhþoþvþ}þ…þŒþ”þœþ¤þ¬þ´þ¼þÄþÌþÔþÜþäþìþôþüÿÿ ÿÿÿ%ÿ-ÿ6ÿ>ÿFÿNÿVÿ]ÿeÿmÿtÿ|ÿƒÿŠÿ‘ÿ™ÿ ÿ§ÿ®ÿµÿ¼ÿÃÿÉÿÏÿÕÿÚÿàÿæÿëÿñÿöÿúÿý !&+05;BHMTZ`gnt{‚‰—Ÿ¦®µ½ÃËÒÚáéðø%-4;BIQW^ekqw}‚ˆ‘–™ ¢¤¦§§¨§¦¥¢Ÿœ—’Œ†~vndZPD7* þïßν«™†taN;'ÿíÿÚÿÇÿ´ÿ¡ÿÿ}ÿkÿZÿJÿ9ÿ*ÿÿ þþþñþäþØþÍþÂþ·þ®þ¥þþ•þþ†þ€þ{þvþqþmþjþgþdþbþaþ`þ_þ_þ`þ`þbþdþfþiþlþoþrþvþ{þþ„þ‰þŽþ“þ™þŸþ¦þ¬þ³þºþÁþÇþÎþÕþÜþãþëþòþøþÿÿÿÿÿÿ#ÿ*ÿ1ÿ8ÿ@ÿGÿNÿVÿ]ÿdÿkÿqÿxÿÿ†ÿŒÿ’ÿ™ÿŸÿ¦ÿ¬ÿ³ÿ¹ÿ¿ÿÅÿËÿÐÿÕÿÚÿßÿåÿêÿïÿóÿ÷ÿûÿþ  %).38=BHMSX^djpv|‚ˆ•œ£©¯µ¼ÂÉÏÖÜãéðöý "(.49?DINRW[^adgikllmmlkjhfc_ZUOHA:2)  ÿóæÙ̾°¡’‚rbRB1 ÿÿÿïÿÞÿÎÿ¾ÿ®ÿžÿÿ€ÿqÿcÿUÿGÿ:ÿ.ÿ"ÿÿ ÿþøþîþåþÝþÕþÎþÇþÁþ»þµþ°þ¬þ¨þ¤þ¡þŸþþ›þšþ™þ™þ™þ™þšþ›þœþžþ þ£þ¦þ©þ¬þ°þ´þ¸þ¼þÀþÅþÊþÐþÕþÛþáþçþíþóþøþþÿÿ ÿÿÿÿ#ÿ)ÿ/ÿ5ÿ<ÿBÿHÿNÿTÿZÿ`ÿgÿnÿtÿzÿÿ…ÿ‹ÿ‘ÿ—ÿœÿ¢ÿ¨ÿ­ÿ³ÿ¸ÿ¾ÿÃÿÈÿÍÿÒÿ×ÿÛÿàÿåÿéÿîÿòÿõÿùÿüÿþ #&*/38<AEJOTY_cimsx~ƒ‰Ž”™Ÿ¤©¯´º¿ÅÊÐÕÛáæëðõúÿ  "%(+-/1233333210.,($úòêàÖÌÁ¶«Ÿ“‡zm_RD7( ÿþÿñÿãÿÕÿÈÿºÿ­ÿ ÿ”ÿ‡ÿ|ÿpÿeÿZÿOÿEÿ<ÿ3ÿ*ÿ"ÿÿÿ ÿþþþùþóþîþéþäþàþÝþÚþØþÖþÔþÓþÒþÑþÑþÑþÑþÒþÓþÔþÕþ×þÙþÛþÞþáþäþçþêþîþòþöþúþÿÿÿ ÿÿÿÿÿ"ÿ&ÿ,ÿ1ÿ6ÿ<ÿAÿFÿKÿPÿUÿZÿ`ÿeÿjÿoÿtÿzÿ€ÿ…ÿŠÿÿ”ÿ˜ÿžÿ¢ÿ§ÿ¬ÿ±ÿ¶ÿ»ÿ¿ÿÄÿÈÿÍÿÑÿÖÿÚÿÝÿáÿæÿêÿîÿñÿõÿ÷ÿúÿýÿÿ "&)-148<@DHMQUY]bfkotx}‚†‹”˜¡¦ª¯´¹½ÁÅÉÍÑÕÙÝáåèëîñôöøùúûûûûûûûúùøöóïëæáÜ×ÒÌÆ¿·¯¦”‹wmcXMB7+  ÿþÿóÿèÿÝÿÒÿÇÿ¼ÿ²ÿ¨ÿžÿ”ÿ‹ÿ‚ÿyÿpÿhÿ`ÿXÿQÿJÿDÿ>ÿ8ÿ3ÿ.ÿ)ÿ$ÿÿÿÿÿÿÿ ÿ ÿ ÿ ÿÿÿÿÿÿÿ ÿ ÿ ÿ ÿ ÿÿÿÿÿÿÿÿ"ÿ%ÿ)ÿ-ÿ1ÿ5ÿ9ÿ=ÿAÿFÿJÿNÿRÿVÿ[ÿ_ÿdÿhÿlÿpÿtÿyÿ}ÿ‚ÿ†ÿŠÿŽÿ“ÿ—ÿœÿ ÿ¤ÿ¨ÿ¬ÿ°ÿ´ÿ¸ÿ¼ÿÀÿÄÿÈÿÌÿÏÿÓÿ×ÿÚÿÞÿáÿäÿèÿëÿïÿòÿõÿ÷ÿúÿüÿþÿÿ  "%(+.158;?BEILPSWZ^bfjmqtx{‚†ŠŽ’•˜›Ÿ¢¥¨«®±´·º¼¾ÀÂÃÄÅÅÅÅÅÅÅÅÅÄÿ¼¸´°¬¨¤ ›–‰‚{tld\TLD;3*!ÿþÿöÿîÿåÿÜÿÓÿËÿÃÿ»ÿ´ÿ¬ÿ¥ÿžÿ—ÿÿ‰ÿ‚ÿ|ÿvÿqÿlÿhÿdÿ`ÿ\ÿXÿTÿPÿLÿIÿFÿDÿBÿ@ÿ?ÿ>ÿ=ÿ=ÿ=ÿ=ÿ=ÿ=ÿ=ÿ=ÿ>ÿ?ÿ@ÿAÿBÿDÿEÿGÿIÿLÿNÿQÿTÿWÿZÿ]ÿ`ÿcÿfÿjÿmÿqÿtÿwÿzÿ~ÿ‚ÿ…ÿ‰ÿŒÿÿ’ÿ–ÿšÿÿ¡ÿ¤ÿ§ÿªÿ®ÿ²ÿµÿ¹ÿ¼ÿ¿ÿÂÿÅÿÈÿËÿÏÿÒÿÕÿØÿÛÿÞÿàÿãÿæÿèÿëÿîÿñÿóÿõÿ÷ÿúÿüÿþÿÿ !$&(+-0358:=?BEHKNQSVX[]`cfilnpsuxz|ƒ…‡‰‹Ž‘‘‘‘‘‘‘‘‘‘‘Ї„~{xurnje`[UOIC=71+$ ÿþÿùÿóÿìÿæÿàÿÚÿÔÿÎÿÈÿÃÿ½ÿ¸ÿ³ÿ®ÿ©ÿ¤ÿŸÿ›ÿ—ÿ”ÿ‘ÿŽÿ‹ÿˆÿ…ÿ‚ÿÿ|ÿyÿwÿuÿsÿrÿqÿpÿpÿpÿpÿpÿpÿpÿpÿpÿpÿqÿrÿsÿtÿuÿvÿwÿyÿ{ÿ}ÿÿÿƒÿ…ÿ‡ÿŠÿŒÿŽÿ‘ÿ”ÿ–ÿ™ÿ›ÿÿ ÿ£ÿ¦ÿ¨ÿ«ÿ­ÿ¯ÿ²ÿµÿ¸ÿºÿ½ÿ¿ÿÁÿÄÿÇÿÊÿÌÿÏÿÑÿÓÿÕÿØÿÚÿÜÿßÿáÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿ÷ÿùÿúÿüÿþÿÿ !#$&')+-/13578:;=?ACEGHJKMOPRSUVXYZ\]^^_____________^\ZXVTRPNLJHEB?;73/+'# ÿÿÿûÿøÿôÿðÿìÿèÿäÿàÿÜÿØÿÕÿÑÿÎÿÊÿÇÿÄÿÁÿ¾ÿ¼ÿºÿ¸ÿ¶ÿ´ÿ²ÿ°ÿ®ÿ¬ÿªÿ¨ÿ¦ÿ¤ÿ£ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ¢ÿ£ÿ¤ÿ¤ÿ¥ÿ¦ÿ§ÿ¨ÿªÿ«ÿ¬ÿ®ÿ¯ÿ±ÿ²ÿ´ÿµÿ·ÿ¹ÿ»ÿ¼ÿ¾ÿ¿ÿÁÿÃÿÅÿÇÿÈÿÊÿËÿÍÿÏÿÑÿÓÿÔÿÖÿ×ÿÙÿÛÿÝÿßÿàÿâÿãÿåÿæÿèÿéÿëÿíÿîÿðÿñÿòÿôÿõÿöÿøÿùÿúÿûÿüÿýÿþÿÿ  !"#$$%&'(()*++,--..//////////////.-,+*)('&%$#"! ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿíÿëÿéÿçÿæÿäÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÒÿÓÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÝÿÞÿßÿßÿàÿáÿâÿãÿäÿåÿåÿæÿçÿèÿéÿêÿëÿëÿìÿíÿîÿïÿðÿñÿñÿòÿóÿôÿôÿõÿöÿ÷ÿøÿøÿùÿúÿúÿûÿüÿüÿýÿýÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿþÿþÿþÿþÿþÿþÿþÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿþÿþÿþÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿ  !"#$%&'()*+,-./012345567889::;;;;;;;;;;;;;;;;;;::99876543210/.-,+*)('&%$#"!  ÿÿÿÿÿÿÿÿÿÿÿþÿþÿþÿþÿþÿýÿýÿüÿüÿüÿüÿüÿûÿûÿûÿûÿúÿúÿúÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿùÿúÿúÿûÿûÿûÿüÿüÿýÿýÿþÿþÿþÿÿ !#%'(*,.02468:<>@BDFHJLNPRTVXZ\^`bdfhjlmoprstuvwwwwwwwwwwwwwwwwvvutrqomkigeca_][YWUSQOMKIGECA?<:7530.+)'%"  ÿÿÿÿÿþÿþÿþÿýÿýÿüÿüÿüÿûÿûÿúÿúÿùÿùÿùÿøÿøÿ÷ÿ÷ÿ÷ÿöÿöÿõÿõÿõÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿôÿõÿõÿöÿ÷ÿ÷ÿøÿøÿùÿúÿûÿüÿüÿýÿþÿÿ  "%'*,.1369;>@CFILORUX[^behknqtwz}€ƒ†‰Œ’•˜›ž¡£¦¨ª¬®°²³´µµµµµµµµµµµµµµ´³²±¯­«©¦£ š—”‘Ž‹ˆ…‚|yvspmjgc`\XUQNJFC?<851.*'$! ÿÿÿÿÿÿÿþÿþÿýÿüÿüÿûÿûÿúÿúÿùÿøÿøÿ÷ÿ÷ÿöÿõÿõÿôÿôÿóÿóÿòÿñÿñÿðÿðÿïÿïÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿîÿïÿðÿñÿòÿóÿóÿôÿõÿöÿ÷ÿùÿúÿûÿüÿþÿÿ !$'*-036:=@CFJNQTX[_cgkosw{€„‰‘•™¡¥©­±µ¹½ÁÅÉÍÑÕÙÜßâåèëîðòóôõõõõõõõõõõõõôóòðîìéæãàÝÙÕÑÍÉÅÁ½¹µ±­©¥¡˜”‹‡‚}xsoje`[WRMHD?;62.)%  ÿÿÿÿÿþÿþÿýÿüÿûÿûÿúÿùÿùÿøÿ÷ÿöÿõÿõÿôÿóÿòÿòÿñÿðÿðÿïÿîÿíÿìÿìÿëÿêÿêÿéÿéÿèÿèÿèÿèÿèÿèÿèÿèÿèÿèÿèÿèÿèÿèÿèÿèÿéÿêÿëÿíÿîÿïÿðÿñÿòÿôÿöÿ÷ÿùÿûÿýÿþÿÿ  #'+/37;>BFJOSVZ_chlpuy~ƒˆ’—¢¨­²¸½ÂÇÌÒ×Üáæëðõúÿ "&*-02456777777777765420-*'# ûöñìçâÝØÒÍǼ·±«¥Ÿ™“‡{uoic]WRLFA;60*$ ÿÿÿÿÿþÿýÿüÿûÿúÿùÿøÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿëÿêÿéÿèÿçÿæÿåÿäÿäÿãÿâÿâÿâÿáÿáÿàÿàÿàÿàÿàÿàÿàÿàÿàÿàÿáÿâÿãÿäÿåÿæÿèÿéÿëÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ $(,15:?CHMQV[`ejotz…Е𠦬²¹¿ÆÌÒÙßæìòùÿ %+17=CHMRW\afjnqtvxyz{{{{{{{{zyxvtqnjfb]XSNID?93-'!úóìæßØÑÊü´¬¥ž—‰‚zskd^WPIB<5-&  ÿÿÿÿÿþÿýÿüÿûÿúÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿáÿàÿßÿÞÿÝÿÜÿÜÿÛÿÛÿÚÿÚÿÙÿÙÿÙÿÙÿÙÿÙÿÙÿÙÿÙÿÙÿÚÿÛÿÜÿÝÿßÿàÿâÿäÿæÿèÿêÿìÿïÿòÿõÿ÷ÿúÿýÿÿ !&+05:@EKPV[agmrx~„Š‘—¤ª±·¾ÅÌÓÛâêñù&.6>EMT\cjqx~„Š–œ¢§¬°´·º¼¾¿ÀÁÁÁÁÁÁÀ¿¾¼¹¶³¯«§¢—‘‹…ysle^WOH@80( øïçÞÕÍļ´«£š‘‰€xpg_WOG?6.& ÿÿÿÿÿýÿüÿûÿúÿùÿ÷ÿöÿõÿôÿóÿñÿðÿïÿîÿìÿëÿéÿèÿçÿåÿäÿãÿâÿáÿßÿÞÿÜÿÛÿÙÿØÿ×ÿÖÿÕÿÕÿÔÿÓÿÒÿÒÿÑÿÑÿÑÿÑÿÐÿÐÿÐÿÑÿÑÿÑÿÒÿÓÿÔÿÖÿØÿÚÿÜÿÞÿàÿãÿæÿéÿìÿïÿòÿöÿùÿü !'-39?DJQW]djqx…Œ“𡍝·¾ÆÎÕÝåìõý )2;CLU^gpy‚Š“›¤¬´»ÂÉÐÖÝãéîó÷ûÿ    þúöòíèãÝ×ÑÊüµ®¦ž–…|tkaXOE<2) ÷îäÛÑǽ³¨Ÿ•Œ‚xoe[RI@6-$ ÿÿÿÿÿþÿüÿûÿúÿùÿ÷ÿöÿôÿóÿòÿðÿîÿíÿìÿëÿéÿçÿæÿäÿâÿáÿßÿÞÿÜÿÛÿÙÿØÿÖÿÕÿÓÿÒÿÐÿÏÿÎÿÎÿÍÿÌÿËÿÊÿÊÿÊÿÉÿÉÿÈÿÈÿÉÿÉÿÉÿÊÿËÿÌÿÍÿÏÿÑÿÓÿÖÿØÿÛÿÞÿáÿåÿéÿìÿðÿôÿøÿü  &-4:AHNU\dkrz‰˜ §¯·¿ÇÐØáêóü  *4>HR\fpz„Ž™£­·ÁËÕÞçðù &,27<AEHKMOQRRRQPOMJGD@;61+% úñéà×Îĺ±§’ˆ}rg]RG<1%ùîâ×ËÀµªŸ”‰~sh^SI?5* ÿÿÿÿÿþÿýÿûÿúÿøÿ÷ÿõÿôÿòÿðÿïÿíÿëÿêÿèÿçÿåÿãÿáÿßÿÝÿÛÿÚÿØÿÖÿÕÿÓÿÑÿÏÿÎÿÌÿËÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÂÿÂÿÁÿÁÿÀÿÀÿÁÿÁÿÁÿÂÿÃÿÄÿÆÿÈÿÊÿÍÿÏÿÒÿÕÿÙÿÝÿáÿåÿéÿîÿòÿ÷ÿü %,3:BJQX`iqyВ𢫴¼ÆÎ×àêóý%/9CNYep|‡’©´ÀË×âíø$.7@IR[cjqw}ƒˆ“–™šœœœ›š˜•’‹‡|vpib[SJA8/%üñæÛÐĸ¬ ”ˆ|pcVJ=1$ ÿòåØÌ¿³§›Ž‚vj^RG<0%ÿÿÿþÿýÿüÿúÿùÿ÷ÿõÿôÿòÿðÿîÿìÿêÿéÿçÿåÿãÿáÿßÿÝÿÚÿØÿÖÿÔÿÒÿÐÿÏÿÍÿËÿÉÿÇÿÅÿÄÿÂÿÁÿÀÿ¿ÿ¾ÿ½ÿ¼ÿ»ÿºÿºÿºÿ¹ÿ¹ÿ¹ÿ¹ÿºÿºÿ»ÿ¼ÿ½ÿ¿ÿÁÿÄÿÇÿÉÿÍÿÐÿÔÿÙÿÝÿâÿçÿìÿñÿöÿû "*2:BJRZclu~‡™¢¬µ¾ÈÒÜåïù#/:EP[gsŒ˜¥±¾Ê×äñþ $0=IUalv€Š”ž§¯·¾ÅËÑÖÚÝàãåæççæäâßÜØÓÎÉüµ®¦ž•‹wmcXL@4(öéÜÎÁ´¦˜Š|naSE7) ÿñãÕǺ¬ž‘ƒvi\OC6* ÿÿÿþÿüÿûÿùÿ÷ÿõÿôÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿ¾ÿ½ÿ»ÿºÿ¸ÿ·ÿ¶ÿµÿ´ÿ³ÿ²ÿ²ÿ²ÿ±ÿ±ÿ±ÿ±ÿ²ÿ²ÿ³ÿ´ÿ¶ÿ¸ÿºÿ½ÿÀÿÃÿÇÿËÿÏÿÔÿÙÿßÿäÿêÿïÿõÿû&/7@IR[dnx‚Œ–Ÿ©³½ÈÒÝçòý)5AMYfr‹˜¥³ÁÏÝêø#1@N\iw„’ž«·ÂÍØãíöÿ!%)-/133320-*'" üôëâØÎø­¡•ˆ{naSE7) þïàѳ£”…vfWG8) ûìÜ;¯ ‘ƒtfXJ<.! ÿÿÿþÿýÿûÿúÿ÷ÿöÿôÿòÿïÿíÿëÿéÿçÿäÿâÿàÿÝÿÛÿØÿÕÿÒÿÐÿÎÿÌÿÉÿÇÿÅÿÃÿÀÿ¾ÿ¼ÿºÿ¸ÿ¶ÿµÿ³ÿ²ÿ°ÿ¯ÿ­ÿ¬ÿ«ÿ«ÿªÿªÿªÿ©ÿ©ÿªÿªÿ«ÿ¬ÿ­ÿ¯ÿ±ÿ´ÿ·ÿºÿ½ÿÁÿÆÿÊÿÐÿÕÿÛÿáÿèÿîÿõÿû "+4>GQZdny„™¤®¹ÄÏÛæòý  ,8EQ^kx†”¢°¾ÌÛêù'6FVeu…”£²ÁÏÝëø)4?HQYagmsw{~€‚€~{wsnic\UMD;1'ùìßÒ͍™Š{l]M=- üìÛʺ©™ˆwfUE4#ñáÐÀ¯Ÿ€p`QB3% ÿÿÿÿÿþÿüÿúÿøÿöÿôÿòÿðÿíÿëÿèÿæÿäÿáÿßÿÜÿÙÿÖÿÓÿÐÿÍÿËÿÉÿÆÿÄÿÁÿ¿ÿ¼ÿºÿ¸ÿµÿ³ÿ²ÿ°ÿ®ÿ¬ÿªÿ©ÿ§ÿ¦ÿ¤ÿ£ÿ¢ÿ¢ÿ¡ÿ¡ÿ¡ÿ¡ÿ¡ÿ¢ÿ¢ÿ¤ÿ¥ÿ§ÿªÿ­ÿ°ÿ´ÿ·ÿ¼ÿÀÿÅÿËÿÑÿØÿßÿæÿìÿôÿû &0:DNXcmy„›§²¾ÉÖâîú ,9FS`n|Š˜§¶ÅÔäó$4EVgx‰š«¼ÍÞîþ-<JWdq}‰“¦®¶¼ÂÇËÎÐÒÒÑÐÍÊÆÂ¼¶°¨ —ƒxmaUH;-òâÓò¢‘€n]L:(òàμª˜†taO=+ôãÑ¿­‹ziXH8( ÿÿÿþÿýÿûÿùÿ÷ÿõÿóÿðÿîÿëÿéÿæÿäÿáÿÞÿÛÿØÿÕÿÒÿÎÿÌÿÉÿÆÿÄÿÁÿ¾ÿ¼ÿ¹ÿ·ÿ´ÿ²ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿ ÿžÿœÿ›ÿšÿ™ÿ™ÿ˜ÿ˜ÿ˜ÿ˜ÿ™ÿšÿœÿžÿ ÿ£ÿ¦ÿ©ÿ­ÿ²ÿ¶ÿ»ÿÁÿÇÿÍÿÔÿÜÿãÿëÿóÿû  *5@JU`kwƒœ¨´ÁÍÚçô)7DR`n|‹š©¸ÈØéù ,>Oas†˜«½Ðâõ+=O`p€Ÿ­»ÉÕáëõþ  "$$#! þöíãØÍÁµ¨›~o`P@/ üêØÆ³¡Ž{hUA.óà̹¥‘~jWC/õâϼ©—…r`N=,ÿÿÿþÿüÿûÿøÿöÿôÿñÿîÿìÿéÿçÿãÿáÿÞÿÛÿ×ÿÔÿÑÿÍÿÊÿÇÿÄÿÁÿ¾ÿ»ÿ¹ÿ¶ÿ³ÿ±ÿ®ÿ¬ÿ©ÿ§ÿ¤ÿ¢ÿŸÿÿ›ÿ™ÿ—ÿ•ÿ”ÿ’ÿ‘ÿÿÿÿÿÿÿ‘ÿ’ÿ”ÿ–ÿ˜ÿ›ÿŸÿ¢ÿ§ÿ«ÿ°ÿ¶ÿ¼ÿÂÿÉÿÑÿÙÿáÿéÿòÿû#.9EQ\huŽ›¨µÃÐÞëù#1?N\kz‰˜¨¸ÉÙêû 0BUh{Ž¢¶ÊÞò.BVj~‘£µÇØéø#0<FPX`glqtwxxwusoje^WOF<1% þðâÓó¢‘n[I6#üèÔÀ«–‚mXC.ïÚŰ›†q\F1ôßË·£{hUB0ÿÿÿþÿüÿúÿøÿõÿóÿðÿìÿêÿçÿäÿáÿÞÿÛÿØÿÔÿÐÿÍÿÊÿÆÿÃÿ¿ÿ½ÿ¹ÿ¶ÿ³ÿ±ÿ®ÿ«ÿ¨ÿ¥ÿ¢ÿŸÿÿšÿ—ÿ•ÿ“ÿ‘ÿÿÿ‹ÿ‰ÿˆÿ‡ÿ†ÿ†ÿ†ÿ†ÿ‡ÿˆÿ‰ÿ‹ÿŽÿ‘ÿ”ÿ—ÿ›ÿ ÿ¥ÿ«ÿ±ÿ·ÿ¾ÿÅÿÍÿÖÿßÿèÿñÿû&2>KWdq~‹™¦´ÃÑßîü (7GVeu…•¥µÆ×èú 0CVj~“§¼Ñçü(>Ti•ª¿Ôèü"4EUetŽ™¤­µ½ÃÇËÍÎÎÍÌÉÅÀº²«¢˜tgYJ:+ ÷åÓÀ­™…q\G2òÜÆ¯™ƒlV?)üåϸ¢‹t^G1ðÚįš„o[G4!ÿÿÿýÿûÿùÿ÷ÿôÿñÿîÿêÿçÿäÿáÿÞÿÛÿØÿÕÿÑÿÍÿÉÿÆÿÂÿ¾ÿ»ÿ¸ÿ´ÿ±ÿ®ÿ«ÿ¨ÿ¥ÿ¡ÿžÿ›ÿ—ÿ”ÿ’ÿÿŒÿŠÿˆÿ†ÿƒÿÿ€ÿ~ÿ}ÿ}ÿ|ÿ}ÿ}ÿ~ÿÿ€ÿƒÿ…ÿˆÿŒÿÿ”ÿ™ÿŸÿ¥ÿ«ÿ²ÿºÿÁÿÊÿÓÿÜÿæÿñÿû)6CP]ky‡•¤²ÁÐàïÿ-<L]m}ŽŸ°ÁÒäö.AUi~’¨¾Ôê0G_w¦½Õì/EYn”¥¶ÆÕâïú  $'(('%" öìàÓŶ§—†ucQ=*íØÃ­—jS<%öÞÆ¯–~fN6îÖ¾¦Žu^F/éÒ»¤waL7$ÿÿÿþÿýÿûÿøÿöÿóÿïÿìÿèÿåÿáÿÞÿÛÿØÿÕÿÒÿÎÿÊÿÆÿÂÿ¾ÿºÿ·ÿ³ÿ¯ÿ¬ÿ©ÿ¦ÿ¢ÿžÿ›ÿ—ÿ“ÿÿÿŠÿ‡ÿ„ÿ‚ÿÿ}ÿzÿxÿvÿuÿtÿsÿsÿsÿtÿuÿvÿwÿzÿ}ÿ€ÿ„ÿˆÿÿ’ÿ˜ÿŸÿ¦ÿ­ÿµÿ½ÿÆÿÐÿÚÿäÿðÿû,:HVdrŸ¯¾ÎÞïÿ/?Parƒ”¦¸ÊÜï(<Pez¥»Òê2Ke~˜±Ëäý/H`x¦»Ðåø +:GS^hpw|€ƒ„„ƒ}xrjaXMA4&÷æÔÁ®š…p[E/êÒº¢ŠqY@' ôÛÁ§Žt[A'ôÛÁ§Žt[C*ùàǯ—hQ;&ÿÿÿþÿüÿúÿ÷ÿôÿñÿíÿéÿæÿâÿßÿÜÿØÿÕÿÒÿÏÿÊÿÆÿÁÿ½ÿ¹ÿµÿ²ÿ®ÿªÿ§ÿ£ÿ ÿ›ÿ—ÿ”ÿÿŒÿˆÿ…ÿ‚ÿ~ÿ{ÿyÿvÿsÿpÿnÿlÿkÿjÿjÿiÿiÿjÿkÿlÿnÿqÿtÿxÿ|ÿÿ†ÿ‹ÿ‘ÿ˜ÿ ÿ¨ÿ°ÿ¹ÿÃÿÍÿ×ÿãÿïÿû!/>L[jz‰šª»ËÜìþ 0BRdvˆ™¬¿Òåø  4I]s‰Ÿ¶Íåý/Idš¶Ñí#>Yt©ÃÜô "8Mas„”¢¯»ÅÎÕÛßâääâßÛÕÎÆ¼²¦™‹|l[I7#úåη ‰qYA(õܨsX="ìѶ›€eI.øÝ¦ŒqW<"îÔº¡ˆoV?)ÿÿÿþÿüÿùÿöÿóÿðÿëÿèÿäÿáÿÝÿÚÿÖÿÓÿÏÿËÿÇÿÂÿ½ÿ¹ÿµÿ±ÿ­ÿ©ÿ¥ÿ¡ÿÿ™ÿ•ÿ‘ÿÿ‰ÿ…ÿÿ}ÿyÿvÿrÿoÿlÿjÿgÿeÿcÿbÿaÿ`ÿ`ÿ`ÿ`ÿaÿcÿeÿhÿkÿoÿtÿyÿ~ÿ„ÿ‹ÿ’ÿšÿ¢ÿ«ÿµÿ¿ÿÊÿÕÿáÿîÿú#2BQaq’£´Æ×éú 0BSfx‹°Ã×ëÿ(=Si–­ÅÝö)C^z—´Ñï *Gd‚Ÿ¼Øõ+E_wŽ¥ºÍàñ&07=BEFFDA<6.%ôåÕñž‰t_H1çε›gL1ûßæŠnQ5ûßÂ¥ˆkN2ùÜ¿£‡kO3üàÅ«u\C,ÿÿÿýÿûÿøÿöÿòÿîÿêÿæÿâÿÞÿÛÿ×ÿÔÿÐÿËÿÇÿÂÿ¾ÿ¹ÿµÿ±ÿ­ÿ¨ÿ¤ÿ ÿ›ÿ—ÿ’ÿŽÿŠÿ†ÿ‚ÿ}ÿyÿuÿpÿmÿiÿfÿcÿ`ÿ^ÿ[ÿZÿXÿWÿVÿVÿVÿWÿXÿZÿ\ÿ_ÿbÿfÿkÿpÿvÿ}ÿ„ÿ‹ÿ“ÿœÿ¦ÿ±ÿ»ÿÆÿÓÿßÿíÿú%5FVgw‰›­¿Ñãö.ASfy ³ÇÛð/E\r‰¡¹Ñê9UqެËê (Hh‡§Çæ$B`|™´Îçÿ+?QbqŠ”£¨«¬«©¦ ™‘‡{oaQA/ ôÞȰ˜fK0úßç‹nQ4ùÛ½ŸcE'êË­ŽpQ3÷Ù»€bE' îÑ´˜|aH/ÿÿÿýÿûÿøÿõÿñÿíÿèÿäÿàÿÜÿÙÿÕÿÑÿÍÿÈÿÃÿ¾ÿºÿµÿ±ÿ­ÿ¨ÿ¤ÿŸÿšÿ•ÿ‘ÿŒÿ‡ÿƒÿÿzÿvÿqÿlÿhÿdÿaÿ]ÿZÿWÿTÿRÿPÿNÿMÿLÿLÿLÿMÿNÿPÿRÿVÿYÿ]ÿbÿgÿnÿuÿ|ÿ„ÿÿ–ÿ¡ÿ¬ÿ·ÿÃÿÐÿÝÿëÿù'8I[l~£¶ÉÜï*=QdxŒ¡µÉÞó4Kby‘©ÂÜö+GdŸ¾Þÿ Bd…§Éë /Pq’±Ðï (C]vŒ¢µÇ׿òý ÷ìßѲ ycM6ëд˜{^A$éˬnO0ñѲ’rR2ñѱ‘qQ2òÓ´”uV8ûݾ ƒgL2ÿÿÿýÿúÿ÷ÿôÿðÿìÿçÿãÿÞÿÚÿ×ÿÓÿÎÿÊÿÅÿÀÿ»ÿ¶ÿ±ÿ­ÿ¨ÿ£ÿžÿ™ÿ”ÿÿ‹ÿ†ÿÿ|ÿwÿrÿnÿiÿdÿ_ÿ\ÿXÿTÿPÿMÿJÿHÿFÿDÿCÿBÿBÿBÿCÿDÿFÿIÿLÿPÿTÿYÿ_ÿeÿmÿuÿ}ÿ†ÿÿ›ÿ§ÿ³ÿ¿ÿÍÿÛÿêÿù):L_q„˜«¿Óçú#8LauŠŸµÊßõ !8Og—°Êäÿ6Sq®Îï4X| Äé 1VzžÁä'Hg†£¾Ùñ0BQ^jsz‚ƒ‚zsj`TG8'í×À©v[?#çÈ©ŠkL, ì˪‰hG&ã ~\:÷Õ´’pO. ìÊ©ˆhH(éÉ©‹mQ5ÿÿÿýÿúÿöÿóÿïÿëÿæÿáÿÝÿÙÿÕÿÐÿÌÿÇÿÁÿ¼ÿ·ÿ²ÿ®ÿ©ÿ¤ÿžÿ˜ÿ“ÿŽÿ‰ÿ…ÿ€ÿzÿuÿoÿjÿfÿaÿ\ÿWÿSÿOÿKÿGÿCÿ@ÿ>ÿ<ÿ:ÿ9ÿ8ÿ8ÿ8ÿ9ÿ:ÿ<ÿ?ÿBÿFÿKÿPÿVÿ]ÿdÿmÿvÿÿŠÿ•ÿ¡ÿ®ÿ»ÿÊÿÙÿèÿø*=PcvŠŸ³ÇÜñ0E[p…›±ÈÞô "9Qj‚œµÐë"?]{›»Üþ!Fk·Ý+Ry Çí9]¤Ææ$@Zs‰ž±ÁÏÛåìñôõóðêâÙÎÀ²¡|gQ9 ìд–wX8öÕ´“qO- èÅ¢\9òÏ«‡c@ùÖ³mJ'ᾜzY7ôÓ²’sU8ÿÿÿüÿùÿöÿòÿíÿéÿäÿàÿÛÿ×ÿÒÿÎÿÉÿÄÿ¾ÿ¸ÿ³ÿ®ÿ©ÿ¤ÿŸÿ™ÿ“ÿŽÿ‰ÿ„ÿÿyÿsÿmÿhÿbÿ]ÿXÿSÿNÿJÿEÿAÿ=ÿ9ÿ6ÿ4ÿ1ÿ0ÿ.ÿ-ÿ-ÿ-ÿ.ÿ/ÿ2ÿ4ÿ8ÿ<ÿAÿFÿMÿTÿ\ÿdÿnÿxÿƒÿÿ›ÿ©ÿ·ÿÆÿÖÿæÿ÷,?Sg|‘¦»Ðåû'<Si•¬ÃÚñ  9Rk„ž¸Ôï (Fe„¤Æè /T{¢ÊòEo˜Âì?h·Þ(Km«Èâû$6EQ[chkkie_VK?1 ûæÏ·žƒhK-ïÏ­‹iF#ÿܸ”oK&ݸ“nH#þÙ³ŽhCùÔ°‹gBøÔ°iF#Ý»šyZ;ÿþÿüÿùÿõÿñÿìÿçÿâÿÞÿÙÿÕÿÐÿËÿÆÿÀÿºÿµÿ°ÿ«ÿ¦ÿ ÿšÿ”ÿŽÿ‰ÿ„ÿ~ÿxÿrÿlÿfÿ`ÿ[ÿUÿPÿKÿEÿ@ÿ;ÿ7ÿ3ÿ/ÿ,ÿ)ÿ'ÿ%ÿ$ÿ#ÿ"ÿ#ÿ#ÿ%ÿ'ÿ*ÿ.ÿ2ÿ7ÿ=ÿCÿKÿSÿ\ÿfÿqÿ|ÿˆÿ–ÿ¤ÿ³ÿÃÿÓÿäÿõ-AVk–¬ÂØî2H_v¤¼Ôì5Oi„ž¹Õñ,KjЬÎñ:`ˆ°Ú/[‡´à :g“¿ê>fŽ´Øû:Wq‰°ÀÍ×ßäççäàØÏõ¥“€jS;!éÌ­lJ(á¼—rL&Ú³f?ñÊ£|U.߸‘jCöЩƒ]6êÅŸ{V1 èÄ¡^>ÿþÿüÿøÿôÿðÿëÿæÿáÿÝÿØÿÓÿÎÿÉÿÃÿ½ÿ·ÿ²ÿ­ÿ¨ÿ¢ÿœÿ•ÿÿ‰ÿ„ÿ~ÿxÿqÿkÿeÿ_ÿYÿSÿMÿGÿAÿ<ÿ7ÿ2ÿ-ÿ)ÿ%ÿ!ÿÿÿÿÿÿÿÿÿÿÿÿ#ÿ(ÿ-ÿ3ÿ:ÿAÿJÿSÿ^ÿiÿuÿ‚ÿÿŸÿ®ÿ¿ÿÐÿáÿó.CYp†œ²Éà÷%<Sj™²Êãü0Je€œ¸Õñ.MmްÓ÷Bi‘»æ?m›Êú*ZŠºêHu¢Îø!Hm‘²Ðí   / @ N Y a f h h e _ W L ? /  õÞÅ«qS3ðÌ©„^8êÛrJ!ùЧ~U,Ù°‡^5 ä»’iAñÈ xP(Ù³Œf?òÍ©…cA ÿþÿûÿøÿôÿïÿêÿåÿàÿÛÿÖÿÒÿÌÿÆÿÀÿºÿ´ÿ¯ÿªÿ¤ÿžÿ—ÿÿŠÿ„ÿ~ÿxÿqÿjÿdÿ^ÿXÿQÿKÿDÿ>ÿ8ÿ2ÿ-ÿ(ÿ#ÿÿÿÿÿÿÿÿ ÿ ÿ ÿÿÿÿÿÿÿ#ÿ)ÿ0ÿ8ÿ@ÿJÿUÿaÿnÿ{ÿ‰ÿ˜ÿ©ÿºÿÌÿÞÿñ/E\sŠ¡¸Ïçþ-D\tŒ¤¾×ñ 'B]z–´Ñï-Mn³×û!Go˜ÂîJz«ÜBu©ÜCv¨Ú 9g“½å / P n ‰   µ Æ Õ à è î ð ï ë ä Û Ï À ¯ œ ‡ o V ;  à¿yU/ ⺒i?ëÀ–k@龓h<æ»e:åºe;ç½”jAîÆuM%ýÖ°‹gD"ÿþÿûÿ÷ÿóÿïÿéÿäÿßÿÚÿÕÿÐÿÊÿÄÿ¾ÿ¸ÿ²ÿ¬ÿ¦ÿ ÿ™ÿ’ÿŒÿ…ÿÿxÿqÿjÿdÿ]ÿWÿPÿIÿBÿ<ÿ5ÿ/ÿ)ÿ#ÿÿÿÿÿ ÿ ÿÿÿÿÿÿÿÿÿÿ ÿ ÿÿÿÿ&ÿ.ÿ7ÿAÿLÿYÿfÿtÿ‚ÿ’ÿ£ÿµÿÇÿÛÿï/F^vŽ¥½Õì3Kc|•®Èãþ6SpެÊé *Km³×ü#JrœÇó!Q‚µéTŠÂù1h Ö Bv©Ú 7 b ‹ ± Õ õ  + A T b n v | } { w o d W G 4   î Ó µ – v S 0 å¾–mCî–j=㶈[-Ò¥wJðÖi=ã·‹_3ܰ…Z/Ù¯…[2߸‘lG#ÿþÿûÿ÷ÿóÿîÿèÿãÿÞÿÙÿÓÿÎÿÈÿÁÿ»ÿµÿ¯ÿ¨ÿ¢ÿ›ÿ”ÿŽÿ‡ÿ€ÿyÿrÿkÿdÿ]ÿVÿPÿHÿAÿ:ÿ3ÿ-ÿ&ÿ ÿÿÿÿ ÿÿþþþûþùþ÷þöþöþöþ÷þøþûþþÿÿÿ ÿÿÿ$ÿ-ÿ8ÿCÿPÿ^ÿlÿ{ÿŒÿÿ¯ÿÃÿ×ÿì/G`x‘©ÁÙñ  8Pi‚œ¶Ñì &Dc Àà#Fh‹¯Ôù Hq›Çõ$T†ºð(ašÕK‡Ãÿ:u®ç  R † ¸ ç  < b … ¤ ¿ Ö é ù     ô å Ó ¾ § Ž r T 4  ï Ê ¤ | S *ÿÓ§zLïÀ‘a2Ò¢rC㳄T%öÇ™j; Þ°ƒU'úÍ sFíÁ•j>é¿—pJ%ÿþÿûÿ÷ÿòÿíÿçÿâÿÜÿ×ÿÑÿÌÿÅÿ¾ÿ¸ÿ²ÿ«ÿ¥ÿžÿ—ÿÿ‰ÿ‚ÿ{ÿtÿlÿeÿ^ÿWÿPÿHÿ@ÿ9ÿ2ÿ+ÿ$ÿÿÿÿ ÿÿþûþ÷þóþðþíþëþêþêþêþëþíþïþòþ÷þüÿÿ ÿÿÿ#ÿ.ÿ:ÿGÿUÿdÿtÿ…ÿ—ÿªÿ¾ÿÓÿèÿÿ/Gaz“«ÄÜô $<Tm† ¼×ô1Qq’³Ôö<`ƒ¨Ìò@j”Áï R†»ò,g£á _ à!a¡á  \ — Ò @ s £ Ð ù  @ \ u ‰ ™ ¤ ¬ ° ¯ « ¤ ™ ‹ y e N 5  û Ú ¸ “ m E  ñ Æ ™ k = Ý­|J絃P칇U#ð¿[*ùȘg7×§wH껌^/Ó¦yLòÇuM&ÿþÿúÿöÿñÿìÿæÿáÿÛÿÖÿÐÿÉÿÃÿ¼ÿµÿ¯ÿ©ÿ¢ÿšÿ“ÿŒÿ…ÿ~ÿvÿnÿgÿ_ÿXÿPÿHÿ@ÿ9ÿ2ÿ*ÿ"ÿÿÿ ÿÿþûþõþðþìþèþäþâþßþÞþÞþÞþßþáþãþçþëþðþ÷þþÿÿÿÿ$ÿ0ÿ>ÿLÿ\ÿlÿ~ÿ‘ÿ¤ÿ¹ÿÏÿåÿü.Ga{”­ÅÞö&>Voˆ£¿Ûù9[} Ãç /SxÂè5^ˆµäH~µï)f¦æ)l±ö;Ç Q ” ×  X – Ñ = n š  å   2 B N U X V Q G : *  ÿ æ É ª ‰ f A  ð Å ™ k < Û ª w D ܨs? Õ k6͘c/úÆ“_,ùÆ”a/ýÌši8Ö¦uEæ·ˆY*üϤyP(ÿýÿúÿöÿñÿëÿåÿàÿÚÿÕÿÎÿÈÿÁÿºÿ³ÿ­ÿ¦ÿŸÿ—ÿÿˆÿÿyÿqÿiÿaÿYÿRÿIÿAÿ9ÿ2ÿ)ÿ!ÿÿÿ ÿþüþöþðþêþåþàþÝþÙþÖþÔþÒþÒþÒþÓþÕþØþÛþßþåþëþòþúÿÿÿÿ&ÿ4ÿCÿSÿdÿvÿ‰ÿžÿ³ÿÊÿáÿù,F`z”­ÆÞö&=Unˆ¢¿Ýü?cˆ­ÓùDi´Ú'Nx£Ñ6l¦â _¡ä*q¹M™ä 0 | Æ  X   æ * k § à  E p • ¶ Ñ æ ö    ô å Ò ¼ ¢ … f C  ø Ï ¤ w I  é ¶ ƒ O  ä ® w @ Ñ™a*òº‚KÜ¥n7Ë•`+öÁX%ñ½ŠW$ò¿[*ùÈ—f5ת~S)ÿýÿúÿõÿðÿêÿäÿßÿÙÿÓÿÍÿÆÿ¿ÿ¸ÿ±ÿªÿ£ÿ›ÿ“ÿŒÿ„ÿ}ÿuÿlÿdÿ\ÿTÿKÿBÿ:ÿ2ÿ*ÿ!ÿÿÿÿþùþòþëþåþßþÚþÕþÑþÍþËþÈþÇþÆþÆþÇþÉþÌþÏþÓþÙþßþæþïþøÿÿÿÿ*ÿ9ÿJÿ[ÿnÿ‚ÿ—ÿ­ÿÅÿÝÿõ)D_y“¬ÅÞõ $;Rj„ž»ÚûBi¸à0W~¤Êð<d¹èQŒÊ O”Ú#n¹V¦ø J œ ï @ ‘ á 0 } Ç  P È û ) Q s ¥ ¶ Á Æ Æ Â ¹ « ™ „ j M - ä ¼ ‘ d 5  Ò Ÿ k 5 þ Æ Ž T  à ¦ k 0õº€E Ж["è¯u=Ì•]&︂Lá¬wBÚ¦r? Ù¦sAß°ƒV+ÿýÿùÿõÿïÿêÿäÿÞÿØÿÒÿËÿÄÿ½ÿ¶ÿ¯ÿ¨ÿ ÿ˜ÿÿˆÿ€ÿyÿpÿgÿ_ÿVÿMÿDÿ<ÿ3ÿ+ÿ"ÿÿÿþÿþ÷þïþèþáþÛþÔþÏþÊþÅþÂþ¿þ¼þ»þºþºþ»þ½þ¿þÃþÇþÍþÓþÛþãþíþøÿÿÿ ÿ/ÿ@ÿRÿeÿzÿÿ¦ÿ¿ÿ×ÿñ %@[vªÃÛò 5Lc|–³ÓõBk–Áì@i‘·Ý(NtÉù-g¥é0{Æb²Uª Y ² f ¿  p Ç  m »  H † ¾ ï=Zq‹Ž‡|lX?" Þ · a 2  Í ˜ b * ñ ¸ } B  È ‹ M  Ñ ’ T Øš]â¥h,ðµy>ÊWå¬t<Θa*ô¾‰TêµLç·‡Y,ÿýÿùÿôÿïÿéÿãÿÝÿ×ÿÑÿÊÿÂÿ»ÿ´ÿ¬ÿ¥ÿÿ•ÿÿ…ÿ}ÿtÿkÿbÿZÿPÿGÿ>ÿ5ÿ,ÿ#ÿÿÿþþþöþíþåþÞþÖþÐþÉþÄþ¾þºþ¶þ³þ°þ¯þ®þ®þ¯þ°þ³þ¶þ»þÁþÈþÏþØþâþîþúÿÿÿ%ÿ6ÿIÿ\ÿqÿ‡ÿžÿ·ÿÐÿê ;WrŒ¦¿Öí,AWo‰¦Æë=j˜Æõ"Ny¢Éï7[€§Ò7s·Q¤ùM¢÷M¤ÿ [ »  ~ á C ¥  g Å  t ÄQÂï2IYbebYK8!äÀ™m@ Û ¥ m 4 ø ¼ ~ ? Á @ þ ¼ z 9 ÷ µ s 2ñ°p0ð°q3õ·y=ĈL×c*ñ¸G× i2ûÄŽX#ð½Œ\.ÿýÿùÿôÿîÿéÿâÿÜÿÖÿÏÿÈÿÁÿ¹ÿ²ÿªÿ¢ÿšÿ’ÿŠÿÿyÿpÿgÿ]ÿTÿKÿAÿ8ÿ/ÿ%ÿÿÿþþþõþìþäþÛþÓþÌþÅþ¾þ¹þ³þ®þªþ¦þ¤þ¢þ¡þ¡þ¢þ¤þ¦þªþ¯þµþ¼þÄþÍþØþãþðþþÿ ÿÿ,ÿ?ÿSÿhÿ~ÿ–ÿ®ÿÇÿâÿü4Pk† ¸Ïäù 2F\u‘³Ù3d—Éú*X†±Ùþ!Bc…¨Ïý3s¾nÍ-Šå>˜ô S ·  ˆ ô ` Í 9 ¦  y Ü:’â+k£Óú/>FGB6&õÕ±‰]-ûÅR Ö – T  Í ‰ D » u / é £ ^  Ó J Â<ú¸w6õµv7øº|?ÆŠOÙžd*ð·~E Ôœd.øÄ‘`/ÿýÿùÿôÿîÿèÿáÿÛÿÔÿÎÿÆÿ¿ÿ·ÿ¯ÿ§ÿŸÿ—ÿÿ†ÿ~ÿuÿlÿbÿYÿOÿFÿ<ÿ2ÿ(ÿÿÿ þÿþöþìþãþÚþÒþÉþÁþºþ³þ­þ§þ£þžþšþ—þ–þ•þ•þ–þ—þšþžþ£þªþ±þ¹þÃþÍþÙþæþôÿÿÿ"ÿ5ÿHÿ]ÿsÿ‹ÿ£ÿ¼ÿÖÿñ *Fb}—®Ä×êú -@Ws•¾î"YÅø+]޾é/Lg‚ŸÁë"h¼ŠúfÌ,‡ã B §  ‚ ö l ä \ Õ N Å9§oÆZ•Çï#176/! óÔ°ˆ\+÷¿…GÅ€: ó « a  Í ƒ 9 ï ¥ [  È ~ 5 í ¥ ] ЊD»x5ò°o.í­m.ð²t7ú½E Ï”Yäªq8Ë—c1ÿýÿøÿóÿíÿçÿáÿÚÿÓÿÌÿÅÿ½ÿµÿ®ÿ¥ÿÿ”ÿŒÿƒÿzÿqÿhÿ^ÿTÿJÿ@ÿ6ÿ,ÿ!ÿÿ ÿþ÷þíþãþÚþÐþÇþ¿þ·þ¯þ¨þ¡þœþ—þ’þŽþ‹þ‰þˆþˆþ‰þ‹þŽþ’þ˜þžþ¦þ¯þ¸þÃþÏþÜþêþøÿÿÿ*ÿ=ÿQÿfÿ}ÿ•ÿ®ÿÈÿã9Up‰Ÿ³ÅÕãðý .Hj—Í Hƒºî!X“Íÿ&BViyŠ£ÊP°#¦.©xÔ . Ž ø m ê j ì o ó y‡ …÷`¾Z˜Ìõ(484)âÀ˜k:ËŽN Å|2ç™K ü ¬ \ ½ m  Ð ‚ 4 ç š M  · l "Ù‘I»u0ë§d!Þœ[Úš[ÝŸa$æ©l0ô¸}C Óœg3ÿüÿøÿóÿíÿçÿàÿÙÿÒÿËÿÃÿ»ÿ´ÿ¬ÿ£ÿ›ÿ’ÿ‰ÿ€ÿwÿmÿcÿYÿOÿEÿ;ÿ1ÿ&ÿÿÿþúþïþåþÚþÐþÇþ½þµþ¬þ¥þþ–þþ‹þ†þ‚þþ}þ|þ|þ}þþ‚þ‡þŒþ“þ›þ¤þ®þ¹þÅþÒþàþîþýÿ ÿÿ0ÿCÿWÿlÿƒÿœÿ¶ÿÑÿî 'C^v‹ž®»ÆÏ×áëú/_Ÿè2t¨ÖD“ç*Pbiopim…¨pÃaùjØ % x Ó B É Z î {  –*Ã\ð{ùjÎ%q±å +>GG@2߸‹Z$éªg!ØŒ=í›GóH ñ › F ñ œ H ö £ R  ° a  Ä v *Þ“Iÿ¶n'à›ÜEÀ>ý½}=þ¿€BƉNÚ¢k5ÿüÿøÿóÿìÿæÿßÿÙÿÒÿÊÿÂÿºÿ²ÿªÿ¡ÿ˜ÿÿ†ÿ}ÿsÿiÿ_ÿUÿKÿ@ÿ6ÿ+ÿ ÿÿ þýþòþçþÝþÒþÈþ¾þ´þªþ¢þšþ’þ‹þ…þþzþvþsþqþpþpþqþsþwþ{þþˆþ‘þšþ¤þ¯þ»þÈþÕþãþñÿÿÿ ÿ1ÿDÿXÿnÿ†ÿŸÿ»ÿ×ÿô,F^s„‘š¡¦ª®³ºÆß]Á"j–±Íÿ ‹²¢¨¡tLÕñÿ×´gà # x à þ w  ð • 3 ³LïšJõ‘‘øQŸà<Wgmi]J0齌UÙ”Kþ¯\°Wý¡Eé0 Ô y  Å m  ¿ j   o  Ì | -ß‘Dø®dÒŠCü¶p+ç£`Û™WÕ”TÔ–Xá§n7ÿüÿøÿòÿìÿåÿÞÿØÿÑÿÉÿÁÿ¹ÿ±ÿ¨ÿŸÿ–ÿÿƒÿzÿpÿfÿ[ÿQÿGÿ;ÿ0ÿ%ÿÿÿþöþêþßþÔþÉþ¿þ´þªþ þ—þþ‡þ€þyþsþnþjþgþeþdþdþeþhþkþpþvþ~þ†þþ›þ¦þ±þ½þÉþÖþãþðþþÿ ÿÿ,ÿ?ÿTÿjÿƒÿÿ¹ÿÕÿò)ATcmtvwuutuyz•倈Ÿœ¥æv¶ß²þ‡yÍâDOG³ [ ×  D k e P o àgˇSÏaØ>˜ç([™¦§ŒsS.Ñš^ÕŠ:ç7Ú|ºXõ’.Ëh ¦ F è ‹ / Ö } % Î x $ Ð } +Û‹<î¡U ¿v,ä›T È‚=ùµq.ë¨f$ã¢c%è¬r8ÿüÿ÷ÿòÿëÿåÿÞÿ×ÿÐÿÈÿÀÿ¸ÿ¯ÿ§ÿÿ”ÿŠÿÿwÿmÿbÿXÿMÿBÿ7ÿ+ÿÿÿþûþïþãþØþÍþÁþ¶þ«þ¡þ—þþ„þ|þtþmþgþbþ^þ[þYþXþXþYþ\þ`þeþlþsþ|þ†þþšþ¥þ°þ»þÆþÒþÝþéþõÿÿÿÿ2ÿFÿ]ÿwÿ’ÿ¯ÿÌÿé1?FIIB<7641,@ç–±Ÿv‚Ì2¨³yhx ÇÆš´ÄÕÇù ”  x  £ † ÓrI´‚co;Ù:œøHˆºÞóûõåÍ­ˆ],õ¹v.áŽ7Ü}·Q逫@Ölš2 Ì h  ¤ D ç ‹ 0 Ö } % Ï z %Ò€/ßBõ©]Ç}4ì¥^ÑŒF¼x4ñ¯n.ï²u:ÿüÿ÷ÿñÿëÿäÿÝÿÖÿÏÿÇÿ¿ÿ¶ÿ®ÿ¥ÿ›ÿ’ÿˆÿ~ÿtÿjÿ_ÿTÿIÿ>ÿ2ÿ&ÿÿ ÿþõþèþÜþÐþÅþ¹þ®þ£þ˜þþƒþzþqþiþbþ[þVþRþOþMþLþLþMþPþUþZþaþiþqþzþƒþþ–þ þªþ´þ¾þÇþÏþØþáþëþ÷ÿÿÿ,ÿCÿ^ÿ|ÿ›ÿ¹ÿØÿõ  ÿþÿý r1 ˆˆqak5JMÔ!Ο‰•™ö¢°È±ž _  – ï ~ <S}N Év±Ò_®pÁ1Uhi[AùÍg*èŸPû¡BÞw Ÿ0¿NÜiö„¢2ÃW ì ƒ  ¶ S ò “ 5 Ø | " É q ÆrÌ{+ÜŽ@ó§\Ç~6î¦^ЊE¼y7÷·y<ÿüÿ÷ÿñÿëÿäÿÝÿÖÿÎÿÆÿ¾ÿµÿ­ÿ¤ÿšÿÿ†ÿ|ÿrÿgÿ\ÿQÿEÿ:ÿ.ÿ!ÿÿþûþîþâþÖþÉþ½þ±þ¦þšþþ„þyþoþfþ^þVþPþJþFþCþAþ@þ@þAþDþIþOþUþ\þcþlþtþ}þ…þŽþ–þžþ¤þªþ¯þ´þ¹þ¾þÅþÎþÛþëþýÿÿ9ÿZÿ~ÿžÿÊÿò  ! 5€À  ÿþï &HNzt‰š¤ÿ;ÛÞ£W  Ì { + û â ýRVøÌ×-mpÓ) PнêþùÚ°‚T$î³q)Ú„'Å]ð ” %ª.³9¿GÏZæt — , à \ ø – 5 Õ v  ¾ e µ^ µbÀo у6êŸU Áw.åVÉ„Aþ½}>ÿüÿ÷ÿñÿêÿäÿÜÿÕÿÍÿÅÿ½ÿ´ÿ«ÿ¢ÿ˜ÿÿ…ÿ{ÿpÿeÿZÿNÿBÿ6ÿ)ÿÿÿþõþèþÜþÏþÂþ¶þ©þþ‘þ†þzþoþeþ\þSþKþDþ?þ:þ7þ4þ3þ4þ5þ8þ<þAþGþMþTþ[þbþjþqþxþ}þ‚þ…þ‡þ‡þ‡þ†þ…þ†þˆþþ”þœþ­þÐÿ!ÿ!ÿ[ÿ†ÿú ÿñÿèÿíÿéÿïÿû:Žæ.es¥¹Õøí×ðh€”äÁ0È© v U b ] tž×îß¹¦65“eðor¯ýQžÃ¬t)òÀŒSË}'Êeúˆ–•üwôròsõz‹ ¥ 6 É _ ø “ / Ì l ¯ SùŸGðšEòŸMü¬\Às'ÛDú°gÖJÃ@ÿüÿ÷ÿñÿêÿãÿÜÿÕÿÍÿÅÿ¼ÿ³ÿ«ÿ¡ÿ—ÿŽÿƒÿyÿnÿcÿWÿLÿ?ÿ2ÿ%ÿÿ þþþðþãþÖþÉþ¼þ¯þ¢þ•þ‰þ}þqþfþ[þQþHþ@þ9þ3þ.þ*þ'þ&þ'þ)þ+þ.þ2þ6þ;þAþGþNþSþXþ\þ^þ^þ\þYþUþOþGþ@þ9þ2þ,þ(þþþ7þ‚ÿþDÿXÿú% ÿñÿÏÿºÿ´ÿÿkÿjÿ‡ÿ¯ÿÜÿö#MF;ðÒäçžqç‘ BM•o‹M^Ø÷U \ r Ý ó=t–«°×èúÔeÞ;À'È.aWí h8Ɇ;æ‰#¶AÅD½2¥…ôcÓE·,£–“š! ¬ 9 É \ ò Š # ¿ \ û › =á…+Ó{%Ï{'Ôƒ2â“Dö¨[Ãw-ãšS È„Bÿüÿ÷ÿñÿêÿãÿÜÿÔÿÍÿÄÿ»ÿ³ÿªÿ¡ÿ—ÿÿ‚ÿwÿlÿ`ÿUÿIÿ<ÿ/ÿ"ÿÿþùþìþÞþÐþÃþµþ¨þ›þŽþþuþiþ]þRþGþ>þ5þ.þ'þ"þþþþþþþþ þ#þ'þ+þ/þ3þ6þ8þ7þ5þ0þ)þ þþ ýþýðýáýÍý·ý¬ý©ýŒý©ýêýÄýÿþdÿxÿ›ÿ¯ÿ”ÿHÿ%ÿþßþ¤þŠþÖÿVÿÎÿôHÿþsÿ6þÁÿ>¦‘›ooµJÁøÜ¨ß`L³ÞT ] ‡ Ÿ ñxÚ0`ˆóØÓ³¡r%ª5²O®neWíÀ‘NÁe“žŠö^Â&‰ìPµƒîZÊ<±)¤!¢& ¬ 6 à S ç |  ¬ H ä ƒ #Äg ±Xÿ¨Rý©V²aÁr#Õˆ;ð¥\͈Cÿüÿ÷ÿñÿêÿãÿÜÿÔÿÌÿÄÿ»ÿ²ÿ©ÿ ÿ–ÿŒÿÿvÿjÿ_ÿSÿGÿ:ÿ,ÿÿÿþõþçþÙþËþ½þ°þ¢þ”þ‡þyþlþ`þTþHþ=þ3þ*þ"þþþþ þ þ þ þ þ þ þ þþþþþþþ þýöýçýØýÈý¸ýªý•ý{ýqý-üòýýbýŽý–ý€ý‡ýßþ1þ}þŒþŽþ‚þiþOþ"ýðýšýÔÿÿ§ÿ×[fÿPþMýèþBÿKHVsy4Jæ›­up€:zö  w Ú š/‘ÚÙ½þpU<ýšqë€~”Yxa@Xõ¹_þ’œ€åB›ñEšïGŸúW·èTÃ6¬&¢# ¦ - · E Ö i þ • . É e £Eç‹0Ö~&Ðz%Ñ~,Úˆ8è˜Jý°eÓ‹Eÿüÿ÷ÿñÿêÿãÿÜÿÔÿÌÿÄÿ»ÿ²ÿ©ÿŸÿ•ÿ‹ÿ€ÿuÿiÿ]ÿQÿDÿ7ÿ)ÿÿ þÿþñþãþÕþÇþ¸þªþœþŽþ€þrþdþWþKþ?þ4þ)þþþþþþýüýùý÷ýõýóýòýòýñýðýîýêýäýÜýÐýÀý¬ý•ý}ýjýXýGýEýüÒü¯û¿û­üÌýXý‡ýmý/üþüùüìýýTý¤ýÉýÊý³ýxýýùþÌÿrÿ»qØ ð\ÿAÿBÿœHÝ{ýh©+HÅòPB41Ϙët } 5 œcó@s™éfMG:ý‡¸ùYµ;¯ . < U h · Å ‚ (·AÀ5 W¤ë0t¹ÿH”ã4‰à;šübÍ<®#œ ™  ¦ 1 À Q ä y  © Dà~¿aªOöžGñœGóŸLú©Y »n#ØGÿüÿ÷ÿñÿêÿãÿÜÿÔÿÌÿÄÿ»ÿ²ÿ¨ÿŸÿ•ÿŠÿÿtÿhÿ\ÿOÿCÿ5ÿ'ÿÿ þüþîþàþÑþÂþ´þ¥þ—þˆþzþkþ]þOþBþ6þ*þþþ þýûýöýðýëýæýáýÝýÙýÖýÓýÏýÉýÃýºý®ýžýŠýqýRý0ý üóüùüÍüÁü®ûÏû_úíûû—ü*ü„üâüoü$û²û’û™übýýý±ýÑýÎýôþàÿÅ`¶ œ xé‚õ  w‡ÿö0ÈåGS_#Ø,¼ ¨ « }ÉïÅÃÞöI§×ÄÅÍ ” oq–óbà y ê!8!y!Õ""^"d"!Š! ìKœâP²åU“Õb¯ÿR«hÏ9¦Ž †  Ž  ¤ 3 Ä X í „ ¹Uó“3ÕyÃi¹b ·a ºhÆx*Þ“Iÿüÿ÷ÿñÿêÿãÿÜÿÔÿÌÿÄÿ»ÿ²ÿ©ÿŸÿ”ÿŠÿÿsÿgÿ[ÿNÿAÿ4ÿ%ÿÿþúþëþÝþÎþ¿þ°þ¡þ’þƒþtþeþWþHþ:þ-þ!þþ ýÿýöýîýçýßýØýÑýÊýÃý¼ý¶ý¯ý¦ýœýý€ýlýTý6ýüçü¸ü†üZüJürû´û¸û?úºú¦úšúµúãû%û-û}úýûúíûIüüèý¢þ:þzþTþ€ÿ¥[Úð,àÐçuQqp€3©yÿÿ ¥dpA¡ŠV ‡ -ƒXäæP€éYrpY™¹"Z¢ÏïIž ²!m!ú"W"·##V#¤$#Ø#v"ñ"a!Ã! Uˆ­ÉãÿDnÐD„É_² eÇ-˜z ñ m í q ù „    2 Æ [ó(Äb¢Dç‹0×~%Îv Ëv#Ñ2ä—Kÿüÿ÷ÿñÿêÿãÿÜÿÔÿÍÿÄÿ»ÿ²ÿ©ÿŸÿ”ÿŠÿÿsÿgÿZÿMÿ@ÿ2ÿ$ÿÿþøþéþÚþËþ¼þ­þþŽþ~þoþ`þQþBþ3þ%þþ ýÿýôýêýàýÖýÍýÃý¹ý¯ý¥ýœý‘ý…ýwýgýTý=ý üþüÖü¦üoü+ûéû­ûû@ûúæúÅúaúCú3ùÊù°ù¸ù¹ù}ú)úlúùûÓüpý!ýÒþÔÿ_ÿlÿ{Lj¾“¿¦JÚªéFyy;¡sj[½›èÌöì“Î Ó ë Ü 4‡è(£n¢@¥{É:U µÇÆþƒ ¦!|"£##”#ö$W$›$þ%{%’%o$×$C#£"ô"-!L VUV\gz’±Õÿ.bšØa®X·í^ Ô N Ì O Õ ^ é w  š .Ä\ö‘.Ìk ­Pô™>ä‹3Û…0ÜŠ9éšMÿüÿ÷ÿñÿêÿãÿÜÿÕÿÍÿÅÿ¼ÿ³ÿ©ÿŸÿ•ÿŠÿÿtÿgÿZÿMÿ?ÿ2ÿ#ÿÿþ÷þèþÙþÉþºþªþšþŠþ{þkþ\þLþ=þ-þþþýõýéýÝýÑýÅý¸ý¬ýŸý’ý„ýwýgýUýBý+ýüðüÉü›ühü0ûñû¦ûEû úóú×ú³úIù÷ù²ùjù#øÖø»øªø‘øÑù;ú;ûNüKýý|þþ¼ÿÓ|8š‹‰–œU>RnnH?`fJX|Ñ7踴”l@û ‰ Ý à p íþuèOÙ(ªþa›.@Ïìßû- !@"‰#›$‚$Ñ%%Ì&&N&£&í&¦&N%ö%~$ñ$,#@" ïÕż»ÂÐå Gs¤ÛY¡ïCžþcÍ= ± ) ¦ ' ¬ 3 ½ I Ø iü‘(ÀZõ’0Ïp³Wû Eì”=ç“@îžNÿüÿ÷ÿñÿêÿäÿÜÿÕÿÍÿÅÿ¼ÿ³ÿªÿ ÿ•ÿ‹ÿ€ÿtÿgÿZÿMÿ?ÿ1ÿ#ÿÿþöþçþØþÈþ¸þ¨þ˜þˆþxþiþYþIþ8þ(þþ ýúýëýÝýÐýÁý²ý£ý“ýƒýrýaýNý8ý!ýüéüÆüœüjü0ûîû´û|ûAûúéú§úAùáùxù#øÌøW÷ûøøPøVøNøwùRúPûŽü±ý~ý£ýÊþ^ÿ2ÿæ”bä#Abˆ©¨®©‹dl¡åbËKã–`(ß} ‡ ê d 3 h ³! Ò–&‰›Qi6 ó>ç Ú"#l$~%‡&z' 'v'Œ'¿'ç'î'Â' 't'8&¥&h%#Õ"‡!] : ýúÿ 4Sw¡ÑE‰Ô%~Û?§ ‡ þ z ú }  Œ  ¤ 4ÆYUñ.Îo´Xý£JòœGô¡Pÿüÿ÷ÿñÿëÿäÿÝÿÖÿÎÿÆÿ½ÿ´ÿ«ÿ¡ÿ–ÿŒÿÿuÿhÿ[ÿMÿ?ÿ2ÿ#ÿÿþöþçþ×þÇþ·þ§þ—þ‡þwþgþWþFþ5þ$þþýòýâýÒýÂý±ýŸýŒýxýdýOý9ý!ýüçüÆü üsü@üûÂû{ûBû&ûúðú¿úùcøÕøuø÷ø÷.öŽ÷'÷óø_øjø§ù8úRûTü-üÕý%ýKýÅþƒÿ{ÿÕpÙO¤è-v¾ø" ݸ·íPÓmÅz>¾ A œ ä 9 ª C  /L:6(=–¢lÓ#; ­ˆ …!™"ù$%c&½'µ(d(è))6)ƒ)(ß(À(Á(Q'ù'j&À%E$"û!· ‡bE/" )9Pm‘¼î'h°ÿV²z ç X Î I È J Ï V à lû‹²Iày¯Kéˆ(Ék²Wþ¦Où¥RÿüÿøÿòÿëÿäÿÝÿÖÿÏÿÇÿ¾ÿµÿ¬ÿ¢ÿ—ÿŒÿÿvÿiÿ[ÿNÿ@ÿ2ÿ$ÿÿþ÷þçþØþÈþ¸þ¨þ˜þˆþwþgþVþEþ3þ!þýýýëýÙýÇý´ý ýŠýtý\ýDý*ýüðüÎü©üüRüûßûžû^û%ûúöú¤ú9ùÌù øH÷‹÷4÷6öhöõåö@÷Gø-ø{øœùùîúÄû-û“üý ýƒþ,þÙÿ~$@ìD›ÿ||ÀÅD DÁ…twUÕ Õ „ Þ » ° Ô < ê Ë ËÙÛ¶h͵°ã"«¶#m~… Ô"#}%C&·'ñ(ä)ž*%*^*]*X*B)Ó)©)t)/(‘'ú'&I%Ë$}#8!þ ȘoP:-''/?Vt›É>„Ò'âH ³ $ ™  ‘  •  ¥ 0½MÞr5Îh¡?Þ~Ád ¯Vÿ©TÿýÿøÿóÿìÿåÿÞÿ×ÿÐÿÈÿ¿ÿ¶ÿ­ÿ£ÿ™ÿŽÿƒÿwÿjÿ]ÿOÿBÿ4ÿ%ÿÿþøþéþÙþÉþ¹þ©þ™þ‰þyþhþWþFþ3þ þ ýùýåýÑý¼ý¦ýývý[ý?ý!ýüáü¼ü”üiü8üûÄû…ûHûúöúêúoùÆù6ø“øö×ö–öõÕõÇõ­õ°öö—÷Yø2øxø¥ù;ùâúûûÇü‡ý<ýÓþsÿÿ—QªýTÉ`JÛµBŠ@,Që|å  ® S  a  L  } _ ck‹±…Þ”C"&Do›Ñ E c!ð#…%'u(Ý)Û*‰+L+"*ú*Ý*»*ž*m*!))(_'¹'Q&É%ï$Â#y"5 õ¸‡`C,1KnšÏ PñJª z ê _ Ø U Õ X Ý eï| ›.ÁWí…ºUò/Ïq¸^­VÿýÿùÿóÿíÿæÿßÿØÿÑÿÉÿÀÿ¸ÿ®ÿ¥ÿšÿÿ„ÿxÿlÿ_ÿQÿDÿ6ÿ'ÿÿ þúþëþÜþÌþ¼þ­þþþ|þkþZþHþ5þ!þ ý÷ýáýÊý²ý™ý~ýaýBý üýüØü±ü†üWü%ûîû¯ûnû0ûúÝúªú-ùPøc÷›÷&öJö+õêõÌõªõ±õ²õ¸õ¿õþöš÷s÷ðøøƒù=ùþú±ûfüüÑý{þþ·ÿ@ÿ·'…Ð kþÒ€%˜3†R'–f~   æ # b Ÿ G ‘ × Ä L FÅp?ÒDÐ Ž™¸äR¡_|!#%&î(ª)û++¦+†+`+]++"+T*À* )_(À(S('Á'C&$Î#˜"T!Æb;óíñÿ7b•Ða´ l Ñ ; « ˜  ”  š !«6ÄTåx ¢:Òl¢?Þ~Áe °XÿýÿùÿôÿîÿçÿàÿÙÿÒÿÊÿÂÿ¹ÿ°ÿ§ÿœÿ’ÿ†ÿ{ÿnÿaÿTÿFÿ8ÿ)ÿÿ þýþïþàþÑþÁþ²þ¢þ’þþpþ_þLþ9þ$þý÷ýßýÅýªýŽýoýMý(ýüØü­üüMüûÞû¤ûcûúçú£úPù›ø»÷µöšõ‰õõ õ$õ!õVõ¢õÏõ™õ¶õÏõíöö`÷%÷•øøËù†úBúúû´üoý&ý×þ{ÿÿŽ ¥Ïзãíhƒs"WûÌ o / ‡ Ø – B ê õ œðÛ³’ñWt¢£Y  0Rz¥×lÀ "$ %´'¶)ˆ*‹+h+Ð+±+‚+h+€+{+G*ƒ)z(ã(Ó(æ(y'Ñ&ÿ%ï$ú#¶"^!ËŒS!÷ÖÀµ¶Á×÷ SŽÓqÊ) Ž ø h Ü T Ð N Ð SÚbî{ š+¿Tê‚´OìŠ*Êl´YÿýÿùÿõÿïÿéÿâÿÛÿÓÿÌÿÃÿ»ÿ²ÿ©ÿŸÿ”ÿ‰ÿ}ÿpÿcÿVÿIÿ;ÿ,ÿÿÿþóþåþÖþÇþ¸þ©þ™þ‰þxþfþSþ?þ)þýúýàýÃý¥ý„ýaý:ýüãü³ü€üKüûÖû—ûUûú½úYùòù4øN÷)õÑô«óÛóróùó×óÎôôåôàôöõ8õŠõ©õ¶õâö÷÷ÃøkùùÒúŒûJüüÕý˜þ?þÞÿfÿôTTDe‡!A¢à7·´IìÆÚ • ä  y Ú Ë’àg ¾M~Vp 7°’²Ëåÿ:l±ýr!'"‰$P& ()ó+++–+Ž+‰+i+E*»*<(é(ü)5)7(ø(n'æ'c&r%3#Ð"i!Äv.ð¾—}onxŽ­× FŠÖ( à E ° ” †  … Ž¡-»JÜn˜.Æ_ú—4Ós·[ÿýÿúÿõÿðÿêÿãÿÜÿÕÿÎÿÅÿ½ÿ´ÿ«ÿ¡ÿ—ÿŒÿ€ÿsÿgÿZÿLÿ>ÿ0ÿ#ÿÿþùþëþÝþÏþÀþ²þ¢þ’þþoþ\þGþ1þþýãýÅý£ýýVý*üúüÆüüTüû×û”ûJûú²ú/ù{øâø5÷õ¥ôUó]ò\ò4ònòjò?òžòÀó3ótóÛô`ô£õõØö2ö¯÷_øø®ù^úúÙû¬ü‰ý^þþÿ–Nò飜ÿ´ÿ¦ =*×~yw÷*ß e : ÕŠ0Â>ä’p ¸Å=kzŒ¡¥ ¬ÏK« !#$Á&s( *™+ +t+++l*Ö*Œ)e))$)š)·))D(ü(°(&é%W#é"t!  BïªrH,'<]‡ºö<ˆÚ4 “ ø c Ó G ¾ 9 · 7º?ÇQÜiøˆ­BØo£?Üz»]ÿþÿúÿöÿñÿëÿåÿÞÿ×ÿÐÿÈÿ¿ÿ¶ÿ­ÿ¤ÿšÿŽÿƒÿwÿjÿ]ÿPÿCÿ5ÿ(ÿÿÿþôþæþØþÊþ¼þ­þžþþ|þhþTþ=þ$þ ýëýËý¦ý~ýRý üéü­ülü(ûãûœûOûúúIùŸø»÷ï÷ö5ô]óhò«ñzññ>ñ-ñññ$ñlòòóôBõ(õäö*ö…÷÷˜ø8øâù•ú[ûGüZýfþ8ÿQ¥¡­€–c‰¢âY ‚ÎNŠå^¦¢ºïƒ d ÷ ÕNå3L#¼„@Ö§¯ìɳ«¢i2 Du²÷I ­""#¤%Y'+(ñ*u*¼+1++’+H*K)Í)Œ)Ó*R*’*€*$)Ù)¾))((&þ%~#î"X ÑZñ˜NêÎÁÁÍä0d¢ç4‡ á A §  ‚ ö m è eåhítý‡¢2ÃVê¯Iå¾_ÿþÿûÿ÷ÿòÿìÿæÿàÿÙÿÒÿÊÿÂÿ¹ÿ°ÿ§ÿÿ’ÿ‡ÿ{ÿoÿbÿUÿHÿ;ÿ/ÿ"ÿÿ þýþðþãþÖþÉþ»þ¬þœþ‹þxþcþMþ4þýùýÖý¯ý„ýTýüàü›üNûýû¬ûZûúÀú_ù¶øåø÷öôŠóóó$òñð°ð¿ð¾ð³ðƒðiðñò-óôôôõ‰õëö5öŸ÷'÷Äø^ùùÌúïüfýÿÿ˜?°:W8¹×m­Ã*ËÍi—˜ŠvHGr - ¡ Ì{C««wêòf¹o®æÎX k·¬Å?zµ÷!F"ª$'%¸';(N)Z*z+"++s*Í)¤)Ä*H++¶+f*ä*ƒ*2)Ý(¤(0'-%u#·" töˆ,âªh]_l„§Ó HŽÛ/ Š ë Q ½ - ¡  “ –¥/»IØiü$»Tíˆ$Â`ÿþÿûÿ÷ÿóÿíÿçÿáÿÚÿÔÿÌÿÄÿ¼ÿ³ÿªÿ ÿ•ÿŠÿÿsÿgÿZÿNÿBÿ6ÿ+ÿÿÿþüþðþäþØþËþ½þ®þþ‹þwþaþHþ,þ ýèýÀý’ý_ý%üãü–ü;ûÒûnûúÊú£úDù<ø;÷7ötôÙóÞóòÁñ¬ðéð¦ðŸð¥ð¬ðœðoðŒñUòJóTô:ôìõ[õ“õÉö!ö–÷8÷ïø–ùuúÜüÊþåiŦ{¶¯Èã¹ü$¾Byb5¬Zþ††…N , ’Ø÷œVh5äœyú¡œ‘ùRqP·:`¦ø-Pp ’!¿"ý$K%Œ&Æ(,)?*+*Â*Õ**)ê*+A+â+Ù+ƒ+5*É)â)/(ü(R&ò$÷#5!ûy ±j5úñöCp¨è/} Ò . ø d Õ H À :·7¹=ÃKÔ`í| Ÿ2Ç^ö)ÅbÿþÿûÿøÿóÿîÿéÿãÿÜÿÖÿÏÿÇÿ¿ÿ¶ÿ­ÿ¤ÿšÿÿ„ÿxÿlÿ`ÿUÿIÿ>ÿ4ÿ)ÿÿÿ þÿþõþéþÞþÑþÃþ´þ£þþzþbþFþ&þýÙý«ýwý<ü÷ü£ü;û¯û'úæúëú‚ù²øÁ÷žöˆôûôóTòžñØñGðËðoð ð<ðjð™ððûñ°ò¬ó·ôÔõyõ›õEõ$õfõêö{÷§øïúû€ý_ÿê.rÿÿ¸ Q ° k‹D ã†Û»i§ÝÜ“©‹ €ö¿ô  ¡ÜÈ:í_Õàš—1§Ú*×ÿX{Ý "' !!ù# $2%j&£'ì(ß)“)¸)×*O)í*š+z++±+ú,$+<*N)”(ö(™'™&#$f"¯!iè*é¹™†€‡˜³ÙB‚Ë q Î 2 ›  x ì cÞ[Ú\àfíw®@Óhþ–.ÈdÿþÿüÿøÿôÿïÿêÿäÿÞÿØÿÒÿÊÿÂÿ¹ÿ±ÿ¨ÿžÿ”ÿ‰ÿ}ÿrÿgÿ\ÿRÿHÿ>ÿ5ÿ+ÿ"ÿÿÿþýþóþçþÛþÎþ¾þ­þ™þ‚þgþHþ%ýýýÏýœýdý"üÍüCû«ú÷úöúçú.ùCø;÷0õ¤ô{ó‡ò¯ñªñ@ðžðï ï4îðïÃð-ð™ñ-òóôsõ’ö´õÀôÄô?ô¬õ{öŸø5ù{úïüMþË ãR d / ù © 8 áx‘Ûu\N;Sp¨þCåCI¸ ŸûƒHR?"ÀÊ"(ò ;XQöþU½ë%W ™!!ï"ø$%6&g'»(P(Í)x)Ò*{+)+¥+œ+·+Ñ,+*²)î)&(('%š#â" SÃLëžd9  $Bi›Öb ´ k Ð : §  Œ ü{ýŽ¢/½Mßrœ3ÌeÿÿÿüÿùÿõÿñÿëÿæÿàÿÛÿÔÿÍÿÅÿ½ÿµÿ¬ÿ£ÿ™ÿŽÿƒÿxÿnÿdÿ[ÿRÿIÿAÿ9ÿ1ÿ*ÿ"ÿÿÿ ÿþ÷þìþßþÐþ¾þ©þþtþSþ-þýÐý›ý`ý ü–û±ûrûú¦ùöù÷Ûö¯õ®óûóòñÊð¿ïCîºî‹îHî^ïïÄðxñLòIó’ôàö‹õØôåóôó¾ôQö÷—ù%úaûþ¶ Úâ - ' Õ ƒ 8 È ©BPÂZÐB¬ˆ  h JÛ | ,*/n¨Š Æ¿úH‘‚içÑ^?ÝH ¡øÎP ?Ø # ã!Ö"Ü#ë%&!'$(())ç+ +´+Ä+è+¶+·+µ++*q)ª)(l'Ç&Ø$ö"þ!7›¬UÛ´šŒ–«Ëõ)eª ö J ¤  k Õ C µ *¢š›¤,µ@ÌZê|£8ÏgÿÿÿýÿúÿöÿòÿíÿèÿâÿÝÿ×ÿÐÿÉÿÁÿ¹ÿ±ÿ¨ÿžÿ”ÿ‰ÿÿvÿmÿeÿ]ÿVÿOÿHÿBÿ<ÿ7ÿ1ÿ+ÿ%ÿÿÿÿþøþéþ×þÂþªþþkþBþýÝýŸýrýBüüûDúÅúøð÷ÛõÞô¶óØóò ñïvî_íòíîîîDî¿ï€ðjñ†ò‹ó§õôØôió«òÌóô¡öÆø¬ú ûÉýÿõ–u Ç  z ž L ¤ W s æÎVäºoGUa d Z ƒ ü ÿ ¢wõ–KŒvg—n“qäÉ¥Ììj‹0—fÅ!Ú ¿!¹"¼#Ä$Ï%í'(*)«*™+#+£+ý+‘+@++¾+¶+*5)m(¼'ó'e%é#Ù"( säo¿N*,N{²ñ8 † Ü 9 ›  n Ü OÄ=¸5µ6º@ÇPÛgö…©=Òiÿÿÿýÿûÿ÷ÿóÿïÿêÿåÿßÿÚÿÔÿÍÿÆÿ¾ÿ¶ÿ­ÿ¤ÿšÿÿ‡ÿÿwÿpÿiÿcÿ^ÿYÿTÿQÿMÿJÿFÿCÿ?ÿ:ÿ5ÿ.ÿ%ÿÿ þþþëþÕþ¸þ”þgþ+ýÝýœý—ýoü†ûéû#úXøú÷õóÓóIò©ñ¹ï¤îmî íëíÚíïî$îïKðzñÁòËóó7ó0òµñóñpòzõ.÷§ùÖû¥ü²ýïÿÜg£º ) • R â á ¤ } ¯  ÉÉ= v£« d ½ ¯’tSŒ ö‡h†ãÈÏÈ—`¸ŠAê8¾ëy-gíàx½² ¤!ž"›#Ÿ$·%ä'(A)b*N*å+"+3+o+ +¶,.+¥*)•(Ó(6'¥&%$ã"ÿ!N¶8Ís'ë»™„{~¨Íþ7x   l Ë / —  sæ\ÕPÎMÏSÙ`ét¯BÕjÿÿÿþÿûÿøÿõÿñÿìÿçÿâÿÜÿ×ÿÑÿÊÿÂÿºÿ²ÿªÿ¡ÿ˜ÿÿ‰ÿ‚ÿ|ÿwÿrÿnÿkÿhÿfÿeÿdÿcÿcÿbÿaÿ_ÿ\ÿXÿRÿKÿBÿ8ÿ)ÿþùþÏþŽþ,ýÉý°ý…ý6ü—ûÑú^ù öëô¼ó'òWòDð°îˆíòíüíæíÐíÊíæî:îìðDñãò5ñ­ñzñ+ðÉððÉò×õøBûüÄýmþJÿ¢‘;­ V Á Ü p » ñ ¦ ¤¾|kÅW  ‡ ² € Ã/HýáwZžš¦…˜ž[5)k}‚Á_°ÁFØÙÊ­¡ !†"ƒ#Ž$´%Õ&¾()X)Î*++Ñ+´+´+Ñ+º*¯)¿(é(P'Ñ'%#ê"# ’ “,Ô‹O!îèîH|¸ ý J ž ù Z ¿ ) – {ñkædäfêpø ˜&µFØlÿÿÿþÿüÿùÿöÿòÿïÿêÿåÿàÿÚÿÕÿÏÿÇÿÀÿ¸ÿ°ÿ¨ÿ ÿ™ÿ“ÿÿˆÿ„ÿÿÿ~ÿ}ÿ~ÿÿ€ÿƒÿ…ÿˆÿ‹ÿÿÿÿÿÿÿŽÿ‹ÿƒÿqÿOÿþ¤þ:ýöþ'ýÜýü¾û`ù{÷õóÓò„ñ—ï×î6íªíÑíÐí«íŽí‹í¹î>ï[ð³ð=ï¡ïï6ï>ð&ñ³óÆöøœúÊüwý›þ¦ÿÓ>­  º r E # 4 — à ¶ ½ •’”×Z)K €Vddk´­pu&BBÿf¨° •ö¼mǦU:7ŒÖôÆC  þ ôØCUëÕ • †!€"€#‰$•%¤&Æ'î(¤(ñ*K+x+Ú++‘+5+)Ç(í(W'Ö'Ý&º$š#!„ëcí‡.åª}`PNXn‘¿ö6  Ï & „ ç N ¸ '˜ „þzøyû¡-»JÛmÿÿÿþÿýÿúÿøÿõÿñÿíÿéÿäÿÞÿÙÿÓÿÍÿÆÿ¿ÿ·ÿ¯ÿ¨ÿ¢ÿÿ™ÿ–ÿ“ÿ’ÿ‘ÿ’ÿ“ÿ–ÿšÿžÿ¤ÿªÿ±ÿ¸ÿ¿ÿÅÿÌÿÓÿÚÿâÿíÿøÿýÿãÿÀÿoÿÿ=þñþ·þ^ýûüú’øˆö1ô,óñïîíÉíàíÁí…íEíííKíÎîJî?í­îîµðñqóôìöÞøÍúü>ý‹þÛ w 5KÚ ¨ M ¸ ^ f 1 › · ‰Òcf Y  .GöñWx.2_Wñf»ƒÓÖ–5C5î‘Ò@•k >!Â!ñ!U ËÍ(c* Ú¤§ £!"—#”$—%¥&Ÿ'/'Ñ)-*•++W++w*Â)Â(Ã('((1'%2#ù"y ×=·?Ö|3úÒ¸¬®½Ø3n ² þ R ­ q Ú Fµ( ‹ Ž™!ª5ÁOÞnÿÿÿýÿûÿùÿöÿôÿðÿìÿçÿâÿÝÿØÿÒÿÌÿÅÿ¾ÿ·ÿ±ÿ¬ÿ¨ÿ¥ÿ£ÿ¢ÿ¢ÿ¤ÿ¦ÿªÿ°ÿ¶ÿ¾ÿÇÿÑÿÛÿçÿòÿþ (:Pj†¤˜ze5ÿïÿõÿ¼ÿrþgýûXùöÈôôòÄððïînîWî$íÏífì÷ì‘ìLì8ì6ìAí0íÖîãð.ñ‚óôyö÷›ù.úÄüGýºþx2€/èJ1È… ’ š ( ô B v r ‰Ÿ‘£ä X ç Û£H<&_ÎðÊmþ¹¥8äƒÙò´}~ÙpÍ›Éy @!´"N!… ¸ z¼ó][þú  ü!í"á#Ý$Ø%º&b&ü(;)‰*p*œ*Þ+*¶)b(2'Ø'Ë'&¥%è$Ö#!Í %ý»uA @m¤ ä , } Ô 1 “ ú dÑBµ,¤œœ¤*²;ÆRàoÿÿÿþÿýÿûÿùÿöÿóÿïÿëÿçÿâÿÝÿØÿÒÿÌÿÅÿ¿ÿºÿ¶ÿ³ÿ²ÿ±ÿ²ÿ´ÿ·ÿ¼ÿÂÿÊÿÓÿßÿëÿù(9L`w“´Ý @u ¼Ÿ›ÁgÿOýNû4ùš÷¥õDóEò/ð*ïuî÷îíðíRì©ìëië#ëë‘ì”î.ð/ñÊó9ô•õè÷øQùúÖülýþŠÿ o¥©ÖH ' t P s d % ä 3 ˆ  ² Î È f ó î@Þd­ùZz}*|{s· à’ «Û¬äúnc#Þ!c"!ˆ Ý ’ j¤"9I¸ÂÁ «!"€#ƒ$…%c& &«'G(Z)¾*,*Å*´)Ñ(‘'š'G',&ð&…&P%þ$j"Æ!/i½'©Aí­~`RR`|¥× X ¥ ú U ´  €ì[ÍA¸2­+ª+®3¹AÊUâpÿÿÿÿÿþÿýÿûÿùÿöÿóÿïÿëÿçÿâÿÝÿØÿÓÿÍÿÈÿÄÿÁÿ¿ÿ¿ÿ¿ÿÂÿÅÿËÿÒÿÚÿåÿò"5I^u§ÅèI…ØÛxþã÷Zè˜ÿßþü£úø`öwôøóñyðNïžîåî!íNìeë€ê–ê ê‹ëˆíŒïñMóqõö÷xøMøÃùˆú–ûïýŽþÉ rÜfÒÿÅ’ À d k  ÿ ² d ' ! í  mp“ÄãÔÜåBRzÂľs+Œµ! ûvW×:,¯m ü!u!= ø · ÔèTë“í  É!n"Y#Ž$ª%™&+&›&ø'(U)¬*I)×(ˆ'˜&ò&³&¸&˜&…&{& $æ#ø"2 GzÊ9Á`Û´ž— ¶Ú@ ‚ Ì  v Ô 6 œ sãVÌC½9·7¸;ÀFÎXäqÿÿÿþÿýÿûÿùÿöÿóÿðÿìÿèÿãÿÞÿÙÿÔÿÑÿÎÿÌÿËÿÌÿÎÿÒÿ×ÿÞÿèÿó"5Kb{•°Íí9j§ö>€Êµ0/´O¿ÿDý³ûIù÷Zõªô;ò]ñð4ïSîgífìFëê é`êlìjî,ð¿óõV÷bø\ùù&ø®ù#úû¤ý–ÿ©æÞ¹Ù%¨œg[’  … ð Œ   ° è N Ù 69ë6ñ”jÆýHl6ë«=iA«I›ß¶*ÅNØ  o ƒ — h /ËèV1ðT ²! !{"N#ƒ%4&&Æ'&ü&ê'j(%)/(Ä'‹&§&Š&Š&I&w&p&`&%J$³#4!&%a¿9Ìu3æØÛì 6k © ð ? – ò R ¶ ŠùjÞTÍGÃAÁCÆKÒ[ærÿÿÿþÿüÿúÿ÷ÿõÿñÿíÿéÿåÿàÿÜÿÙÿ×ÿ×ÿ×ÿÙÿÝÿâÿéÿòÿþ .C[t­Ëë 0V‚´ò>¤“¡Z]áO·Ì<ÿÇýüûgù÷€ö%ôgóñàðÛïÒîÉí¾ìgêöépé’ë>í}ð?ò/ô¡÷qùùÿù•ùøÄøÝú üþÌq…HƒuB bÊ±Ú X ¬ ·  £, ¾ ! S å JýƒôF䤀G<d,UÕÒÆÖÅLËkp)@:„Ôb’¤–)†FëÒ½&ü ˜!3!›"6#K$œ&'â'š'E&à&š'D('è&ý&e&>&f&‰&_&p&[&%%K#ù!¡µé;¨/΃L(:a’ Î  _ ´  l Ï 6  }ðdÛTÏLÊJÌPÖ^èsÿÿÿþÿüÿùÿöÿóÿïÿëÿçÿäÿâÿáÿâÿãÿçÿìÿòÿû$7Ldœ¼Ý$Ho—Âò*j›ÇWØ•F+nÿPýú—ø²÷Uöô¾ó›òÎñ„ðgïPî.í4ë:ê@ê³í+ïwñ“óÍõúøùÔúrùêøèø ù'ú&ü þ£ÿíh#X+{òÏ‘ ­ E oqë̃ < Õ¼%ÍÅ.ûIà7û>#¸“Œ…W™~¡W¦Y4;7èwÓÓˆ&´FcKr  (!X!Ñ""Ã#à%“'¬(('u&ï&¹&¼&ü'&«&-&5&“&°&„&n&z&*&%-#X!× #c« ˆËcKDMdˆ· ð 2 } Ð ) … ç Lµ!téaÚUÒQÒUÚaêtÿÿÿýÿûÿøÿõÿòÿïÿìÿëÿëÿìÿïÿôÿú *<Rj…¢Ãç 2YªÒû%Tƒ¥È†šÜIàÿ2üÓúXø÷ö3õ ô*óaòXñ-ïØîáíšíì€í`ïñ€óõk÷ ø¦ùàú{ùÐøìø¼ùfúgûŠýÿÿ½{½ÔoM…”v  D Ô(9È,;1´fðQÒÈe“¶©§Ö¦ÇpenzsaI&ßÞ«­…9ÊFqoSÙš™%ý$ h!â!Î!ä""Ü$N%ü'X']'&Ë&˜&h&q&Ò&±&t&Ð&×&š&ë&ë&u%¹$¸# !Ù •ÔbÔc Ç™|qvŠ¬Ø P ™ ë A ý aÈ3 ‚÷må_ÚXØZÞdìuÿÿÿýÿûÿùÿöÿôÿôÿõÿ÷ÿû -?Tk†¤Äè7aŒ¸â .PtÑ|­Z0. ÿ=ý\úàøe÷cöõƒô•óçó~ñ†ð0ïJîýîŽïOðò ôQö.÷yø—ù}ú6úwù_ø°ùùØú–ûÈýCþ þÏÿÎ-—†õÕoùš# Ô ò2|·<nrr{[É}X-ÜöHëÑMÝ2X^„±éQ™‘•Ý ™O±;¹û…nAÆhD+ >!l!_ ú! !š"Ú$v&&ø&ÿ&ò&²&c&ˆ''9'7' '_'¦'ñ'¼&–%z$C#8"w!N`¨@ùǧ™›¬Ì÷, k ³  Y ³  tÛE±xïhâ_Þ_âgîvÿÿÿýÿüÿýÿÿ"0@Sj„¡Áå 5a޽íD`r‡¬íaÛ`2¿j&÷]ÿ¡ýËûrùo÷çöØõÖôâô,óXñsðïßïƒïÔð÷òÿõ5÷ëù ùäúeú¼úÈúdù“ù9ùOú;ûPü‰þ&þùÿ´È«2¶£ÚCFr* r U É I Ø”dq‘°Ë±è"ÿŽ>+ŒX:oþ³A„Æ‚§j”$ºE¿&(´&5[Ó9¨+«â ³_ !["õ$­&')'4'&ã&Ü''•'ó((N(Ù(Ò'î&»%f$.#a"ß!Æ—ÜFÍm#îÌ»»ÊèF „ Ë  n Ç % ‡íUÀ.žƒùqêfädæjðw  %1@Rg€›»Ý,X‡¸ë"Zˆž–…©¢-ª)¿VPáÿËýºû’ùÉøS÷ öõô òáñ¡ð•ðFï¥ðÎòãõBø3ù¡û„ü üûþûíûúÕúŒú¡û7üiý¤þ¢4?Zj¥.=^è|Ó¸6Ë Û  Ü K h & 8 W[DÊ(ˆ§µ‹Æµó†Ja|-ͱè!vš™írñ_ª±£îô¿ÐYeÿôÛvß{!w#r%''‚'y'{'_'(K(Ü)))(Q'Ç&Í%U$<#•"æ!“Ž´põ“FêØÖä*] š à - ‚ Ú 7 ˜ýeÏ<«Žzòmêiêmòx  '2?Ocy“±Óø L{­áV™ßôÈ”¹JítÑz](®Üþçü»û2ù»øl÷HöJõeôZò÷òPñ®ð¿ñNòzô®÷ùEû!ü}üÌü²ü‹üŒü¾ü€üfüYüªý£þdÿv—݊ 1G cŠ0±- ¬ ‰ õ |  ë ñ u FI‘ïZÀ,†%Øž&œöð@Š3BšA¤ ›í<˜,»?Œ¬ÍGh³ ªëe·ZÅ~<ô× v"‹%/')'¿(([(N([(µ)C)m)Š(Å'm&Ç&@%$$#x"³ ÆTÌ/˜³d*ðíú>q ® ó @ ” ì I © tÝI·'™ ƒútðnîpôy !)2>M^rЦÆé;jÒ IÖCì‡òŒ8Ñ·o¤ž“"ÿžýqûæú°ù‚øY÷Mökõ·õ(ôIóÎòÊòiòÂôõÙøú/û¢ü,ýüÍü\üÛýmþþ'ýÌþþ¸ÿƒl«CìBDKÔuUf8ûŽ¢ z  “  g   H/š1—à@¨KͦÖÁsj=ÍHØåf»Ðd°7_¨î°¾+š·ˆ8c L Ô Í£—ᦧ¶» í#%U'#(p)_)g)X)(Ø)"))·(”&÷%µ$é$#×#(!î l*l¾9Ï|@ÿ 'Pƒ À  Q ¥ ý Y ¸ ‚êVÃ2£Œ{ösòsöz  $+3=JYlš·Øþ'Uˆ¿ú;ÉD¦¶'Ú†÷– $—»þÁü§ûjúQù8ø÷"önöõ±õÈô¥óÏózóÐô¿öPørùÏúœûøüÔýüöý@ýÙþ\þ°þÏÿ=ÿâ•YNƺ…  /Gmï[àfNïa(§ s å  ö jÝ   P ÉEãÉ9®ééC[ësPÔYûÊ®b JGaµct/Va|Ôçß5®.W¼v±ø‹ ­"{$X&'Ç)T*.*Ä*„)Ù)9) )Q)€(»&Á%¿$»$# "É!™ OxVŠàXé’Q' 6_’ Ï  a ´ h Ç *÷aÎ=­ ” ‚üxövø{  !$(-4=HUex©Çê=n¥ã'qÂ]q÷‡¼m/Ø5 ýÙ'ÿ¼ýúü_ûúøà÷¸ö¢ö õñõìõ²ôÕô"óùôCõö=÷©øÞúEûüÉýQýjýuý¸þNþ±ÿE ¸1ÅöªÊ z Í–~}ç_a’ Má n } BÕ” N ß âeŸû ‚1£Ôû¸÷qÔdì£ðÞEŠ›yˆÆ+Çzý):kn¬Xq†LyÚ‚Ì Ó"Ô${%à'G(¹* +,+¿*x)\(Ý))'ã&×&$Ó$>#ƒ"“!h a;û•x¤_2%Bk  Ý # p à  v Õ 7›mØF¶(œ‰}úyú| !"$%%&(+05=FR`p„›¶Öú#Q‡Ä Z´~Ö° uðÉ…Å·CvíSþ‹ýûðúáù»ø{÷$õÆôãõõ6ôºôTô ôôVôìõÌöîø{ùsûoýýµýÌýƒýþ)ÿ%8TQi Ë´ Q &SóÙLJ9Ô?!ß 9 óºÆ O  í‘ãZˆïhuSH3ú{µk¿tG’Vƒî9Ÿ<Æiíïï&ošm³ÃùÓ !R#$Ü&c'(‘)¬*õ,+,>+×*…)l(s(j('U&~%“$ú$C#i"L!=á‡À¤/ž³i:# .Lw¬ ë 1 ~ Ñ ( ƒ á C§wâP¿1¤‚þ|ü} "%')*,-/27=EO[iz§Âã3eŸä5•†‰}iÔh-ßÎ*3£ÿ]þfüxû‚ú¨ù}øöcô¥óSóuó–óeó}óÀóþô-ô”õ5ö÷_ù{ûü ýÏýýVý—þEÿ£{ÊØn¡„nS ;ýš‹QÞÑÆ Z à 3 3ÿ ã \ TWÿ?$p»¶¥)ü Ï … ÊrG »QÄÜ;_Y#ýä\-Ü}D·@hö]Ò ,!U"Þ$&§()))Â*¾+,—+¾*¡*a)M(ˆ('Î'%ÿ%O$Ê$¤"÷"!/üå'…È.¼o?('6V¸ ÷ = ‹ Þ 5 í N²ìYÇ8«– ‡þ~ #&)+.01369?EMXdr„˜±ÍîBw¸dÖa Éz …æ4Òò{ª1Æÿ?þÔþrýÖüHûdú”ù]÷Òõåóò4ñ·ñÍñïò—ó«óÓóêôôRôòöKø(ú'üüõý*ýaýÃþ·å½€¦í S Î ú _llÒqߌ¨1ÑB d É ´ Ú m  O 3Øç]œB’1Î,› » ô  -\NÑl•ù18=œ®âŒ6ÒÖ+#ü€^][ " é"ª#¿%='0)B)þ*•+,R+œ+U*½)Ô)f(s'Ä'l&w%×% $î$h"ô!Ô!6 ÌóBéßá3½oA,,>_ŒÃ J — ê A › ù Y½"ŠôaÏ?±%›‹‚"&)-0368:<@FMU_l{Œ¡¹Ö÷O‰Ð(”Á”Ë"™ÏMŽÿ¥ÿýíý×ý+üRû§ú»ùn÷ËõÅóñçðøðôñYò7óóóeó\óDó~ô–öhø%ú+û<ü`üãýŸþ o«h ˜ D ~ è Ì 3 i … ‹ª É ÕΗç @ Ì f i Ü f  Ì Ö¾'X0uÒV ô ÷  M „{J¶_=VÌÖI`މTÉàí¢æ !ƒ!l Õ í! !Ä##ö% &ß(Ñ)ü)û++?+X+;+!*…)’(O':&»&A%U%$#Ï"‡!ƒ! ¶ ¦¨MèÍ"³kB03Gi–Î V £ ö M ¦  dÆ,“ýhÖF·*  …€  %)-159;>@CGMT]gt‚”©ÁÞ)\šèIÂ[*Eõ"¸Ôróéß##ÿzÿnþ*ý¨ýü9û%ù´øöôñÔñ2ð÷ñ=ñ÷ò@òˆòÓòÊònñøòéôXõÀö¡øºúGûXüýïZU} 6…‘xå” ¶ “ ¦üfŒØ:í ½  z j k ® p _²i ùk}ª„9àÄ a Ÿ C ð ó ÏŽ@ùȹå+¦ }Ÿºxç×\v€± ©"">!ß!Ø!¯"1"Ó#¥$|%©'m(¥);)Ì*z*´++B*ó)z(+'*&k%»%ß%8#â"z!q!B º 6—kI€ù¡fD7<Rt¢Ú b ¯  X ±  mÐ4›oÜK¼/¤’ ‡ #(-16:>ADGJNT[dn{Š›°Èä2g©ýgî—id‹Q,8ÇïÙ‰­ksPeøÿ»þÁþý-ûèú7øWöÔôJòñcñ5ññdñ•ñ÷òkò‘ò>ñ‡ñXòóœôYõø÷ûù%ú|ü³PÓ— lþžÏ……m ´ S ] ¦ |¹+ . Ü Ç ) g 6 ½ A% ÒF‹íŒ2§Õ­/”> ¦  £ õ ™ D ßv$J£5ï—éð%¦{=8«úå á!â!•!N!<",#V#u#V#æ%?'O(>(þ)&){)Æ**D)N'ø'&8%Ý%¾$õ#y!Å!$! 02C–T È‘fLBI_‚°ç( o » c ¼  wÙ=£ vâQÁ3¨•‰‚ &+16;?CGJMQU[bkv‚¢¶Îê:q·È©·Ç}+Ax½Vdè$U€Cÿùÿ#þ?üÝú´øŒö—õoóbò+ñuñÊñ•ñçò>ò}òò…ñàñ ñ‹òIòöôSöW÷¡ùbüä` ÿ55bª^ñ  ° È & ³ a W ´ ‘ ¯ ® t ä ô Þx@KŒøFÙNr¶>w2 š K Þ ó ] Ò < ™ìYˆñâÆ1ڪ͑Žìºï•¼O ² M z ! !Û#+#N""›#Â%j'1'q'ì(‹(ë)')(¢'®&ä&?%¯%§%X#¢"Z!í Õ¿„ýÚGy¤ª‘s]U\q“À÷6 | È  n Æ " €áDª|èVÅ7« —Š‚ "(.4:?DIMPTX\bir}‰—¨¼Óð@y–.ëÔí hÖ¯|¼BœÆÐjø %ÿOýYúóù)÷%õÐõBóŒòòò˜òò°òÛòÛò³òò=ñÇñcñjòhóàõŠ÷UúHý\·¾ R õ,PK)È ä ³ Ÿ æ n * ! t ¥ b€« Ê+QVû€ìD¬½ŠŒÀ`  q Û å - t ¨ Í û Æû¼)¥Æ{ÇÖa¿h%@f>ú¶yþ Á!"˜#B"Å"Ó#f$o%¨&,'6'å(T({(V('f&Õ&[&,&!%‰$|#‹"°!BŽSjI˜Á°“|qu‡§ÒF Š Õ % y Ð + ‰éL±íZÉ:®"™‹‚ $+28>DINRWZ^cipyƒ­ÁØõFÌ,¦@þåöÙØ Ó´žÙ2¶ñþô%X,þpüúøŽ÷öõô$ó¶ótó]óÃóaò°óò÷ò“ñüò]óˆôõöÕøóûWþ!úòù Ó X ¬ Ó ¢ } 9 › Ü 8 ¼ z k a ì¹ö«Õ¡Ÿ>›Ì§í†¨ìJæŸÃ» i ¢ Í á  ; ' 6 úН ”v‡j©f1ý#ªy|nÛ–³³ ¢!¢"'##L#=#¥$]%;&r&Þ'h'Ð((7'È'D&à&´&±&½& %2$;"ñ!v Ä«É ÝôÊ©—•£¿çV ™ â 0 ƒ Ú 3 ‘ðR·†ñ^Í=°$šŒ‚&.5<BIOTY]aejpx€Š•£³ÆÜùL‡Ô6²LÝÔq*­¶ÁØ`Hb“ð¶Ù{å,É—ÿQýûùx÷ö¾õÙõ ôyôIôTôaóåô ô&ô8óåó¶ô‰õ»÷0øÄúü‘þÑ@¿U x ç ä œ ™ È \ ê ™ h R ’  Ì f‹K¿åÇnBÔÒõsŽjëÓŠîȵ8 ð <    6 @ ü e p s=ª%Œv†ó)Y©Ð¹¶ˆ!6? €!°"Í"õ#@#d#Ñ$†%s&A&ó'R'q'û(:(9'W'B''.'i&ê%r#õ"¦!l rœÅuh®ZäÆºÂÙþ.g ¨ ï < Ž ã < ˜÷X¼"ŠõaÏ@²&œŒ‚ )19@GNTY_dhlqx‡‘œ©¹Ëáþ!PÜ@½UÌšEìÝÿ3›¨•@¹±GˆJW ÿÿýéûÙù@øv÷,ö{õ×õôïõ†õLõ2õNõ~õ“õŽõýöÙøùBú‹ûÓý‡ÿzª½¹U £ ™ _ à )  ß Ù ø 6 € , Ä Ÿ œmK§h.EGçT¶¿‡/’ÏÓ ;œ Á £ K u ’   — ; ¾ ¦ `á»™”¾G€X^¶ÌKï2㨟ÿ!Š"h#"î#'#Â$ %w&a''–'Û('(­(Ô(o'â'•'‹'‰&²%$"ì"‡!u ƒäSV» ^Õo'úååöCy · ý H ˜ ì D Ÿý^Á&ŽødÒA³'œŒ‚"+4<DKRY_ejoty†Ž˜£°¿Ðæ&U“ãIÉbÊ€A-UxÏ*e‚‰4’ëMпÛþžûéù°ø>÷µ÷ö«ö]ö.ö õïõûö…öÏö¸÷.øù ùùûûªüÔþ ÿþí÷,xù'*÷—”·ú f ê K ½ `  è Èž­Àà„ „ rLƒ­ˆ+ÔL?^|Mÿk N ¡ Ñ = 2 -  È / j¾p¿i*L9çõ£Èï: äÃÀÛ6¤X³ µ!|""V"¾#£$¶%É&®'ô( (=(~(÷)Ê)p( 'â'™'[&„%y$i#¬#K"c!2 Ô!ó TÊm1 0YŒ Ç S ¢ ô K ¥ bÄ*‘úfÓC´(Œ‚#-6?GOW^ekqv{€†–Ÿ©¶ÅÖë+Z™ëUÙx,é™*†¿×}5(eÒhœœ9…—êñfÿZü›ùÅø ÷ü÷Á÷±÷|÷EödööGö¬÷÷¿ø¤ùÞûûQûyüaýZþ¿©B=&խѶUî÷ 6 ™ 8 ã N ] ú –{jç ‹ . 3 ™Q3C®ù!Nnñ†X¥ s ³  Œ ° ßsÀ Dͺ¥òJ|d³©_Òe’JZñï„ O Æ!¨"\#¶%&('æ(Z(«(˜(¥(ù)~)ù(ß'é'['&x%¿$€#‘#_"}!•!=!$ Í0Ý´À¯g=.3Jnž Ö  ] « ü Q ª fÈ,“ügÕDµ(Œ‚%/9BKS\dkrx~ƒˆŽ•¦±½ËÜñ 0` õcî˜\9 ¸>n˜¸gV¿tDW|)Md^ñýŠúüø÷÷Öø øRøT÷˜ö[õÃöö™÷cø}ùâû?ûûûúü$üÐýýÿ1<&æ£Óºª…=Å'fOþTÊ | … ‹ % 2  Ê \ ›  Ð ž^#O@èC©¨9  Ô á r…¢[ðÉB;ú S¹§¨*fŒeT`Ô´Á«Q—5ÁUÝ!"‘#ð%v'3(])6)(×(˜(}(¬(ì(i'd&Ü&&F%$I#n#/"‰!Ê!3 ê “diaé˜gQQcƒ¯ å " g ²  W ¯ iÊ.•ýhÕDµ(Œ‚'1;EOXaiqx~…‹–¥®¸ÄÒâ÷6f§ÿr¿œ£Ü€ä÷Ùß;6Míx`}ÍëCH.þÊüaùKø÷ˆøø#÷„öfõjõsöù÷øøÒú¬û×übü~ü„ýmþŠÿª˜­® í¡Å<Ö6D¥¥€† Ü % [ Ñ R › + U Ý>7"h>ìÏIÌH½,w´ ý ! Ö » ³t£Fòš“Ù~¨Ð°uujÕT"¡ÁOp[å> N1íñ Ì"6#Æ%q'n(¸)[)Z(ß(W'Û'[&å&º&s&+&%µ$ò$#8#"»!è! ‹ ½=•Ãqly–¾ ñ - o ¹  [ ² jË/•þiÖDµ(Œ‚ (3>HR\env~…Œ’˜ž¥­¶ÁÍÚêþ=m¯ èâ+xž¼©Aâà O #ÚÈ @o”éA”uÉæýÈû3øâ÷§÷a÷Ç÷…öõ¦õã÷ø^ù½úúü£ýüêüûý¬ÿe69Vÿ–ÿcÿªz(tl5Ã<:‚ý ’ ³ K j  L z œ! œh$ÁWàVÐò Å ÿ Ì ’/äz §Hì˜-»i®ø*{É—.Ѻ˜Y×8¬[pèÊ!o#$è&Ö(z)S)A(½'þ'0&$% %%=%\%r%I$¡#Ì#-"×"Æ!ñ û 5vzà b¿@欄¦Ì ü 5 v ¾ ^ ´ kÌ/•þhÕDµ(Œ‚ *6ALV`js|„Œ“š §®¶¿ÊÕãó!Eu¸6#/  ® NÈ8 ƒ ½ ¦ lzù &£²ZÖ2~îÿlüœúeø8÷þ÷È÷™öÏöBöˆ÷ÀùQú·ü ýýµý2ý5ýÍþé"UX6+0ÿ«ÿ4ÿPÊñËz~ð‹ƒa  è è   8 Ïè(¿ä4Ànœe®UÙTÓVâv ë…ÅM(?É| ÏÛŸq®DðÉsÈò!~<QÞ·¡ u"G$2&&(%(ž)&(Š'­&Š%^$I#õ$8$l$™$œ$p$##"­!Æ «îtß<[‰à_Å£—ž´× < {   _ ´ jË.”ügÔCµ(Œ‚  ,8DOZeoy‚‹“›¢¨¯·ÀÉÓßíü+OÂJ1Z×E Ž D Ç D · † ù g ÿÊX‡pn^:àüíÿÓý8ûùùø&ø÷ ößöö›ø+úû¡üÚýÊþþ%þþSþøÿ¾#l€zw\+L÷ä¯\ëö,ûsǃ ™ t  ´ J & î&˜®ªÍÝæË›Påqù“–%0i¼‰†"àÐù_Š h Ï «¤ÝÚ›GKùç$¼Á`^žp!k#%™'.(«(·(^')& $À#õ#a#W#›#›#²$$&#œ#L"[! L³uÕž¨õqÕ±¤©¾ß @ ~ à  _ ³ iÉ,’úeÓB³'œŒ‚ !.;GR^it~ˆ‘𢩱¸ÀÉÓÞêø7ZŠÌ)ª]R’Ä % • ú B K² N }  ±E²ÙHœè )Ÿ3Xÿ¿ýúóùTø…÷¬öäö-õÉö6÷€ù„ûŽý(þ\þäÿÿ ÿÿÿèz½åîëßÕ㈚}á(ft\Ë$. m 8 ž ò î ½ DM"t¢¸ÒÖ†0Ù…SóÑåVª ¨iTm€b%± ¬(<ëUæ´ýÍv€êÓŠ&U` ˆ"É%':(§(l'D&—%™$…#"³"Í"è###}#Ð#g"å" Íôc3 Á®ªötÛ¹¬±Äã A ~ à ] ± fÅ)÷cÐ@²%›Œ‚ "0=JVamxƒ—¡©²ºÂÊÔÞéö*Dh˜Ú6·pwç 2 Y ¢ Á z—è ð ì™9ÊV  5 ;?SÍÿ‚üËúdù ø(÷&ö^õÕõ•õüöýøÑúÎüÖþUþÜÿMÿÑÿ­‘Bcw¶öHžë&IéM“7ht ‡ h û # ± þ / ñÅíãS»Å¬t;ÑžoPGW~¹cÒTë—k*ÄLö2è3žÁÖƒ¸k'ðôú̪gÿT‘!÷$'(6'Ý&¢&%:$;#B"­"`"e"l"§"Î"ö"Û"Z!Å Ø­ô¯RM[Ýc×·¬±Äã ? | ¿ X ¬ aÁ%‹ô_Í=¯#™‹‚ $1?LYer}‰“ž¨²ºÃÌÕßêö#9Tx¨éEÇ„œFM § R ã FÄAn­ïUh4ÞÛ|  Gk(èXÿSýwû•ù—ø÷fö¨öCöö÷øoúgü1ý”þ—ÿn ¼7¢ÇÕù*-)+:Z…´ÞöäŠÃß|vù © ( ·  = #  Ï `j¥ÓŲ›~V!ç´“ˆ•¸î5ŒñcÞ^¡_ž{‹¹1õ[©Dœ\Õ(¥à%ÄMÒ1ˆ!#¢%æ'#' &»%°$Â#Ö# "u"!ã!Ý!é":"""!Ÿ ‘Y`½=Ì6¦?öÆ­¥¬¿Þ : v º  R ¦ÿ[¼†ï[É:¬!—Š‚ %3AO\jvƒŽš¥°ºÃÍÖàëö!3Jf‹»üWו³w ¦ º L¨=;¶ÜŒÐé¹åÍJ”(| ØÿÀþ üDú¾ùbør÷´÷<öý÷÷¨øÇú0ûÀý5þiÿ•Ã_J¤[i¡ÛõîÕÀ·»ÉÜìóæ¶«ˆ/2ç Ç m â L ½ # ¥ – ™ À ð¥%8ìðñü  î­Z ̦š§Èû<ˆÜ2z›xqéŽ †ö <tZì_QSSÀò•¥Õ"0$‹%¡&Z&% $!#M"œ"!¥!V!1!Z!m!L!^!Ñ!q Gà­¶ú:¿VÏ¬š– µÕ þ 1 n ± ú I žöS´éVÄ5¨” ˆ &5DR`n{ˆ•¡­¸ÃÍ×áì÷ 1E]z Ñk螬Gªí´`ú  Aåë"ŒÈUþ4ï4d*lÿ³þeüçûmúlù„øÈø;÷ç÷×ø'øæú$ûƒüóþ^ÿn´°Fš²Ù^Þ Ó‚R1 D°“á Ž y Ë ø o Ô-‚"Ÿh¦×ù ^¾´QÐSñ¯†”µã[›Ó÷õÈw3î wÏŽ‡¥Ö V 4  ~y˜Eûë7Ô¡e }"›$V%$ì$'#S" " !!' ¼ g o n J | þ ÷ð:ÙÉûZU2ワˆ‚¦Ç ñ % a ¥ ï > “ìJ«xâO¾0¤‘ …€ '6FUcr€›¨´ÁÌ×áìø!1CXr‘¸ê+‚÷žˆËîJÏ8½   g .×3ÚÓ/o`ì ®ÏaÿÉþÁý„üWûIúgù øøøuø$ø"ø˜ù“û0üdý»þê*Rt´ ·Ý7.Û£‰nUGJi´?]­æ ¹ ?  ˜  ¼È8¡h½'ñìýUÿÁ¼%@‰þ¢lUTe„­ÞPˆ°Ã¡"½¾Ô4 æ æ94 à û   h‘Äà®`Q÷ ¼"²#p#‹"ý"]!Õ!b! µ ?©Œé‚• I JEÕÊ Vz{od^_hy“µ à  R – á 1 †à?¡oÚH¸*žƒ )8HXgv…“¡¯¼ÉÕáìø!1CVn‰ªÓH››Z=Ó|E¾Ú ! 5 ± £ h    ãK†@ ›Û5ÿ2þý üû#úKù„øÎø3÷¯÷§øYù‚ûsý þeÿ·ÑZ‰é«v ø†Ù¢zx¡ý``z| ¡ ³ ´ X ß r0& %Uµ——~¯-pÙ¨’æx6 !=b“ÕB–ÑÃ%q‰ ¡ G u t ‰ ² ¸ ” –HXšx³Mr]ÿ[ !À"!º!U ù ª q G ymÃ}:Áó÷1* oÌ $-3<I^zž Ê ? „ Ð ! wÓ2•ûeÑ?°#˜ˆ€þ~ *:K[k{Š™§¶ÄÒÞëø"2DWl…£Æñ'h¹›Oçyu<…o F  b 2 ­ c ( â » TM8ÑóÉÿ­þ‚ýŸü­û¾úÖùõùø'÷OököµøúWüeþ#ÿ0G]Ûh*ìIª–©[ËŠˆ½&»z]Xc y « Ÿ @ ˜  àªÆ-´ÐÝ–’õ•'nQ 0ëÄ´²ºÌåPÆ{m&JŸ5¾'  h  ÿ ©'‰À¬Yÿº_d(éÑ  ~ y F éп¨§}‡^¥ † <|ékOŒF¼ëþ '>\‚ ° è ( o ¼  fÃ#‡ïYÆ6¨‘ ƒÿ}ü} +<M^ož®½ÌÚèõ"2DWlƒŸ¿åLÞ;¨9¯pÐÛÖ¬îé ê q . ß  I ± v o &{º±Âÿ¹þäþý3üAûOú^ù`øE÷%öö÷ù¥ûÅý&þfÿ…NíHŽ˜­à½ÑsO¥`m¼9σVA@ M g Ÿ Ò â ` 0bI~ˆ_ §ï8™W-²X‹¸*ËŽjXQSYhƒ½(‚MçÇ}D üU À [ H ‡‘[¯©a€ïz—ì"é¸.öA>-("' %}ñô S ä ¡6Ý[ÂFv'¤ÌÛäð9a ’ Ë V ¥ ù S±xáM»,ŸŠ~ûzú|,=O`rƒ”¤´ÄÓãñ 1CWl‚œ»Þ ;w½iËE…œŠß[ï5¬ K 1 Û 3 g M f ‹ f°½ AÍ>ÿQþœý®ü·ûÀúËùÏøÏ÷Ò÷‡÷œø'ùƒûü1ýwþ”ÿo…ü÷¯í·Íur¹.ATÂDØ„L+   ž µ < é ” öÈ«—C¢ó¶úDÉI‡:*æ’P#øðíëîú zŒw}rvg[#¿% ¼ x Ôz;À–!ßÏZ˜ÖLªR¦yd .B_‹œYû— = t ˜ ‹ Jäo„ÚŽ&E¨ÁÅÁÁÉØñ< o « ð ; ‹ â =hÒ?¯!• ƒýy÷wø{-?Qcu‡™©ºËÛìû /BUk‚›¸Ú0g¨õL®r¸å:ÌPëi×M˜  a - ó  ù R ¥ £øñª¤gßÿ%þ(ý(ü.û?úZù‘ùDùù?ù€ú"úëû¥üÕýðþËÿuÿùdœ=nŠÛÖ+‹ã(ÝQÚ?ùá Ö _ Ù =  W°oíh ã Õ ` I ¦R¿ÃÞ í˲¡˜’†~’¯Ô PheJ*úÁˆ œ v Á`B“¤ö+yõiµSÍN%Xj¿T˜«£ j TÜöð*EHTÔäPùÈ«žŸ¬Åç J ˆ Ï  p È %‡íVÂ1¢‹|÷tótöz/@Sex‹¯ÁÓäõ*>Sh€™µÖû'[™á7› Š‚ä…-—ÅÈù`  c œ ˜l { n ® ø «ïª”:üÊÿ¾þ©ýšü›û´úìú_úùÈúoúqúœú¤ûü˜ý“þ^ÿÿ€ÿÒBÉbÓN¿Hû7Úþ Y×v0ÿܹ °  ƒ ] ƒðœE r M  Ø @ k ! 9  “ Ç ÿ-JNG@<:95-!:zò1. 佘, ¡ ' )J$®ô¨…7S¿VCAZ“·g^”Õ jÌ:ƒs2ÅfÅÔíAdàf¥ÌÃvq}•¹ è b ¬ ü Q ¬ pØC±!” €ùtñoïqôy0BUh|¢µÇÚìþ$9Ne}–²ÑõO‰Ï!ƒö#çÏ—i”¾ÜÒ´   ¿  Ý:™ Î Þ  o × ÷@H¡?ë¢dÿ2þý ü&ûtûúÂúâûûúØûûÁü ýnþþ­ÿ%ÿÿñY°ÕBŒ _º‡rIWÎk!ê¢ — J ò … ` i{g q · o V Ê ý , T T = È  W ‡ ª À Ì Õ Ý ã ç ç á Õ Ã ± ¢ › Ç+×ØÃªŠV ¶ Ö _°ÇqûÒq:‹ýÇEª«Åºƒ•u6`«Z¤¦}â⮈µ…S´ÄåÚ©gF=Ga‡ ¹ ô 8 … Ø 1 ŽñWÁ.ž…üuïkéiënòx 2DXl€”§»Îáô1G_w‘®ÌïE{¼ fÕ[üÄÁó V ó Ü Ñ ï !  È Z 7 ¸ Dj³2 _ ¦  Å ] `yâBÚ{ÿÇþ|ýwü’ûüû™û¶üü3üû·ûîüXüåývýÿþxþäÿDÿÿë>Föq×V3: ùCÀ^Ö§| 9 » g @ # õ áa ä § w ö : Ð l ‚ ° , … Å ù # C ] r „ ’ £ ¢ ™ … a 6   ¥;†ˆ~g@ — 2 Ç cËž³sŒ—Â.¼ƒ§ÉãìvÒxñ’}¤ñ_mìŠNëéß k]ò—çŒçt/  (Q † Ä \ ²  oÔ=©Šÿuîhäbâcæjðw!3FZnƒ—¬ÀÔèý(>Vp‹§Æè:m©ñG®+Â{_wÞ `  ó    H ® < t ê ˆ4Å,Å ü N Ñ © œ ’ ºÑPçuó^þâý“ýGü–ü^ü’ý+ýŠý:ýüôýýJý þþ]þ´ÿÿNÿŒÿ½ÿÞ%€íA®_ùr¶$°SÄŠOä * Í ø È z  f >   è _ ª   ½ ÷ R ±  F ~ ® × ú  3 I [ g m j \ ; ù ß 3 – ÿE`cYD# ø ¼ x h)UŽ®œS»öG·hžÓÒ—«Ãž¬ó âÿ¶ig+Í ›%9®Û*(èÇÀÍë P ’ Ý 0 Š ê Mµ!vìeß[ÙYÚ]ágîv"4H\q…›°ÅÚð3Lfž¾ß._—Ù(†ø‚)ôë € ð ­ ² ¢ º ñ % _Íoürª — e _ ? 7µ|!¡è&ÿHþRýÞýâýÝýáþGþhþSýÏýÍýºý¸ýÜþþVþ•þÒÿ ÿBÿvÿ°ÿô?¢À=öÐr¥Mÿ·q¬ 9 ç ° l  | Ô û  x ³  1 U ä ½ Ð  N – Ù  H v ¡ Ç è   2 @ H G 9 + ? w Æ4OZ\YVZs_Md„<¸²ðaœÎ÷!\^»(Ä/ÜÀÎ]3…Ln;÷ÍsÝ;P›#Ë•zw‰ª Ú  ] ¬  ` à *•uê`ÙTÐNÎOÒVÜcìu"5I^sˆž´Êà÷&?Zv“³Ôù!P„Á `ÇCØfjš  ]  Ñ [ ë n Œ ¸ ÚŠÙ—gÁtvn â À ï öË“õ"BÒÿ÷ÿ\ÿ§ÿ±ÿ¨ÿrÿ5þþþ:þ4þþ!þ<þ`þ†þ­þÖÿÿ6ÿuÿ»<L7Œ‡Mü¦R´c § B á    c ¸ Ë K È J H Ç ’ “ » ÷ ; } ¸ î ! O { ¤ È è   + > S q › Ì ý&BT`jv‹°kQ‡Î)ã$ÝQŒ¤Ÿ‰wtÙ ù˜"èæN—ИèGy¶.šse…ô…¬f;(+@g › Ü & y Ô 5 œ tåZÑJÅBÁAÂEÉO×_ét#6K`vŒ¢¹Ðçþ1Lh†¥Çì?qªí;˜Œ-íÒà  w ø ‘ å ( Â?›YG¼Ä6¿oeð–% #  Mø‡Î5‘S ê±>Øÿ¼þõþ¸þ§þ•þzþlþoþxþ…þ’þ¥þÄþôÿ7ÿ‰ÿÞ&H]Ï”U ºf½c˜ ( µ >  A Ç   / ‚ /  ì æ o = @ h ¨ î / i ž Ñ  4 c Ž µ Ö ó  5 j ¬ ð'IZcku‚—·ò$r ÝÛ^3l©€®ÞÒ–&¸‡©>öä AíŠz‡J`À¾[˰z4þÝÒÛö" Z Ÿ î E ¤ sáRÇ>·3±0±3¶:ÀHÑ[æs$8Lby¦½Õí ;Xv–·Ü.]“ÐlÐGÕI:S “ ÷ ` §#rÒ†‘y?¡1.„ÀÕ =s Í”– n û š CèiíÞ|ÎÀ .ÿ›ÿmÿ:ÿþÞþÁþ®þ þþþrþ{þ¢þïÿ[ÿÐ<–öqÊ„6âŒ3ÕqŠ „ þ t æ [ × Ñ c 6 ¡ Î ñ D ê Ç Õ  _ ² ñ # P ƒ ¸ î # W ‡ ° Ñ ò  p å[¤°¡‘”¤¼Ý .X8ë£p tJ\6Â:¼–N}º²Ísˆ3¾æé¥Î®yÎvùÄ™|Š« Û  b µ  s Ü J»0§!œ $©/·@ËVãq%9Nd|’ªÂÛô)Fd„¦ÊñH{µ÷Dž†Í¢ŸÆ  Œ ”¹© æ3fØí᠃Ȕü2”:6ŸB† Ÿ  ä H 9š†;òÇÚ#ÿÓÿ‰ÿOÿ þúþØþ¯þiþ5þþ#þ€ÿÿÞwùs÷‰*Ñy Äcü‹ƒì P ¼ * † Ø  ÿ Ä Œ s : á ~ G 4 N œ * ‘ Ò Ù ÿ 2 k ¦ ã \ ” Ç ì ' ~Ch<é÷¿Óì"÷€ ­s¤S h÷ÒíÏ<fƒ˜ŒšÍ-a¤ qÝZ)y’JÑ<ZñÖ›d<'(;` ” Ö $ | Û B ® ” ‡ƒ† œ$­8ÄQào&;Pg~–®Çàû3Qq’¶Ü2c™×oÎ>Ã_ø 6 ž 1 ÝrD˜$6y[ýÄ×%X¶b3"ÿ³V  u : Ž ‡ [¸jïaÃ¥öwÿÉÿˆÿRÿ#þìþ•þ ý÷ýÝþÿ!×sù|™4Òq¥3´&‡Ö  R · ÿ  ( + 6 ð Kì¹–ˆ û ª • z | ¢ Ù  [ Ÿ è 4 … × ; } üÎê:‹îåõ5NfMå––œÄ¹© SÃÏê>¿ƒ¹qãbÅ÷»SÔå[*@­á°çKIÊZæÒÕì N • ç B ¦  €õnégçhìq÷~Ž£0½LÜn'<Ri™³Ìæ<[} ÆîI|·øCšþsþ¡dK]    Ñ‹¿dbæ,®÷Æ;E?iŠÑ`3VÿÕ;ƒ b ¶ À Ý â Q°Ù(‡Rg° ­Mÿùÿ±ÿwÿUÿþÅþ—þ~þ³ÿ–Œk ‘ ¦<Ôh÷{ïOšÎèàà    â ‡¿;é×¹ñ¿ š ï 7 y À S §  | õ m òb:ßý˜78l¢ÆÚûSFüмG/ò(Íf¯»è!©jÐ9¸3Ÿ“…°£n^X—ô~öU¶ Æ’~„ž Ì S © q ß RËGÅFÉMÔ[ämö ™'·GÙl(=Tkƒœ¶Ðë%Deˆ­Õÿ-_–ÓhÃ,¦7à©—² ÿ ‡ I"^rNê•}d ¨,BI3¤¬ÜQéî êÚ ã € É t M‘$ÿcÉHÙsÿ¾ÿ”ÿ©ÿAÿlÿÁ,˜ƒ:Ë=ª%µEÓZÓ;ŒÃÛÏŽ2!ø¸$l ð/¨kN6 ´ˆª # t Á  c ³ G Ô q ä ; Óy3×—qADBƒà?‚¢;o!BÃWZ›‘Zmbuö¬Ø:’ütûDLð‰b%¶]…åxî¸ÞuÖs=*3Q ƒ Ä  m Ñ < ® %¡ ¢&«2»EÐ\çs°BÖj(>Um†ŸºÔð ,Mo”ºä@t®ï8‹êXØmêÞþ S á «jŒ0‡ÔÊÊw³—O¾ÅÌ(Çž(GÏê^4 ; ã $ d UÀ¦x¦Óqåo„ÿëÿäÿsÿÿW«ß‡¿?¥úQµ+­7ÃLÌ=šÝ  ßˆÕ WÔ–ÞǺ•°1Ûzæ J ¨  Z ª î > E v À ?|&×^)ZÓp Él«¼¨Ëâ }ÄjÇ]u3)s:씣ìR½]­lzÇ_7ß‘Ì_«“õnáÓá ; € Ó 2 ™  ~øwú~£/¼JØeô…©=Òi)?Wo‰¢½Ùõ3UyŸÇò R‰Å V­‚ T& B ™ * òü…3×séŒ9ߺ¥Þf 8ñ“îÔ5 ½ ½ É {Æ]W‰Ä‚«KîzÿˆþJþÇć– `‘¿óJº9ÁJÐL· E ] O »0h²g…’è8Ëx[W[m úrîfÕ ? £  Z ³  “ â ù b ‡ = € ±\ÑJ"!%ÿ¸Kü¬ÆÓ¤´ŠIžï¦a¬L 5ÖÒ«¥g€7MÑ£h{éVˆkÎWé¡~yŽ ¸ ó = • ÷ c Õ NÌNÔ[åpüŠ©9ÈXèz¢8Ïg*@Xq‹¥ÁÝú:]‚ªÓ0dœÜ#sÍ4ª2Ї\V { Ó c,*7P§+ÍfY>ÿt¨šÀ®o€Ý§£àî2r5Ð @ T m F âê4i¬ ž<òlÿéþxþ¯ÉÎçHKÕEÅNØ^Ù B “ Ä Ò ¹ x x´üN„Ó, úÙèþ,^© |òhÛ H ­  {  # 1 : õ b × D “ í p4»m÷ ìÊå‡|Ë HS,A®9åvNà|àá–nø3›Çb3€Ùlç”R&: k ¬ ü W ¾ - £  &®9ÅRár•'¸JÜp›3Ëe*AZs¨ÅáÿAe‹´ß ?u¯ñ;êUÎZûµˆ ¬  ‹J1³µsËûðzRº¨K7æFD0Û,I ` • Þ n @ ¿Ê0fô·|Jiÿ-ÿß3?¿ÝK¬òSÊOÜjô s Þ . \ b @ õ ƒê%Îcé/SQ1^žÀÏäS±}ñ ] Á 2 ‰ Ï Ö m ‹ ª ð 9 € ß r R”5Q1”FqªéY[Vu‡~fGøœß(¤ uÛÀÎà6òhkÜ.-ºª¾Ê¹öÖ·¦©¾ æ  f »  … ø rñuþ‰¥5ÇYí¨<Ðfü”-Èc+B[u«Èå%Hm”½éL„ÁQ¦sï~!Ý·² Ô # ¤V3(ÊCÅNËÇÕÃ%šÝ€S¾y¥KÔT¢" Ð ÿ & MÅrìe»¨Í‰¸ÙGÿÒÿòŸR†lôpàPÅHÕhþ  â   ä  yÀèºIY½üôX¤“’³{ûR¦%¢  x Ð  n ’ M ! ! % 7 ^ ° H > ©NéTÁ¶U¢«ÙûÎSñtŸÅzÕ%zâ`sÒ´°­—M ®°Ûw±YÙS$!(=` ’ Ò ! { ß N Å BÄL×eõ†¬A×m™.Ä[ô(Äb,C\w’®Ëé +OtœÆô$Y’Ñe¼Ž žDÛÕ ô = ²X2DqwF=iægxå- Ï”­Õ>"¡˜›<Øh´ , ± ª ‰/s›KhQÏÚs+ÿŸÿíñ·^G]¸&«4ÃWò 0 Ê R µ å Þ ¤ D Å " UÕÅÉÝ® ¡ÐCc•“pkúLÔ\Ó 8 ‰ Í ÿ  Ý £ u D "  K Ó Ù T ÔšàlH©ýTòñöàú‹+é]µˆ³4&†ÓÌpë e±ÒV蟂çðqx†–¯Ó > ‡ Ü < ¥  “ ™#±AÔgü“*ÂZò‰ ¸Që‡#Á`,D^x”±Îí0Tz£Îý/dŸß'wÐ5¦'ºa ùò N ºS&L¨Y[M|þ·ñ‹p2lrV¦êiÒõÜÑæÕ×Qz ´ #  ~U!ÎV7ßž¨Àÿã)ìÏx dRÓ§<Õ u  Î † 3 ¶ í Ò €  Š ê * OnáYk`”á4ç°œÞeªŽ"   T „ ’ y ;øµqýg H ß ·¸ž¸nðF¬NVÔó=8ÏfüÖSŸò¢T´°vü`.ßöÒãû<l § ì = ˜ ý l ä aånüŒ´Jáy­Gáz­G〾_-E_z–³Ñð4Y€ªÖ8oªì6‡âH¼>Òz9   Y »H \)èOƒÝv—Z1ý’4w{Ù˜ù”›ó{®¤c þ ŽØ¼Ï ) @ÔZ¿+"Go¡ ¸¬AtÊŠdõ ² K ï   b : 8D ó b å c Ï  E .p«6Í®+J÷€£“Õc¸W÷ê 5 Y N ˜"ñ±œ× ~ œ Î ­†1~<Ç·'°ÌkÏOŸŒ»hæ­¾Á2‘ç6\Ü£ œ3ÂöÕìð}tUjzžÎ M œ ô U À 4 ° 1¸DÕhý”,Æaü˜4Ðk¡>Ûz»].F`{—µÓó8^…¯Ü AyµøB•ñYÍQæŽL$  * ^ ·7åÆÃÏíIš´Ÿe”í"xkû“uêê×´¤³Q± ^ „ ¹ 6 — ¸å3xù†öÚòª‚¶îž(š " ¸ ^  à Ó úN–Ê4 » J Í 9 ‚ ¶ # » e ÞLz}9ŸõfW|à–>átæ 3 U =Ì\Ô<uŸà  é = Á.‹ÑJ ªëlðÓ˜6̧òZ·|q‘z'kŒ¼G6U™ñ!ëéü(b § ö L ¬  … þ } ¯DÜu«Hæ„"À]ù–4Ôt¸\.Ga|™¶Õö<bеâI¾IžýgÜ`ôœZ0 . \ ­#¿i5Ý`„ç|ª¼¯1Ð?ôȨ>4…nÊQ¿° »   u 0 I w UîU å½:·šº !†<L’Ýs« †  À y K V›ªPߊ9 ß q ù © S ‹  ~¢ \ÙJët6À*âƒÿ V € p í\*  b s Ç ä Û È ‰ ù q sqâI÷öMO:CñÅdKY)HOÄ2†^ûÑŠäD'ñâï\«D?Vy² ù H   ÿ f Õ L É LÔbõŠ"»Wó‘0Ðp¯Nì‹+ÌnµZ.Gb}š¸×ø?e޹èO‰ÅJ¡sèkÿ¦b6 # , U ž ›S+Ÿ7—î­aåÎÊ!É7ÝÛ2ÕœQ›Q ±   ‚ [ T 8æT¡ô;\ rìí*Äûœ(ÊB|¨  ` Ø l  Ó ¥ »-΋qR4ÂjE\ m + à T5ï­]üܱ½"3± 9 Ú í À Z > Œ  9 [ €  &Û 4 ½ H Ã Æ hÔ­òºG`šÕ¤¬ý+UtñO‡ó ¼  Ù—6z¸•¤´´p­ï< ‘ ì M µ # ˜  • ¨9Îfœ9Øwº]þŸ@à€"Åh ²Y.Hb~›¹ÙúAh‘½ìU‘ÌF¤|ðrªe5  $ E ‡ ët%ÿõJ©ñF­§°@i3»²çÕzTTÉsÞ i Ù ø ‚ c z  9ŠÓ7Æ!zÔ~TáÒþD¶mÕ 0 ¢  ¯ b ( 8î6]L>ë¸Ø í Gè/å8Ži>»0`H “  ] Ê 8 d ƒ ± 5  P f]ÒC¶ Û ù€{çõ¦*¡R8e¢Tëå+ú¬¾bLÏ qqaf“±I¹vYGh¢çˆf É , “ þ m â \ Ü bì|¨BÞ}½^¥Ií1Óv½b¯W.HcœºÚûCj”Àï#[—ÔX´ƒõuªb/   . h ÄEðÊÃĉ˫½_ ö¡BÅ$²y&Ùì€ÿ#U” P K S H y 1 \ µ ú ¥º¬…nD¿¢â¢Ã¯—Z*I I   5 æ © | _cibµÐªÓ:ÊZjTE*{ n D 8±iUdR!S‰½Ù¸ n  Š ù ` Ì M v   Þ ¬ F ¤ 8—Q*ÿI ­ çÕCTÂf(gÄnm}P@½“Ü=ç}eîY¶<·j¶×áÖg æ [ Ì = ° ' ¢ " § 0¾Q郾^¢Fë‘6Û€#Çk¶\¬V.Hc»Ûü El–Âò%^œÛ"‡Â…öu¥Y#  ý  B • ²~”¨“Ö1…_@Á€6F´‘uuÜL+¬ãXƒ© m b « ½¾‰ . § +4¢–Ãè¾¢) ,6]F—Ì}ª G  ï Ô ÇË ˆ9)AQø{?”©ŽÍu û  /”3_ØÄ ·ª„ J ø ” ¡  ž en‡ ò ã x   V "õÍ  N 5Ÿû·^ÚÃâiq›rà}ßjǸ]Ôá…]¯*7S8 ä t ö r ì f ä d é r ’(Â_ýž@ä‰.Õ}$Êp»a®Vÿ©T.Hc€¼Üý!Fn—Äó'_ß,wË „ópý›Lí à ì  ]Ëf. @óŠGSh†Ž(\y†&x_ÂÝr 0 ) Q q—$=]C Iîò-3ïvòš†‡Ä–ðþaÊ” p Z E 8 26L6u—¨rHÿ§è±Äuö Ï  í†#¼«Ÿ K ô • /  P Ü c û]l û l „ ð ( – h #   D Û }'¬ ¢ñÆoñ̇ÏÇ]ÓUê86GJ覴“ß<p¿TÎ ý á È y  œ  Ÿ £ ( ² ?Ðfœ;Ü#ÉoÀiºa¯Vþ§Pû¦S.Hc€ž½Ýþ"Go˜Äô'_œÞ%qÃíióŽ;üÑ ½ Á à  ÁƧ¤«YJ·7o¿Õ«’â·»*éfë^ z P ¨ Az®?ú|@óÙïÖ¡O÷¿·4îW•õRŠ‚ m o | ƒ ˜¯ÏPG¥Ùg½Î¸‹Gv/ñÿ‡M S  > æ " ‘  ª = Ð h  ž/„™d ” . ¸ % M Ô Ô 6  ¬ É:°8=² ,Cq}‰ PÌ*…H õ¨PØ0E3¿áù=ÆšU ï Æ ~ & ½ J Ò X Ý d î | ¢<Øv»`®V«U©Rû£LõŸJö£Q.Hc€Ÿ½Ýÿ"Ho™Åô']™Ú k¼vã]æ}&á± • ‘ ¦ Ø*¢Dú¶MAý^­ùÍŠb©ƒqåÕ®,œÖq ¾ Ó Ë¨6}Â2Ùžh/1=9ߪ!íåýœÜ8oÐ @ › ® æ9[„¸ûœ*ÊR×e3SÓd)£‚z*6 ë ¹ ü  í  w é e ç o  »tn¯Y ú w 5 J % ˜ ê 0 \ ¥  ñC½÷½È÷Ã3x ©!`žþ?"–Ýö‰ºmξÁI`‰ž4a © K ã t  Š  ) ¶ HÝv°QõšAé“>é–Bî™Cî—Aì˜Dò P.Hc€Ÿ½Ýÿ"Ho˜Äó%[•Ôc³ lØPÕi ÃŒ i \ g Œ Î0µ_±î|Ôû#WÉàÚAÃ8`È gÈ0»\ s ­ "]G“U+ ï§*¯Ó‹Á+ª{•zÔ * ‚  ”ÝãùE[OËÄ[³Y:Hây í&ø@Æ W Ð  ó X ·  ‡$#ÅåœÄ Ð ¬ v ƒ é J º œ <ŒÇÀƒ9š‹Ø¡¸jýht]ã;è§Š@ÿ¾:ÍS¸Ð —  § 1 » F Ò _ î € ®Iè‰,Òz#Íy&Ó/܈5à‹7ã>íN.Hc€ž½Ýÿ"Gn˜Äò#X‘ÎZª`Ë@ÃSò£e 9 # $ < n½*¨)æS‚27F€€ñ%]û†§þˤqMØ@qZa Æ ¥RñÞHmûx×H]ÙâmŠ $ ¼ nÛÞ»°±½Èȸ¤qu~ì Òl†|„ñ=±d í ¬ m   : ƒ Ø 4 ” äRÓÄö:‰ é  @ } C ­   f P ç¸¬-hG¿2ªÇr~÷ ãcžUr))Í7/®Ÿ—p{ýÝ% { í k ð x  ‘ " ´ Jã~¾b°Z²_½mËy&Ó€-Ú‰8éšM.Hc€ž½Ýþ!Fn—Âð!UÉ R¡÷U¼/¯;Õ;  é Þ ê M©$̰°÷µ‹,éfSÆb*Ýy•c¢œ› „Í ‹ ¿Ì ½ý,?~©êåÒŸ£Üø6|¼  yBÕuPEGAl~ŸlhÌÿDОÿUR× ì [   J ˆ Ò ]Iþ?±{Íò í A  » ì í û v¥_DO<ÿBbŸÂéðá0ºÌ3ʲŽoABjK^ÏõÕ ý I ± ) ¬ 4 Á R å { ±Oñ•;äŽ:è–Fö§X ¹iÇu#Ò2ä—K.Hc€ž½Üý El•ÁîR‰ÄJ—ìH­˜!¶ZÕ ¬ — ˜ ¯ á0¨YaWØs³&íc™I: ~JD³¬y5çðZ' ° W RéæHÎm91;Up¤„ ôkø < Ù À € v–ÍðÔ3èÉÀÄØ©Ãq”›Ö!Ãû¿Äk ø´, þ õ'_­î6·S)RxÅa€ ’ A W » _ f§««\.ng•ú5ýÄÊÄÈÓï Ž$€ct3ç»ÛØÊ^Vm ¤ û f à d ï ~  ¨ Bß~ ÅlÁmË{-ß’E÷©Z ºjÉz,à”J.Hc€ž¼ÛüDk”¾ëN…¿ýBà: –4â  o Q G S y¾0àå »æÄL ùäé^òðšÞ^¾’屩)ÒYÿ‚  ï S0kârqncœAÀ_ ¡ … c  ¹ Ä!D?ª Ðl9 Y£‰ƒüKÆIݪ×(ºé5§1濯—©×2cK•wé§ Ë  ² õ Í?šõ™Tó¤Þ•í8Y!â·¨¼÷öú.üYjÖŠ QL+>q È , ˜  ‘  § ; Ñ l ©LòšDðLý®aÈ}1å˜Ký®_Ás'Û‘H.Hc€»ÚûCi‘»èJ¹ö9ƒÓ+‹ôhèt ´k 2 ÷ ù Qºb`nŸ›Qrã898ذ‹Ø¡ÊI¡œ&ŒÅ G ü<<]½}–ÌîÐ^Œq&\  É ©8Äß<AEÕ]2îÍÁï^J ðÖÖÚ9‹ÜúBš²sIÛ£Mñ§‘=´ôI¸ÚF| â ©‰DÄa×1¹p?Ì<Ÿfã…RXhvj®W‘<ÏðèÍDé Õ m  ¨ , ² < Ê ^ ö ‘ /ÐtÃnÊz,Þ’Gü²hÓˆ<ï¢T¸l!׎G.HcœºÙúAgޏäEz²î0wÆyßOÊQå†6ö Æ © ¢ µ èFàÂßÿ-25›Ì»›éºÎ°cd‹‘ÁÑ ‘ Y |›—ªÒì§ï®)ò&.xÔ ú L —Íl7ë&be§_š)Ñ(§.Ãm¸—^»®öÝúiëü&iÏ^Ö¡Â'àšc~å%ìë²EDóMO×z½a žª<¥gy­ ɦ×úæh.l¤‡©×X Ó Ï µ „ ) ¿ Q ä z  ° Oò—?é•Dó¥W Àv-äT Áx-â–Jü°eÓŒE.Hb~›¹Øø>d‹µà?s«æ%k· fÉ5¬.¼Wº ‚ ] N W €ÒW£¬ÃíMm«å‰  SùÛ΢-6hÞ] ® z ã …Î‘Ÿ>†G»A‚té† ²  c ÞýÈe–EhQ‡áp#·Ë슔ÍI,>Ø[.ƒà®¶ÖègëH&>©N ,‰›!%Ò»ïNT0½ýû4Æ¥–k®Ëç•ñ%„',z Ó¾úç00>'.´ RWÄ 1 — G · W ò ) È j µ_ ¸hÌ€5ì£[͇@ø°gÔŠ?ó¨_ωD.Gb}š·Öö<aˆ°Û 9l£Ý_©úR² ”)Ì~ ?  û û ]În7 œ!Z€±éK³šù Ý ÕÕ€H%ÈFIJý9 " ˜ z Ó ^ E r ™ R à –fS # E M ÓŠ©C•!Ô¥*·AÁ<¬D4ÞF¸ \©+M¨¼º&Rt‰Þ`ý¨N\Æšpd”ÑïÎo.ú†Z•%SEŒÿžP5|ÓÙJXbýÙwQ‘éÍÆˆÿß!¤€Ï[œÀm ù d  © P ó • 7 Ù ~ %Îy'Ö‡;ï¥[̆@û¶r,æŸWÇ~4ê¡XˆC.Ga|˜¶Ôô9^„¬Ö2dšÓQ™è=šÿmækû˜Cþ Ê ª ¡ µ êFËt,ÊDõ+Mi€ƒC Î!7!1 Cýµ‹{‡­É{»ê§FÒ9 —  ë ï â Æ A ‡ n  i ¤a<g¬ž UIïƒïXëNÝŒ­Úñ›b °ú½·†¢Ö8À_ž/Í–s€Ð&`v¼j`šçRÁžXðÀ°¯Ë › Iز:úU3F=. ‰^¸Ù¯ŽaG2m à Ù " ° K ï ” : â Š 4àŽ>ð£XÆ~8ò®j&ã \ÓHºr*á™R Ç„A.F`{—´Òò6Z§Ðü+\‘ÉD‰Ö(‚äNÃBÍd ¾ ƒ [ I R yÄ2Äqº§W7J‚ÇÝ «!_!‰!U ¹z òéÆÿÁ0Üäl@U~45´( – ¶ éx梙׌w¦§Àðw÷gÍ'‚çª  Vˆ´¬¬;uÿ(ÛŠ¤}ºm]üIÐH‚Õ%z_VýBÕèÏxõ¡÷õ,¦ëïXâo <¥t›Ø; ¨ÇÄÁ ž K ù [ È N é Ž 6 á Ž <ëœO¹p)âXÒN ÌŠGÁ|8ó­f Ø’LÄ@-F_z–²Ðï2Vz¡Êö#T‡¾ø6zÃjÉ/Ÿ 1Ñ < ó ñ F¢"ÁuSl=I¤ê 0!2!­!®!!#ß”REZwW:Ë [r0.Ë€yOl£á¸ OÙõ}Ët×{5)Õ½ã,„Ù%l¨û6Oµ6ieÈÉcÀ$ßQꎓ²)²UÛÄÌ÷T¼‚ÛU»ô ÏÿÃ{§¯-› ŠÁœ])vºÞ0Ç®¤Õ£²|xøÍ45º÷;n » F  û ³ G ß ‚ + Ù ‰ ;î£YɃ>ú·u3ò²r3ó´s2ñ¯l)å [ЊFÀ?-E^y”°Îì .QuœÄîK}²ë(i°þR­|òrÿ˜@÷ À ’   ̈Ò×ëÙþ;~ (!!ª!Ø!—! Tö£‘¨Ú+ÉÛNù¼…™’p^€¦½¾'Îÿ…c™±¢vñ–žÅs-ïãú%W‘½ûÁÆX–¾ñÊ{ãz‘ÌHïö„ÔGÛŒN9Bh{gÿ$áDç8/Š(˜v;Sß&âqÔmWƒç”å²nEœš¾bxýBn¬UtEÂ0 ¼ Ñ E > » g  Ç { 2é¢\Ô‘O ÍMÑ“UÚœ]Þ[×”P ǃ?ý¼|>,D]w’®Ëé *Lp•½çAr§ÞXè9‘ñXÊFÍ`³ u J 5 8 X–õy,7 ˜ÄmË Õ!k!ã!‘ í p-àÔð.žPK31´²b5rþíÎáV2NªTþ(Öûï˜CØuãÈÌäe~'Ø;ø”ÝÎÚŽÑŸiÊñjìYöµŒlÁ ävõúߤ Q\ÅJ9 Æ~'Ä’thh‰ÓÝÏ]ÀvO§ à)'¿þÃ,ï^…ˆ^ §  × ¤ r 1 ì ¦ b Û™XטYÝ c'ë°t9þÂ…H ËŒK ɈE¾{9ø¸z<,C\v‘¬Éæ%Gj¶ß 7gšÑ G‰Ò uÑ5¢œ)Åp * ÷ Ù Ò ægÜ~[^-ÝoÜ* =!!U!R!$ [2 .pÍ5šI¯nCØÄ›Ða`óœ”g¸à‚ÙïoJÔPÌIÔŠmwª÷*õ0žƒ¥Ç¾¿¼Î¤ä )ÍjÛZιÞ6Îý-JÍ?FkÎI*<Æa2zÓök-é*žhG¼#0A e ˆÆ4°{ËÀ4ë¬ä!  í  y D  ä ­ t 9ý†JÓ˜]#è®u;ÉWä©n3ö¹z;ü¼{:ø¶t3óµw;+B[tŽªÆã!Bdˆ®Ö-\ŽÃû6v¼Y²{íkó‰-à ¦  n v šÜBÕˆd;˜i}‘ 8 Ò ë — 58i«wÿ—@á®°¼ôµF¸Ð²Çs ð7îIÆç*ËÊNÌ7]1ýHõ‡¥¥a|½Å¯\½†e˜>NeÈI÷ÐסptÞÿdBÌ-šÌ§qšõDbÿÓJ,ûÍ 'ô«ý#Øíާ€þ¿Rw@= ¸    5  Æ Ž ^ 0 Ïœg2ýÇ‘[$î·KÞ§q:Ë‘Xâ¦i,î¯o/ï®m-ï±u:*AYrŒ§Ãàý<]¦Î÷"P´ë%b¥î=“ïSÁ:½Më˜ U &  Tª+ßÊß8‚½áG±Ù ëaL6wªêC¾`>;²J¢¡Ç9Hà•V‹³Ä:sT—DãŠSAy;°sxáM˜,n‹—öï“+‹yÂ6¿;X¥*Û¸Ä×k,$?Š ÇDÇ8LeÕH¦¥—vºV"* »3Ç|«ŒcŠÞfšÔwë>ö å Q ä K x {  š L ⺒i=ⲂPí»ˆU"Sè²zBΔXß¡c$å¥f(ê®s9*@XpŠ¥ÀÜù7WzžÅíDt¥ÛOÕ!tÍ-– ˆ©O  Í © › ¦ Ì÷Ø£ÌÄÛ_”]r2¦Ï2„¹Ä¨tý­n ‰h„†X¹ ·vêkžŸi÷²²ŽÿÂÙ83Üã(‚Þ­ÿœSêkÚÇAótþ®„†»<äŠj³M Ã'xöÃp)cE)¯¢KÓ“‰Q-±u÷†q×víNxM³ìå ¾ Ä Š A Î è “ ô RÛšoL+ä½”j?帉Z+ûÊ™h5Ιc,ô»‚H Ñ”WÜ_"æ«q8)?Vnˆ¢½Øõ1Qs–¼ã 8f—Ê;y¼TªkÚS×h¶ u H . - F|×[غï1[RÄXnq&Se€Ã:îê(pPcî˜a>+*!Ìì^÷pùFË\¸zâøÞ™‘)é§„:UÆÀk˘VK•!,ZÅAÎs7 7~æ*ü¤7- ëJf§7å5SáˆXšÂ<¯  ;ÝŠSP‰õXŠYþÏ  b Í Ö * ´  ¯ên,æÊ®nJ&ÿ×®…Z.Õ§yIç´Là¨p7ýÇLÓ•Yâ¨o7(>Tl…Ÿ¹Ôð +Kl޳Ù,X‡¹ï'c£é5ˆáA«'Àg  æ à µ À ç.˜#Îfó;E^zÇì…æ ßÎÏùbæ®KŸÌ^ÍuÃìúÕºµØ†ÖÓˆŒ¸Ll·A.”KB ˜€ªrÓ¦2¨àÚ¥5×–„¦î$!#¿×c£;LZµp@àŒ%„g«Iõ²ƒq„Íeæám¼1 X ” º B … JÛaüÄ¡ˆqY?#äŸzT-Û±†Y,ýÍœj6Ì–_'îµ{@ÊŽRÞ¥m6'<Sjƒœ¶Ðì%Dd†©ÎõJx©ÜMŠÍe»|ëdèyÇ † X > ; R†ÙGÃHÙ)fƒÁ]T¹×Òý~Àq ¶Íej*è# ¾‰dEI5áST‰é&_ó%-`õ(4û:؃ÔSÚÉâ øu/Â4¬— —vý›µ ƒ®æÿ#é“lF 8ÖÈS× ¼é÷•R‚*f4ä£u_dÎwd{Â’hÙr ¹ ¶ ‰ gRX‰`E0 ôܦ‰iH&Ý·f;ⳄS í¹„Nà§n5ûÁ†KÙ¢k5&;Qh€™³Íç=\}ŸÃé<i˜Éþ6q²÷C•îN·+©3Êq & î È ¸ À áuÚ`û`pÎ]–H7¤ò¯ßí$’"ÆmÜÂ¥¤ÔƒÝuSÝ¢Dø<b¥ $uXNrŸˆÁrÈAãÞëÇOߪb_—“UÌ}jýÃTÊûCzÁduÂÓšjœñä5`ƒ·xD½ó4+¦Ç­tD'6xåBþ1ÆÆ ˆhð É Â„•jY9ïßÐÁ¯›…lR7úÙ·“nFóÇšk< Ù¦r=Ñšb*ñ¸~E Õži4&:Pf~–°Éãý6Tt•¸Ý.Y‡·êY–Ù!oÄ „òkî~È … T 6 / Ak¯ …,‰Æ|€Ÿ£9݈“T¡¡FçŠ2ò&Sï™r÷‡ØÖ寫‡ª³ \×¶–|^+ØO´Wøwì©NþÁÌ'¼ïÔÈ…Ÿ¿¯²×;%¿ìâ‹È¯‹s­Ah±ã‡¬–©‘¢qQ )¨!F,ÿÝÉÈÕBúÕ@Doó¢EÍB Ý p@ɳÁ¸¬ ”‰}n^K6íѳ“qM(×­S%õÄ’`,øÂŒUç¯v>Лg3%9Nd{“¬ÅÞø/Lk‹­Ñ÷Iu¤Õ @{ºÿJ›óRº-©2Çk  á · ¢ ¤ ¿óA³+’Û3n™¶»ŽuýÇâ*°\—> RÏ\T³ª²RåVS~RIS̹  ¬ 6/÷Ä(:Âã)™YUü——?ÌþP/à"(üæºþ© ¡Ï‹y5(9,Üå{Z_® ª é’ˆÂЭŠoc`eÙÔˆnXyîV[ H °Qˆï1Q`a]VOG>2%ðÚêŽpP. 伓h<à°Nè´Iݧo8̘e2$8Lbx¨ÀÙò (Db¢Åê9d‘Àò'`œÞ%rÆ!ƒðfçt· p :  <}ÕDâL†¤«›n²`±„Ï·lóŒ6_Û§gµšÜÓjÔëUeÈ&å K!3 ²„Seö•I¢sž_ª¹—PDâ”j9¿/;‡#«¤‹Îè%¤ ‹Sµ¦Ëµ^7y¹v¦ 6 4 lÜx^:üòÎ÷ž>¢×'¢t ‹ Á ø‹JÜÜÿ ûðãÔñœ…kN0ìÈ¢zP%ùÌm= Ù¦r> Ôžh1üÈ•c1#6J_uŒ£»Ôí!<Yw—¹Ý)R}«ÛE~½JšðM´$ž#´T  À ‘ w s Šºv •ùºf³ãÞ§¤@à˜ÜdÕ^A²\†§yÃñ²Œ‹Òxsî!³ £![!} Tj>‰zý1èhð'q+™V=îÀÌqÊõ¢KöK°I1tÑ?#r3Uu‚ÍGnS E D ¼bå÷Ф€ro† ª¤NLí"â< ö Fý ÷ÀËÒÕÖÕÓÎÇ¿µ¨šŠwaI.ñЭˆa9ä·Š[,ûʘf2ÿÊ–`+÷Ä’a0"5H]rˆ ·Ïç4PmŒ­ÐôAj–Åö*aœÝ#nÀyâUÓ\ò– I æ Ó Ù ù6“ –ò¸9²ã,V…ùU2…-ûéïQÅ« +ÁÛô þÒÐÔ#~ã €!!´" Ò"V­>~-@ŸW K^te³`DˆZ.¨~5S~Ÿƒ¾«à!_Š¦Ã –|Sõß%šz` E É ö q!™«y* ø Ö Å U ¾>›Ö…nA < \ '¡€°‹†‰–›žŸŸœ˜‘‰sdS?(òÔ´’nI"ùÏ£wI뻊Y'ôÁY%òÀ_/!3FZp…›²Éáù,Gc¡Âå /W®ÝD|¹ûC‘å?¢…’,Ô W 6 + 9` ÷T¿Ó4¼x"qã{ïˆI0õ×ÉËÙðõKÆš\¶ÊÞ _xŽ °!!p!¥!8þ< Z ’km›š#ê¯K7R™ÉæN}bI.…ë™üÒwŠ& ;|¼ø%@2ˆ~†—ÙVs}t o – % R `3œ  þ ˜ f C ô  0G;”¤¬< Š †ÞR‰¶nONRX_ejmonlgaYNA1ïÔ·˜wU1 ãºd7 Ü­}Mê·…Rí¼Œ]. 2DXm‚—­ÄÛò $>Yv•´ÖùDl—Äô']–Õb±dÉ8±5Åc  Ì œ { Š­á!Bs°=¼ZÔÉK¶äááÖÊ´­¨¦£…lÜ¢É_²ÞÕMÑY! !Á!à ¶Õ§>Dîµ1.8ƒÑ ¨¾ ú a7¾'S²éÏÎö[ Ì Ï‘ þ ` $ D Û$pÉÁ îòõ»ð% Ç ³ á ì Y¨ ç L Ù ª ± © ® œy "! ý × ¹õû©^7 ",4:?BCC@<5+þéÑ·›}^=õΦ|Q%ùÌžp@à®}K踉[-0BUi~“¨¾Õì5Okˆ§Çè 0W€«Ù =t®î4~Ï'†î_Úaô• F  Ú Á º ÃÜ÷f‡Jö±o2Iø­¤¬Â¨£™Œ}rfäå,‚7¤±»Gˈ 8"""Ê!iä'`WÀp!«rIJß² þ q Ì Æ E s¿9§’dX z Å ­ € D à ç Q à M ’ Æ3¦ Æ$ à ç  ~ < m î ù í " & Z ² ² • á H Ý ½ ç  ' œ ZM Û ˜ Í ùX†l…±ÃÔâïû þðßË´›€cE%ß¹’i?é½b4Ö¥uDã´†Y,/@Sfz¤¹Ïåü,E`|™¸ØúBi“¾íR‰ÅM™ëD¥‚ÿ‰ v 9  ó ç éó‹xTܳª½´‰Œˆ®§’z[CVÎá#'9U.ûLS!N"Ž"ƒ! &vÊß@íbE E å ´  · . Ù Õ ÞøPq†tÝ ”   ï a ç X Q  % Ò ö  I § ž … · z 3ñMÌ ì ~\V h § ñ h ð — * Á — ð [ )jÓ— «   -é1†e U}˜®ÀÏÛæîôùûûøóêßÑÁ®˜€fJ, ìɤ~V-Ù®‚U(úÌœm= Þ°ƒW+->PcvŠŸ´ÉÞô #;UpŒ©Èè .Sz¤Ðÿ0dœÚc±^Á,¡ ¬Cé ž a 5  4uäÚ€IdNž†‚k‘Óµ¡‚Cê‰vÏÇ7Qà ›!é" ·J.ßþy€Š’é“› ó " ± \ Õ q , z  Ü Èƒ¿· ­ Ò  A Uk¸3 § ¯ > ¥ Ô å Ü ó ù iüe¬¶>EíÕ Ä s ¥ ‰ O ˜ Ï V b W Å¡  m /ð$¯ë[·Bd”¦µÂËÓØÜÜÙÔÌÁ´¤‘}fM2öÖ´jCóÊŸtHï“e6Ù¬€U*,<N`s‡š¯Ã×ì1Jc~š¸×÷<b‰³à@u®ì/wÅuÙE»<Éb ½ S 4 "#A’×ýÝ x¢³ø:c¾žÁÚ:ÎOÔ™„iöiáõm}!!) mhÞäSDލ P Á Ú  k ž ª ¹ ì G À Z ˆÉô$ © Œ Ò n $哨äYŸ Ý t ƒ d É  Þ­NãQ©Jú<°7Î þ 1 K Èe # – ü z » Ñ © F ] °jI:/Yªå:Wo‚“¡¬´»¾¿¼·¯¥˜ˆvbL4þàÀŸ|W1 ãºf;下]/Ô¨}S) *:K]pƒ–©¼Ðåú'>Wp‹§Åä&Jo—ÁîO„½ü?ˆ×,ˆíZÑSàz ! Õ ™ k N CT‚µÄÏÃÏ‘ÿ=2›}›²à»`®—“+@Ä×¾T]ðŠÚPÁ²m8‘úeôuŒ; i € p " š Û  ‚ , " / Y ” ï {   º à ð ? µ .b„9n2ú ´ s ¡ ‘ *µRÜ Lº=@ž‰ÇÛ$6AÚOy Á    0ØtþXA7hšËõ6Ncu„™Ÿ¢£ ›”Š}n\I3çÊ«ŠhDúÓ«‚X.Ù®‚U(ûϤzQ( )8I[m‘¤¶ÊÞó3Jc|—´Ñð2U{£Íú)ZÊ M–å:—üjâdñ‹ 2 ç ¬ ‚ j i~˜¹ÇûâuúM#p†»ê˜ÃdR5»®û3×þǧÙíyã@ж4 Wïñm{yaôp ­ · ­ À  ¬ p _ d n i Í   — ©y£¦­±ø#uNæ  ý p O°3’ý®Ñí  ”ÿkÖÑ=€¤ßì þèŸ-Q<é}ã?â!Cf¸Ýþ3H[jv…ˆˆ†zpcUD0ëд–vU2éÜsK"ùϤyM!õÊ wO' '7GXizŒž°ÃÖêþ(>Un‡¢¾Üú<_…­×2d™ÔW ïE¢uíoü— > õ ½ — … †•¨àEatœ >Rq•¸ç”å:?Ò=` Úî­LLG8³ÍÚ`Òêco^åÈ~]y  \ Šð®‚wd$g•z-ñ¡år¢))sx7q0²ª{z¡x?QÝ:†˜C»-s©¯¶œKÏâ¿÷*ÐŽõÀð>c‡ªËé2CR]floomh`WJ<+íÔºžbB üزe>íÄšpFïÅœtM& &5EUev‡˜ª¼Ïâõ 2H_x‘¬Çä#Dh´Þ 9j Û^§õK¨ zòt F ÿ É ¦ — —®á7Ô}ÝA7àÕ:xpŽª-@¬m€‰Ÿ~ÍÙ놣hñ¸atùyÏæ†Ìˆdý… Ý c ‡ëlɘ¤(q„ˆn"èñZ–œ¾ŽZˆÔÉf¯ ­ˆ0ó;+-½Ù ‰(Õv«¤€FÅÐ,š|ðÛy šÀæ:]Ÿ½Ùò -;FNTWWTOH>2$í׿¥ŠmN/ëÇ£~X1 ⹑g>éÀ˜qK% %3BRaq’£µÇÙìÿ&;Qh€™´Ïì )Kn“ºã=n¤Þ`©÷L© {óuž I  Ð ° ¤ ®ÛFÝ%Ø3Z«•&T#Wgk]öY2Ü(pjÎ=àÔ p)3†›^ÈŸ†1Ù:Œ s ! ]:ñ7‹iéàba8©8>Ž˜*¯rŸˆ^ÝštЀBÜr4Tž \/4jsn¬îK­š3¿Ýž›Åì6Ww•°Êâ÷ &08=@@=80' ýë×Á©uY;üÚ·“oI$ýׯ‡_6 ä»”nI$ $1?N^m|Œ®¿Ñãõ.CYo‡ ºÕñ.Or–½å>o¥Þ_§õI¦ wïqÿ› G  Ò ¶ ¶ ×'êxŠõÇ ‚~4LÿÚ¤oÖữì÷Uºýk-ÃSBÊa­7ì[ß?®Fæsª ½ Ž W¿ƒÛÞDYW\€¹”|h(w”¤Ý3™iÇw²=0zÕ¡)æñ:«7›èQ´osz  Ø÷׺ÖÌÇÁúÁ­µÍî2Qo‹¥½Òæ÷#'*)&!öçÕÁ«”{aE( êɧ„`;ñË¥~V.Þ·kG# "/=KZiw‡—§·ÈÙëý"5J_u¥¿Ùõ1Qs—½å<m¢ÛZ¡îBžoæhö“ ? ý Ò ¿ È ë(À¿ œÏã1?ÍhÒ¤èéºw?ü›‚Ú5žwD‹3Ôp@a²lMüÑÅÛÚŸ º 8 ba" aôÿFÜD¢ôž¥¹ŸÖBŠÔyÏÿö–ÞÜÉw#žó"@zz"ÁÜh &E((¬š¢°½Óð.Kg™¯ÄÖæôÿ úîàÑ¿«–gM2øÙ¸—tQ- åÀštM'ÿزhE" !-:HVds‚ ¯ÀÐáò';Odz¨ÁÜ÷1Qr–»â 7g›ÓQ—ä7’õbØZè… 4 ö Î ½ ¼ ë+ý˜ Ä«ßáÎwè¬æø[ãŽzÎ_ÖÊeÎû–% ž§7éý·™g¾4á  » ékN9Q9zl©e½¤ƒA¡²2ÿvÿÐÿë 4d–ÁîÁƾ¡j%$,zÛ’¢ð_’¥¢Å?¸¶ŽBÅ…”Qû¾dj“¨¼Ôð )E_w¢µÆÕâìõúþÿþúõíäØÊ»©–kS9æÇ¨‡eC ýÙµkEøÒ­‰fC! +8ES`n|Š™¨·Ç×ç÷,?Sg|“ªÂÜ÷0No’¶Ü/_’ÉD‰Õ(äPÅGÖt $ è À ­ ¯ »ÔÌŽ¶ŽŽ®®€ ®¨Ù½žäSÏg½¥ïXeVmÓùï½s'Í®x v ¢ æ@ã -O¢£…¾ËY]-ÿ¯ÿðÿôÿŸÿ þåþïþøÿ ÿÿ6ÿXÿÌ*‘‡Wÿðÿ`ÿ’ÿü~c®Q[`X–×iÏêi>úå¹fK[„µÐì#=Ul•§·ÄÐÚâçêêéåߨ妔‚mW?& ñÔ¶—wV5ñͪ†b<òͨ…cA )5BO\iw„“ ¯¾ÎÜìü /BUi~“ªÂÚô+Ji‹®Òú$S„ºô3wÂmÎ9®/¾^  Ó ¨ Š ˜˜P³XNŠŒ|ñ~ªxm“eÌ‹w÷õ**s Þ Y q › Ç n/   ¾ ï l X p  ³ÑÌÌð=ÕÆÃók)ðÿ¤ÿlÿ<þØþkþýßýÌýÒýàýÚþþ]ÿÿ_ÿhÿ3þªþ+þþ²ÿ~)µnØÙÈöNo³èÉP0 ô»Æ÷5j‹©Çä3J_s†—¦³¾ÇÎÓÖÖÔÐʸ­ ‘€mXC,úßÂ¥‡gG'äŸ|X4ìǤ`? '3?KXdrŒ™§µÄÒáð 1CVi}’¨¿Öï %Ba£ÆíCs¨áb«üS´’¢Añ ³ † m e f+œtI$(GI ä\k£è(æ³®rÙï … ! Ô X ~ ¢ ¿ ! u © Ð ZFê %.Ó™«æÄÂÜÒÌñåjÿåÿrÿþ|þý~ýü¸ütüsü³ýýhý´þþeþlþ>ýÛýIýyýÑþ½ÿ[~„ļ §ÏÔ§[,ù¶±ù ¼Ju™ºØõ(=Rew‡•¢¬´»¿ÁÁ¿º´¬£˜‹|kXD/çͱ”vX9ùض•rO, åŸ~]=%0<GS_lx…’Ÿ­»ÈÖäó!1CUh{¤¹Ðè8Ut•·Ü0_“ÊHß5•ýqñÊ ‰ Z ; " ü “Vu½ãWì\a´*½Ýý—âœ= þ ‚ !öñ¹ŒŠÚ ÂQôäjCxÜŒA°ÿäÿÂÿ«ÿ˜ÿ‰ÿ9ÿÿ)þ7ý«ý*ü—ûüûvûúÙû‘ü¥üÂýý_ýý•ý{ýGýDý>ý©þ5þßÿkÿnÿMÿGÿcëÜÉ‘(ÿöÿíÿôCî-^†©Éæ/BUfuƒ™¡§«­¬ª¥Ÿ—‚ufVD0îÕ» ƒfH* ìÌ«ŠhF$ß¼›zZ;$.9DOZfr‹˜¤±¾ËØæô 0ARdv‰²Èß÷+He„¥ÈïGy®ê*q¾qØJÈTïš U  ì ² o zT(ÝÂâæí£+Y±!‹Ñ$}Ð,  ú Ï |w¿rYmó –ëRýúùš ÿ_þüþ¸þrþ3ýðý²ý‡ý=üáüWü)ûÑú¥ù´ùœùÁú¼ûyü ü`üªüÓüÝüÔüÓüèý%ýwýÒþ2þjþ]þ‘þ=þþ‡ÿaÿðÿùÿÆÿ°ÿ€ÿ\þåþ”ÿ6ÿ½ÿú‰Š×Fp”µÓî1CTcq|†“–˜—”‰xm`QA/òÛ©ŽsV9ýß¿Ÿ^=ûÙ·–vW9",6AKVamx„œ¨´ÁÍÚçõ.>N_p‚•©¾Ôë7Sp²×,\ÊM™ìG¬™"º_  Í _ 6 ;Ü­“jŒƒý —ýÿKÂïð ô z Ô ö û ôçáúÇvw‚9Í[‰þíþœÿ]ÿŽþúþlþ)ýÃýHü¹üIûñû¤ûVúûú®úšúŒøö÷ƒ÷¹ùFúúÄûXûÅü ü2ü<ü:ü8ü[üÉý>ýˆý“ý¢ý·ýÌý¬ýŒýÞþéÿ#þúþ¸þ(þeþý¸ýèþìÿ¡6­#}Äý-X}Ÿ¾Ùò 0AP]iry~ƒ‚ztlcXK<-ôßȰ—}bF* ðÒ³”uT4ôÒ²‘rT7!*4>HR]hs~‰” «·ÂÎÚçó )8HXhy‹ž²ÆÜó #>Yw˜¼ã<n¦ã%oÀ|écè{Æ | 9  ï  À³‡V ÇAt·44;C®í  R  à $9QaŠ»eNva£íÿ©þÏý¸þýßý_ý&ý0ýüäüû)úŠúùÅùwù ø¯øŽø6÷Göl÷iøžù©úWúåûKûŒû¬û³û¨û˜ûšüDýXýwýiýXýiýªý†ýDýŸþoþ^þMýýÆý’ý|ýkýÃþ}ÿ¨G¼l­ã=d†¥ÁÛó-<IT]eilmlie_WNC6(ôá̵ž…lR7ÿãŧ‰jK, ì̬nQ5(1:DMXblvŒ—¢­·ÃÎÙåñý #1@O^n‘£¶Ëàö &@\{ÃìH~¹ù@æF°&§5Ït ! Ó › — x Lvÿ¨¡ …‘à²io’  þ S S c ˆ ú <dËDŸ'à®t¢<Uÿyþýäýcü¤û§û#û%û\û[úùoø˜ø÷Ò÷˜÷@ö—öƒöŽöcö®÷Œøšùpúú›ú÷û.ûCûEû7û û1ü3üæý/ýýý\ýGý2ýý;ý»þýÐýªýoý|ýZý_ýÏþÃÿ—;¬QÆö!Hk‹©ÄÜò'4?HOTWXWTOIB8-!óá͹£Œt[B' ñÕ¹œ~`A#åŧˆkN3 %.7@IR\fpyƒŽ™£­·ÂÌ×âíø)6DSbq‚’¤·Êßô #>\| ÆðR‹É Z® qã`é}¹ t K   á IA,PA.È¿ Ú c † ‰ Å ?{ cªß;¸P÷ž6·oÿ¯þèþ)ýxü¾ûÛú_ùNøÚùùDø…÷@öbõÖõ²öõÖõœõ·ö@ö¯÷9÷öøÀùrúúvúÅúòúýúøúöúûû#û‹û×û¸üBü¿üü üˆü¼ý ýmý”ýžýýýhýký‹þ'þäÿ˜$è1p§×+Pq¬ÅÜð*3:>ABA>:4,# þïßͺ¦zcJ2þãÈ­sU8üÞ¿¡„gL1 #+4<ENW`ir{†™£­¶ÀÊÔÝçñü+8ESap ²ÅÙí9XyžÅò#Y”× qË.œ˜%½c %  Á – 2 ý Åiѽ±Àd Ê ú @ ^ n ‚È+b¢oú^»(ª<Ñ^ÞMÿ­ÿþSý¢üêü#û ùìø]÷,öÊö¯õûõ ôCô1ôfôÜõ}õÐö)ö¢÷3÷Åøbùù”úúqú³ú×úßúÚúîúëúóû ûúñû:ûÖûŽûû¥û÷üúüßüÿýKý\ýsýlýjýÕþ`þþÿ rÇN†¸å4Ww“­ÄÙëû#(+,+)$øêÛ˹§“~hQ:" ïÖ» …hK/ô×¹€dI0  )19AJRZckt}†™¡ª³¼ÅÎ×àéóý)5BO\jxˆ˜©»Íâú0Pr—Áð$\œâ0‡æPÄDÎdÄ ƒ 5  » d  V ~ U R 2 ç r í † Z0uÐ >Ðc½mêqŽ ÿ‚þîþTý¶ýüfû¤úÇù¦ø7÷õîõô–ô óÁôôºõOõÜöWö½÷-÷®ø:øÈùRùÏú9ú†ú¾úÖúáúìúçúÐú´úÎú×úÖúóúøûúîûûšûîüûùühý ý-ýUýžþþ†ÿ ÿ†ÿõT§î-e˜Çò<]{•­ÂÔäòý  ùïãÕÇ·¦”€kV@)úáÈ®”y]A% íд˜|aG. &.6>FMU]emu}†Ž—Ÿ§¯·¿ÇÏØàéòû$/:FR_m{Šš«¾Ôì#CfŽºë!^¡ì?œrír¡Câ · ” % Ÿ õ   ‰ ( ´ C ¶æ:HR¥^v[êKVº˜7ÿÅÿ@þ¹þ0ý¥ýü…ûïûKúù°ø¿÷¶ö¾õÂô¬ôÛôûõDõ¸ö-öŒöâ÷:÷¤ø#ø°ù9ù·ú úxú¼úàúüúèúÒúÕúªúŠú¸úÐúú}úpú‹ú„úÁúþûû1û9ûaû×ü¾ýSý¸þ&þ™ÿ ÿzÿß8ˆÎ FzªÖþ"Db}•ª½ÍÛçð÷ûþÿýùóìäÚÎÁ³£’€mYD/ëÓº¡‡mS8åÊ®“x^E- $+3:AHPW_gnv}…Œ”›¢ª±¸ÀÆÎÕÝåîöÿ$.9DP\iv†—«ÁÙô2W¯ã]¥öN°š,щ U á + K s b - ñ • ­Ývº)íŒó˜Ç,Bÿïÿ°ÿ þ†ýîýsüíümûùû‡û úùäù:øˆ÷Ñ÷öˆöRöö§öØ÷÷4÷e÷£÷þøœù>ùÜúEú”úÊúòû6ûAú£ú’ú¸úÄú½ú úXùãùfùdù—ùÓú úúúKú‹ú¢ûüpýCýÄþ4þ ÿ ÿlÿÉj°ï)^»ä +Ie}“¦¶ÄÐÙàåèêéçãÞ×ÏŹ­Ÿm[G3 óÜĬ”{bH.ùݨŽt[B+!(/6=DKRY`gnu{ƒ‰–¤ª°¶¼ÃÉÐ×Þåìôû '1;FQ_o€”ªÂÝüFr£Ú\¨üY¿-¥)¹RïŠÁëôÖrû·KÙØtË:¬|ÃïÏxŠÿ¼ÿ‚ÿ?þ¸ýÓý_üÄü,û®ûeûúÙúúù³ùEøÎø\ø÷å÷é÷ù÷ø÷ã÷Ñ÷Õ÷õø,ø¤ù¦ú!ú£ûúûûû+úõú¾ú©ú¾úÆúŽúù#øšø[øhø˜ø×øÿøõøÖùaúú‹ûüjý8ýÂþ4þþÿÿ]ÿ´P”ÔCt¡Êð1Mf{ŽŸ­¸ÂÉÎÒÔÔÒÎȺ°¥˜‹|l[I6"ùäͶŸ‡oV=$ ðÖ¼¢‰pW@) %,29?FLSZ`flsy…‹‘—œ¡§¬±·¼ÂÇÍÓØÞåëòù!*6DSey§Ää 2`”ÏW¦ý[À.£•òRj¥¤¶rÂU_°d]À€z4Q"Æ+ÿ}þîþVýòý’ýüRûkûúáúÖú»úœú_ú0úùÌù{ù5ù.ùDù]ù)ø·øDø%ø8øJømøºùgúaúñúôúäú¾úÎú¸úâú®úFùÔøø÷ò÷"÷V÷‡÷¡÷Æ÷ùøø&øøúúÞû¸üý4ý»þ-þ”þóÿMÿ ÿï8|ºô*[ˆ²Øú5Ndwˆ–¡«²¸¼¾¾¼¸³­¤›„whXH7$ýéÔ¿¨‘zbK2èεœ„lT=( ")/5;AGNSZ_ejpv{€…Š“˜œ¡¥©­±¶º¿ÃÈÌÑÖÛáçíóú %4FYoЍÊðL‚¾I˜ëCŸüO™ÓFb˜Èös¿$ž“hnB9ÝvÂÿÏÿDþªþýný4üûÆûBúÔúÃûúãú½úšúŠúšú»ú;úú%úHú]úEù5øSøZønøNøRø[ø®ù×ú¬úãúÍú¾ú´úaúCùðù'øÉø÷%ö[öIö¶ö±ö’öõ÷i÷ïøäú ûûßü™ý3ý³þ$þ‰þæÿ=ÿŽÿÛ#e£ÝDqšÀâ7M`qŠ”œ¢¦¨¨¦£—†|pcTE5$íÙŰ›„nW?(øàǯ—hQ;&  &+17<BHNSX^chmqvz~‚†Š‘”—𠣦©¬¯²¶¹¼ÀÄÈÍÒØàéõ"6Ni‰¬Ó1h£ã&l³ø7j•¿ßN3‡ˆ¦+ !õ땞ÿåÿYþsý‰ýIüìü€ûÐûúæúÒúíúñúÞúÄú úµú™ú|ú0úúú2ùïøüø…ø`øVøVøUøPøeùSúYú³úÌú”ú ùïùøÇø~ø ÷öçõôööõàõßööœ÷Èùú+û$ûñüŸý/ý¬þþ~þÙÿ.ÿ~ÿÉQÈý-Z„©Ìë6IZhs}…Œ““‘ˆ‚zrg\OA2"ïÝʶ¢waK4ïØÀ©‘zdN9% #(-28>CHMQW\`dhlpsvy|„†ˆŠ‹‘’”–—™šœž¡£¥¨­³ºÃÎÛéû)Feˆ°Ü >r¨ÞAh†ŸežÕô‚×UÎA, —~Zm^ã{$ÿÓÿþ ýˆýü·üû¸û`úßúûú´úÊúÖúÎú¾úµújùåùWùùù øÙøŠødøYøbøYøfø]øløÎùáú?ùúùÅùYøïø¥ø@ø ÷Ì÷löjõüõÒõÇõ«õõÇös÷õùDúYû=ûþü ý,ý¥þþsþÍÿ!ÿoÿ¹ÿÿ?|´èEn“µÔð 2CQ]govz}}{xsmf]SG;-ðßͺ§“jU?)ýæÐ¹£Œv`K7#  %*/49>BFKPTX[_behkmoqstuvwxyyyzz{{{{{{{||}~€„Š‘™¤°ÀÒç:\€§Ï÷Fh…𣉔±™/Ùp„—άfRO8ÿòÿ–ÿþ+ýjüÜüQüü:ûîû„û"úÇúÀú¼úÒúÛúæúéú•ù—ø×ømø|øzøiøPø(øAøIø[øtø”øyøNøoøuø^ø•ø©øwø,÷ù÷{öþöuõñõÃõ¿õ¸õªõŽõì÷$øWù…ú~ûSüü£ý)ý þ þkþÃÿÿcÿ«ÿï/k¢Õ1Y~ ¿Úó,:GQY`dggeb^XQH>3' þïßϽ«˜…r^I4 óÝDZœ†q\H4" "'+059=AEIMPSVY\^`acdefffffedccba`_]\ZYWVTSRSUX]dlvƒ’£¸Ïè<Yv§»ÈÌÈÿ²j;ÿþÿäÿÄÿ­ÿ‹ÿhÿÿ5ÿiÿ‘ÿ[þ¾ýÛýü?û£û^ûUûšû²û_úÚúSú~ú²úÒúÍúèúóúŸùYøœøLø2øVøTøXøCø)ø2øIøtøzø0÷ƒöãö˜öî÷øø ÷†÷ ö¦ö4õÅõ®õŸõ¡õ¸õµö-öÚ÷ÇøØùÌúªûlüü¨ý*ýžþþdþ»ÿ ÿXÿŸÿâ [‘ÄóFj‹©ÄÝò$1;CJNQQPMHC<3*ûíÝÏ¿®œŠxeQ=)ÿêÔ¿ª•mXE2  $(,048<?BEHKNPRTVWWXXXXXWUSQONLJGEB?<962/,)&%%').3;DP]m~‘¤¸ÌÞïþüëϘ0ÿÈÿpÿ?ÿþëþ®þ„þ þþ þCþÅþ£ýƒü·ü û|ûúÎúÒú¦úðúžùÕù»ùòú1úZúVúOúeù¯ø÷øuø\ø1ø#÷ú÷Ê÷®÷Å÷×øøKø'÷GöÔöbö3öeöÊ÷ ÷ö¹ö3õØõÐõ¬õ£õ³õ˜öövöô÷«øsùGúúÚûŠü&ü²ý/ýŸþþ`þµÿÿOÿ”ÿÖL‚³á 3Vw•¯ÇÝï%-48;;:73.' õèÛ;¯ŸŽ|jXE2 õàÌ·£{hUB0 !%(,0369<>ADFHJKLLMMLLKJHFC@=:740-)%  ÿþÿúÿ÷ÿõÿôÿõÿ÷ÿúÿÿ  +7CNYbhkjcWE+ÿÊÿzÿþ¨þ*ýùýÑýŒýTýMýüæüàüÞü§ü û{û ú¯úfú/ú úkúYúù ùù&ù]ùfù6ùSù?ùøŒøeøKø@÷Ã÷‘öÇö‚ö™öø÷¾÷ ÷Höâömö-ööö)ö9ööõàõ¸õ¤õŸõµööPöž÷#÷­øKøúù¯úcûû¬ü=üÀý7ý£þþ^þ±þþÿGÿ‹ÿÌ?s¤Ñú Dd›²ÇÚëù#%&%" øîã×ʼ®Ÿo]K9&ìØÄ°œ‰vcQ?. !%(+.1368:<>@ABBCCBA@?=;841-)$  ÿûÿôÿîÿçÿàÿÚÿÓÿÍÿÉÿÅÿÂÿÀÿÀÿÀÿÂÿÄÿÇÿÌÿÑÿÖÿÜÿàÿäÿåÿäÿàÿÙÿÍÿ»ÿ£ÿÿUÿþÏþrýþý•ýCý üÁüiü.üûÙûBûúÈúxúùÑù›ù|ù\ùQùUùtøêø¾ø‘øªø°ø¢ø€øføSø1ø÷ñ÷ò÷á÷~öíöyö%ö4ööÒöåö§öeöõñõÕõ¹õÇõ¹õÑõÈõÆõ·õ«õìö;öŒöë÷F÷¸ø>øÏùkú ú©ûBûÒüWüÒýCýªþþ^þ¯þûÿAÿ„ÿÃÿý3f–Áê1Qm‡ž³ÅÕäðû   þ÷ïæÛÑÆ¹¬ž€qaP?-öâϼ©–ƒq_M<, "%'),.0246789:::997531.+'"ÿüÿöÿïÿèÿáÿÙÿÑÿÉÿÁÿ¹ÿ±ÿ¨ÿ¡ÿšÿ”ÿÿ‹ÿˆÿ†ÿ„ÿƒÿÿÿÿÿÿ}ÿyÿrÿiÿ\ÿKÿ4ÿþñþÂþ‡þAýìýý2üÞü‰üûxû/û úÀúVùÛù‘ùøéøŸø¨ø®ø¦ø“øøQøJøMø]øUø?ø ÷Ó÷œ÷ˆ÷t÷c÷S÷K÷)öîö“ö<öö öö6ö:öõîõÖõžõ õ°õ®õ­õ®õ°õ¹õñö"ö`ö·÷ ÷h÷Íø=øºù@ùÍú\úëûuûøüsüæýQý³þ þ`þ¯þøÿ=ÿ~ÿ»ÿô)Zˆ³Úÿ ?ZtŠŸ±ÁÏÛæîôùûüûøõðêãÜÓÊ¿µ©œŽ€rcSC2!þìÙÇ´¢~l[J:*  !#&()+-./0122210/.+)&# ÿýÿöÿïÿèÿáÿÚÿÒÿÉÿÁÿ¸ÿ®ÿ¥ÿ›ÿ‘ÿˆÿ~ÿtÿlÿdÿ]ÿVÿPÿKÿFÿAÿ<ÿ6ÿ1ÿ+ÿ#ÿÿÿþïþÚþ¿þžþvþFþ ýËýý.üØüüû£û&ú¤ú…úEù£ùøvøZø=øJø.øEøVø6øAø1ø!ø7ø@ø9÷á÷röþöÍö´ö¹ö¹ö¯ö’öxöSö,õÿõÏõÆõÅõÐõäõÆõ›õµõ¤õ§õ¥õÁõ¼õ©õæööRö–öÝ÷-÷„÷àøEø²ù'ù¤ú%ú§û(û¦üü‘üýýaý¾þþdþ°þøÿ:ÿyÿ´ÿëO|¥Ëï-Haw‹­»ÇÑÙßäæçæäàÜÖÐÉÁ¸®¤™ŒqdUF6&ôãÑ¿­œŠyhWG7(   "$%'()*++++*)('%" ÿýÿöÿîÿçÿßÿ×ÿÏÿÆÿ½ÿ´ÿ«ÿ ÿ–ÿ‹ÿÿuÿjÿ_ÿSÿHÿ>ÿ4ÿ*ÿ!ÿÿÿþÿþöþíþâþÖþÉþ¹þ§þ’þyþ\þ9þýàý¨ýiý#üØüˆü2ûÕûsûú®ú]úùwø–ø4ø"øAøJø;øCøMøFøGøOøOøBøDø&÷©ö®ö>öõýöö+ööõÞõîõÜõÇõ²õõµõÃõÊõ´õŸõ õ­õ‰õÀõðöööHöˆöÄ÷÷P÷Ÿ÷õøQø²ùù‰ùýútúìûbûÖüFü°ýýrýÉþþjþ³þøÿ9ÿuÿ®ÿäDp˜½àÿ7OexŠ™§³¼ÄÊÏÑÒÒÐÌÈþ·¯¦“‰}pcUG9* úêÙÈ·¦–…tdTD5&  !"#$%%%%$#"  ÿÿÿøÿñÿéÿáÿÙÿÐÿÇÿ¾ÿµÿ¬ÿ¡ÿ—ÿŒÿ€ÿuÿiÿ\ÿPÿCÿ7ÿ*ÿÿÿþùþíþáþÖþÊþ¾þ±þ£þ”þ„þqþ\þDþ(þ ýäýºý‹ýUýü×üüEûöû£ûMú÷ú£úMùêùhøèøˆøhøeødø^øWøHøBøLø[øQøI÷á÷¥÷ö*õØõ¸õ±õ½õ¿õ®õ³õ½õ²õµõ­õ£õ²õÆõÕõÌõ±õŠõ£õÐõñööBökö‘ö¿öö÷3÷u÷¾ø ø`ø¹ùù{ùãúOú½û,û™üüküÎý+ýƒý×þ&þqþ¸þúÿ8ÿsÿªÿÝ;eŒ°Ñð &=Sfw†“Ÿ¨°¶º½¾¾¼¹µ±«¥ž•ŒƒxnbUG:,ðàÏ¿°Ÿo`PA3$    ÿûÿõÿîÿçÿÞÿÖÿÍÿÄÿºÿ°ÿ¦ÿœÿ‘ÿ…ÿzÿmÿaÿTÿFÿ9ÿ+ÿÿÿþòþäþÖþÈþ¹þ«þþþ~þmþ\þHþ3þþýäýÃýžýtýEýü×ü™üVüûÆûzû,úÞúú=ùäù†ù,øäøµø›ø‹ø~øqøbøWøSøMø@ø÷¿öðösö2õÂõ®õ·õ½õ¿õ±õõÅõÉõ­õ£õÊõäõ÷õþõúõìõêõÿö+öYö€ö§öÐöü÷,÷b÷ž÷àø'øtøÅùùvùÔú6úšûûgûÍü0üüëýCý—ýæþ2þyþ½þýÿ9ÿqÿ¦ÿØ2Z€£Äáý-ATds€Œ•œ¢¦©ªª©¦£ž™“Œ…|si_SG:, õæÖÆ·¨˜‰zk\M>0#   ÿýÿøÿòÿëÿäÿÜÿÔÿËÿÂÿ¸ÿ®ÿ¤ÿ™ÿŽÿ‚ÿvÿiÿ\ÿOÿAÿ3ÿ$ÿÿþøþèþÙþÉþ¸þ¨þ˜þ‡þvþeþRþ@þ+þýÿýåýÊý«ý‰ýcý9ý üÙü¢ügü(ûæû¡ûZûúÊúú6ùéùœùVùøìøÍø¶ø¤ø”ø…øvøeøQø1ø÷¨÷/öºö_ö+ö öööõõõõõ÷õúõïõôö ö'ö9öEöKöRö^ötö”öºöá÷ ÷4÷b÷”÷ÊøøFøŒø×ù&ùyùÏú(ú„úâû@û ûþüZü³ý ý\ý«ý÷þ?þƒþÃÿÿ:ÿpÿ£ÿÓÿÿ)Qu—¶Óî0BSamx‚‰“•——–”‘Œ‡{tlcZPE9, øêÛ;¯ ‘ƒufXJ<.!   ÿüÿ÷ÿñÿêÿãÿÛÿÔÿËÿÂÿ¸ÿ®ÿ¤ÿ™ÿÿ‚ÿuÿiÿ[ÿNÿ@ÿ1ÿ#ÿÿþôþäþÔþÃþ²þ þŽþ|þiþVþCþ.þþýìýÓý¹ý›ý|ýYý3ý üÞü­üxüAüûÇû‡ûEûú¾úzú7ùôù³ùxùDùøùøàøËø¸ø¦ø“ø}øaø;ø ÷Å÷t÷öØö¢ö€ökö`öXöSöNöKöHöIöPö`ötö†ö•ö£ö±öÃöÛöù÷÷B÷k÷—÷Å÷øø.øiø©øíù6ù‚ùÑú"úwúÍû%û}ûÖü-üƒü×ý(ývýÁþþLþþËÿÿ<ÿpÿ¡ÿÏÿú"HkŒªÆà÷  2AO[fov|€ƒ„…„‚{vqkd\TKA7+ úíßÒö§™‹}obTF9,    ÿÿÿúÿöÿðÿêÿãÿÜÿÔÿÌÿÃÿºÿ°ÿ¥ÿšÿÿƒÿwÿjÿ]ÿOÿAÿ3ÿ$ÿÿþôþäþÓþÂþ±þžþŒþyþeþQþ<þ'þýûýãýËý°ý”ývýVý4ýüæüºü‹üZü%ûíû³ûwû9úûú¼ú}ú@úùÍù™ùkùCù#ùøòøÞøÉø´ø›ø}øVø'÷î÷°÷r÷:÷ öêöÑöÀöµö¬ö¦ö¡öŸö¢öªö·öÇöØöéöú÷÷#÷=÷[÷}÷£÷Ì÷÷ø&øYøøÊùùKù‘ùÙú$úrúÂûûeû¸ü ü\ü¬üúýFýýÖþþZþ˜þÓÿ ÿ?ÿpÿŸÿËÿô?ažºÒéþ"1>JT]dinqrsrpnjfa[TME<3)ûïâÕȺ­ ’„wj]PC6*  ÿýÿúÿõÿðÿêÿäÿÝÿÖÿÎÿÅÿ¼ÿ³ÿ©ÿžÿ“ÿ‡ÿzÿnÿaÿSÿEÿ7ÿ(ÿÿ þøþèþ×þÅþ´þ¡þŽþ{þgþSþ>þ)þýûýãýÊý°ý•ýxýZý9ýüòüÊü üsüDüûÝû§ûoû5úüúÂú‰úQúùéùºùùlùMù2ùùøðøÙø¿ø¡ø}øTø%÷ó÷Á÷“÷l÷L÷2÷÷÷öþöùöøöû÷÷÷÷-÷?÷S÷i÷÷÷»÷Ýøø+øWø†ø¸øîù'ùeù¥ùçú,útú½û ûUû¢ûïü<ü‰üÔýýdý©ýìþ,þiþ£þÛÿÿBÿqÿžÿÈÿð8Yw“®ÆÜð!.9CKRX\_aaa_]ZVQKE>6.%ûðäØË¿²¥˜Œ~qeXL@4(  ÿþÿüÿùÿõÿðÿêÿåÿÞÿØÿÐÿÈÿÀÿ·ÿ­ÿ£ÿ˜ÿÿ€ÿsÿfÿYÿKÿ=ÿ.ÿÿþÿþïþÝþÌþºþ¨þ•þ‚þnþZþEþ/þþýêýÒý¸ýýýdýEý%ýüÞü·üüdü7üûÖû£ûoû9ûúÎúšúgú6úùÞù·ù•ùwù]ùFù0ùùøéøÍø­ø‰øaø8ø÷è÷Æ÷¨÷÷|÷m÷a÷X÷S÷R÷U÷\÷g÷u÷†÷™÷®÷Å÷Þ÷úøø;øaø‰ø´øãùùIù‚ù½ùúú:ú|úÀûûLû”ûÜü%ümü´üúý?ý‚ýÃþþ>þwþ¯þãÿÿEÿsÿÿÆÿì1Pn‰¢ºÏâó)2:AFKNOPPOMJFB<6/( úðåÙÍÁµªž‘…yl`TH=1&ÿÿÿýÿûÿøÿôÿðÿëÿæÿàÿÚÿÓÿÌÿÃÿ»ÿ²ÿ¨ÿžÿ“ÿˆÿ{ÿnÿ`ÿSÿDÿ6ÿ'ÿÿþøþçþÕþÄþ²þŸþŒþxþdþOþ:þ$þ ýöýÞýÅý«ýýtýWý8ýüõüÑü¬ü…ü\ü2üûÖû¦ûvûDûúáú°úúTú*úùßù¿ù£ùŠùsù\ùFù/ùøýøáøÂø¡ø~ø\ø;øø÷ê÷×÷È÷¼÷³÷¯÷®÷±÷¸÷Â÷Ð÷á÷ôø ø!ø;øXøwø™ø¾øåùù>ùoù£ùÙúúLú‰úÈûûJûûÐüüXü›üÞý ý`ýŸýÜþþOþ†þºþìÿÿIÿuÿÿÄÿè +Ie€˜®ÂÔåô"*06:=???>=:72.(! øîäÚÎø¬¡–Š~sg[PD9.$ÿÿÿþÿüÿúÿ÷ÿôÿïÿëÿæÿáÿÜÿÖÿÏÿÈÿ¿ÿ·ÿ®ÿ¤ÿšÿÿ„ÿwÿjÿ\ÿNÿ@ÿ1ÿ"ÿÿþòþáþÏþ½þ«þ™þ…þqþ]þHþ2þþýîýÕý¼ý¢ýˆýlýOý0ýüïüÌü¨üƒü\ü3ü ûÝû°ûƒûUû&úøúËú úwúPú,ú ùìùÑù¹ù¢ù‹ùvù`ùIù1ùøþøáøÄø§ø‹øpøWøBø0ø"øøø ø øøøø-ø=øPøfø}ø˜ø´øÓøõùù@ùjù˜ùÇùùú-úcú›úÔûûMû‹ûÊü üIüˆüÈýýDý€ý»ýôþ,þaþ•þÆþõÿ#ÿNÿwÿžÿÃÿå%B]wŽ£¶Ç׿óÿ  %)-/0//-*'# ýõìãÙÏź¯¤šƒxmbWLA6,"ÿÿÿþÿýÿüÿúÿ÷ÿôÿðÿëÿçÿâÿÞÿÙÿÓÿÌÿÅÿ¼ÿ´ÿªÿ¡ÿ–ÿŒÿ€ÿtÿgÿYÿLÿ=ÿ.ÿÿþÿþîþÝþËþ¹þ§þ”þþmþXþCþ.þþýéýÐý·ýžýƒýgýKý,ý üíüÌü©ü…ü`ü9üûèû¾û”ûiû?ûúëúÂúœúxúWú8úúùéùÒù¼ù§ù’ù}ùgùQù:ù"ù øðøØøÁø«ø˜øˆø{øqøkøgøhøkørø|ø‰øšø¬øÂøÙøóùù.ùOùsùšùÃùîúúKú}ú°úåûûUûŽûÉüü?ü{ü·üòý-ýfýŸýÖþ þ@þsþ£þÒþÿÿ*ÿSÿzÿŸÿÂÿã;Un„˜ª»ÊØåðú    ÿøðèà×ÎÄ»±¦œ’ˆ}rg]RH=3) ÿÿÿýÿüÿûÿùÿöÿôÿðÿíÿèÿäÿßÿÚÿÕÿÐÿÉÿÂÿºÿ±ÿ¨ÿŸÿ”ÿ‰ÿ~ÿrÿeÿXÿJÿ<ÿ-ÿÿþýþìþÛþÉþ·þ¥þ’þþkþWþAþ,þýÿýçýÏý¶ýœý‚ýgýJý-ýüðüÏü®ü‹ühüCüûøûÐû©ûûZû3û úçúÄú¢úƒúfúKú1úúùïùÛùÇù³ùŸù‹ùwùbùMù8ù#ùøüøìøÞøÓøÊøÅøÃøÄøÈøÏøÙøæøõùùù4ùNùiùˆù¨ùËùðúúAúlúšúÉúúû-ûaû–ûÌüü;üsü«üãýýQýˆý½ýñþ#þTþ„þ±þÞÿÿ1ÿXÿ}ÿ ÿÁÿàÿþ5NezŸ¯¾Ë×âìôû   þøòëãÜÔÌú±§ž•Š€wlbXND:0' ÿÿÿÿÿÿÿþÿýÿüÿúÿùÿ÷ÿôÿñÿíÿéÿåÿáÿÜÿØÿÓÿÍÿÇÿ¿ÿ·ÿ¯ÿ¦ÿÿ’ÿˆÿ|ÿqÿdÿWÿIÿ;ÿ-ÿÿþýþìþÛþÉþ·þ¥þ’þþkþWþBþ,þþýèýÐý¸ýžý„ýjýNý1ýüöü×ü·ü–ütüRü.ü ûæûÁûœûxûSû0û úíúÍú°ú•ú{úcúLú7ú#úùýùëùØùÆù´ù¢ùù~ùlù\ùLù>ù2ù)ù"ùùùù#ù*ù4ùAùPùbùwùŽù§ùÂùßùÿú úDúiú‘úºúåûûAûqû¢ûÕüü<üpü¤üÙý ýAýuý§ýÙþ þ9þgþ”þÀþéÿÿ9ÿ]ÿ€ÿ¡ÿÁÿßÿû/G]qƒ”¤²¿ÊÕÞæíóøýÿýùõðëåß×ÐÉÁ¹°§Ÿ–ƒzpg]SJ@7.% ÿÿÿÿÿÿÿþÿþÿýÿüÿûÿúÿøÿöÿôÿñÿîÿêÿæÿâÿÞÿÚÿÖÿÑÿËÿÅÿ½ÿ¶ÿ®ÿ¥ÿœÿ’ÿ‡ÿ|ÿqÿdÿWÿJÿ<ÿ.ÿÿþÿþîþÝþËþ¹þ§þ”þþnþZþEþ0þþýìýÕý¼ý¤ýŠýpýUý9ýýüâüÄü¤ü„ücüBü ûþûÛû¹û—ûvûUû5ûúúúÞúÄú¬ú•ú€úkúXúFú4ú#úúùòùâùÓùÃùµù§ùšùù…ù}ùxùuùuùxù}ù…ùù›ùªù¼ùÐùæùþúú4úRúrú”ú¸úÝûû.ûYû…û²ûàüü@üqü¢üÓýý6ýfý–ýÆýõþ#þOþ{þ¥þÍþõÿÿ@ÿcÿ„ÿ£ÿÁÿÝÿø)@UhyŠ˜¦³¾ÈÑÙßæëïòôõõõôòðìèãÞØÒÌŽ¶®¦Ÿ—Ž…|sjaXOF=4+# ÿÿÿÿÿþÿþÿýÿüÿûÿúÿùÿøÿöÿôÿñÿîÿëÿçÿäÿàÿÜÿÙÿÕÿÐÿÊÿÃÿ¼ÿ´ÿ­ÿ¤ÿ›ÿ‘ÿ‡ÿ}ÿqÿeÿXÿKÿ>ÿ0ÿ"ÿÿþñþàþÏþ½þ«þ˜þ…þrþ^þJþ5þþ ýóýÛýÄý«ý“ýyý_ýDý)ý üðüÓüµü—üxüXü8üûùûÙû¹ûšû|û^ûBû'û úõúÞúÈú´ú úŽú}úlú]úNú?ú0ú"úúùüùðùæùÜùÕùÏùËùÊùÌùÏùÕùÝùçùóúúú%ú:úQújú…ú¢úÀúáûû'ûLûsûœûÅûðüüIüvü¤üÒýý.ý\ýŠý·ýäþþ;þdþþµþÛÿÿ$ÿGÿhÿ‡ÿ¥ÿÁÿÜÿö $9M_p€Ž›§²¼ÅÌÓÙÞâåçèèçæåãßÛ×ÒÌÆÀº³¬¤–ކ~vmd[SJA90)! ÿÿÿÿÿÿÿþÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿôÿñÿïÿëÿèÿåÿáÿÞÿÚÿ×ÿÓÿÎÿÈÿÁÿºÿ³ÿ¬ÿ¤ÿ›ÿ’ÿˆÿ~ÿsÿgÿZÿNÿAÿ3ÿ%ÿÿþöþåþÔþÃþ±þžþ‹þxþeþQþ<þ'þýûýåýÍý¶ýý…ýkýRý7ýýüåüÉü¬üüqüSü5üûúûÝûÀû¤ûˆûnûTû<û&ûúûúèúÖúÅúµú¥ú—ú‰ú|úoúcúXúMúBú9ú0ú)ú#úúúúú#ú)ú1ú;úGúUúeúwú‹ú¡ú¹úÓúîû û+ûKûmû‘û¶ûÜüü+üUüü©üÔüÿý+ýVýý¬ýÖþþ)þRþyþŸþÄþéÿ ÿ-ÿNÿmÿ‹ÿ§ÿÁÿÛÿó 3FWgv„‘œ§°¸ÀÆÌÐÔ×ÙÚÛÚÙØÖÓÏËÆÁ»µ¯©¢œ•†wog^VNF=5-& ÿÿÿÿÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿöÿôÿòÿïÿíÿéÿæÿãÿàÿÜÿÙÿÖÿÒÿÍÿÇÿÁÿºÿ³ÿ¬ÿ¤ÿœÿ“ÿ‰ÿÿuÿiÿ]ÿQÿEÿ7ÿ)ÿÿ þûþìþÛþÊþ¸þ¦þ“þ€þmþZþEþ1þþýðýÙýÂý«ý“ýzýaýHý/ýüúüßüÄü¨üŒüpüTü8üüûçûÍû³û›ûƒûlûWûCû0ûû úüúíúßúÒúÅú¹ú®ú£ú™úú‡úúxúsúnúlúkúlúnúsúyú‚úŒú—ú¥ú´úÆúÙúîûûû8ûTûrûû±ûÒûõüü>üdü‹ü²üÚýý+ýSý|ý¥ýÍýõþþBþhþþ±þÔþöÿÿ7ÿUÿrÿŽÿ©ÿÂÿÚÿñ-?P_n{‡’œ¥­´»ÀÄÈËÍÎÎÎÍËÉÆÃ¿»¶°«¥Ÿ™“Œ…~xpiaYQJB:2+$ ÿÿÿÿÿþÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿõÿôÿòÿðÿíÿëÿèÿåÿáÿÞÿÛÿØÿÕÿÑÿÌÿÇÿÀÿºÿ³ÿ¬ÿ¥ÿÿ”ÿ‹ÿÿwÿlÿaÿUÿIÿ<ÿ.ÿ ÿÿþóþãþÒþÀþ®þœþŠþwþdþPþ<þ'þýýýçýÑýºý£ý‹ýsý[ýCý*ýü÷üÝüÃü©üüuü[üAü(üû÷ûßûÈû²ûû‰ûvûdûSûCû4û&ûû ûú÷úíúäúÛúÓúËúÅú¿ú»ú¸ú¶ú¶ú¸ú»úÀúÇúÐúÚúåúòûûû%û9ûOûfûûšûµûÓûñüü2üTüvüšü¿üãý ý/ýUý{ý¡ýÇýìþþ6þZþ~þ þÂþãÿÿ"ÿ@ÿ\ÿxÿ’ÿ«ÿÃÿÙÿï(9IXfr}ˆ’›¢©¯´¸¼¿ÁÂÂÂÁ¿½º·³¯«¦¡›•Šƒ}wqjb[TMF>6/("ÿÿÿÿÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿöÿôÿóÿñÿïÿìÿéÿçÿäÿàÿÝÿÚÿ×ÿÔÿÐÿËÿÆÿÀÿºÿ´ÿ­ÿ¦ÿŸÿ–ÿÿ„ÿzÿpÿeÿZÿNÿAÿ4ÿ&ÿÿ þûþëþÛþÊþ¸þ§þ•þƒþpþ]þIþ5þ þ ý÷ýáýËýµýžý‡ýpýYýAý*ýüùüáüÈü¯ü—ü~üfüOü8ü!ü ûöûáûÎû»ûªû™û‰ûzûmû`ûTûIû>û4û+û#ûûûûûûúÿúþúÿûûû ûûû%û0û<ûKû[ûmûû–û¬ûÃûÜûöüü/üMülüŒü¬üÎüðýý6ýYý}ý ýÄýèþ þ.þPþrþ“þ³þÓþòÿÿ-ÿIÿdÿ}ÿ–ÿ­ÿÄÿÙÿí$4CQ^juˆ‘˜Ÿ¤©­±³µ¶¶¶µ´±¯«¨¤ œ—’Œ‡|vpjc\VOHA:3-&  ÿÿÿÿÿþÿýÿüÿûÿûÿúÿùÿøÿöÿõÿóÿòÿðÿîÿëÿèÿæÿãÿàÿÝÿÚÿ×ÿÔÿÐÿËÿÆÿÀÿ»ÿ´ÿ®ÿ¨ÿ ÿ˜ÿÿ‡ÿ~ÿtÿjÿ_ÿTÿGÿ;ÿ.ÿ ÿÿþôþäþÔþÄþ³þ¢þþ~þkþXþDþ0þþýóýÞýÈý²ýœý†ýpýZýDý-ýüÿüèüÑüºü¤üüwübüLü8ü$üûÿûíûÝûÎû¿û²û¥û™ûŽû„û{ûrûjûbû\ûUûPûKûGûEûDûDûEûHûLûRûZûcûmûxû„û’û¢û³ûÆûÚûïüüü5üOüjü†ü£üÁüàüÿý ý@ýaý‚ý¤ýÅýæþþ(þIþiþ‰þ¨þÆþäÿÿÿ8ÿRÿkÿƒÿšÿ°ÿÅÿÙÿìÿþ /=KWbmv‡Ž”šŸ¢¥¨©ª«ªª¨¦¤¡žš–’Žˆƒ~ytnic\VPJD=60*$ ÿÿÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿöÿôÿóÿñÿïÿíÿêÿèÿåÿãÿßÿÝÿÚÿ×ÿÔÿÐÿËÿÇÿÁÿ¼ÿ¶ÿ°ÿªÿ£ÿ›ÿ“ÿ‹ÿ‚ÿyÿoÿeÿZÿNÿBÿ6ÿ)ÿÿ þþþïþàþÐþÀþ¯þžþþ{þhþUþBþ/þþýóýÞýÉý´ýŸýŠýuý`ýKý5ýý üôüßüÊüµü üŒüxüeüSüAü0ü üüûöûéûÝûÒûÈû¿û¶û®û§û ûšû•ûûŒû‰û‡û‡û‡û‰ûû‘û—ûŸû¨û²û½ûÉûÖûæûöüüü/üDüZüqü‰ü£ü½üÙüõýý/ýMýlý‹ýªýÉýèþþ&þEþcþþŸþ¼þØþôÿÿ)ÿBÿZÿqÿˆÿÿ²ÿÆÿÙÿëÿü *8DP[env~„Š”˜›žŸ  Ÿ›™–“‰„€{vrlgb\WQKE?93-'! ÿÿÿþÿýÿüÿûÿûÿúÿùÿøÿ÷ÿöÿôÿòÿñÿïÿíÿêÿçÿäÿâÿßÿÝÿÚÿ×ÿÔÿÑÿÌÿÈÿÂÿ½ÿ·ÿ²ÿ¬ÿ¥ÿžÿ–ÿŽÿ†ÿ~ÿtÿjÿ`ÿUÿJÿ>ÿ2ÿ%ÿÿ þûþìþÝþÍþ¾þ­þþ‹þyþgþUþBþ0þþ ýöýâýÎýºý¦ý’ý}ýiýUýAý,ýýüñüÝüÊü·ü¥ü“ü‚ürübüSüFü8ü,ü üü üûùûñûêûãûÝûØûÓûÏûÌûÊûÉûÉûÊûÌûÏûÔûÚûáûêûôûÿü üü'ü6üGüYülü€ü”üªüÁüÙüòý ý&ýAý\ýxý•ý²ýÏýìþ þ&þCþ`þ}þ™þ´þÏþéÿÿÿ4ÿLÿbÿxÿÿ¢ÿµÿÈÿÚÿëÿû &3?JT]fnu{†Š’”•••”’Ž‹‰†ƒ|xsnje`[VQLFA;5/*% ÿÿÿþÿýÿüÿûÿûÿùÿøÿ÷ÿöÿõÿôÿòÿðÿïÿíÿêÿçÿäÿâÿßÿÝÿÚÿ×ÿÕÿÒÿÍÿÉÿÄÿ¿ÿ¹ÿ´ÿ®ÿ¨ÿ¡ÿšÿ“ÿ‹ÿ‚ÿzÿpÿgÿ\ÿRÿFÿ;ÿ/ÿ"ÿÿþùþêþÛþÌþ½þ­þœþ‹þzþiþWþEþ3þ!þýüýéýÖýÃý¯ýœý‰ývýcýPý=ý+ýýüõüãüÒüÂü²ü£ü”ü‡üzümübüWüMüDü;ü3ü+ü$üüüüü ü üüüü ü üüüü"ü*ü3ü>üJüWüeütü„ü”ü¦ü¹üÍüáüöý ý$ý<ýUýnýˆý¢ý½ýØýóþþ)þDþ_þzþ•þ¯þÈþáþùÿÿ(ÿ?ÿUÿkÿÿ“ÿ¦ÿ¸ÿÊÿÛÿëÿù#/:DNW_fmsx|„‡ˆŠ‹‹Š‰ˆ†„‚}zwsokfb^YUQLGA;61,'" ÿÿÿþÿýÿüÿûÿûÿùÿøÿ÷ÿöÿõÿóÿòÿðÿïÿíÿêÿçÿäÿâÿßÿÝÿÚÿØÿÖÿÓÿÏÿËÿÆÿÁÿ»ÿ¶ÿ°ÿ«ÿ¥ÿžÿ—ÿÿ‡ÿÿwÿmÿcÿYÿOÿDÿ9ÿ-ÿ!ÿÿþùþêþÜþÍþ¾þ®þžþŽþ}þmþ\þJþ9þ(þþýóýàýÎý¼ýªý˜ý†ýtýcýRýAý0ý ýýüñüâüÔüÇüºü®ü¢ü˜üŽü…ü|ütülüeü_üYüTüPüMüJüGüFüFüGüHüKüOüTüYü`ühüqü{ü‡ü“ü ü®ü¾üÎüÞüðýýý*ý?ýUýký‚ýšý²ýÊýãýüþþ.þGþ`þzþ“þ¬þÄþÛþòÿ ÿÿ5ÿJÿ_ÿsÿ†ÿ™ÿªÿ¼ÿÌÿÜÿëÿù+5?HPX_ekptw{}€€~}{yvtqnjgc_[WSOKFA<72-)$  ÿÿÿþÿýÿüÿûÿûÿùÿøÿ÷ÿöÿõÿóÿòÿñÿïÿíÿêÿçÿåÿâÿàÿÝÿÛÿÙÿÖÿÔÿÐÿÍÿÈÿÄÿ¾ÿ¹ÿ³ÿ®ÿ©ÿ£ÿœÿ”ÿÿ…ÿ}ÿuÿkÿbÿXÿNÿCÿ8ÿ-ÿ!ÿÿþùþëþÝþÏþÀþ±þ¢þ’þ‚þrþbþRþBþ1þ þýÿýîýÝýÌý»ýªý™ý‰ýyýiýZýKý<ý-ýýýüøüìüáüÖüÌüÃü»ü³ü«ü¤üü˜ü’üŽüŠü‡ü…üƒü‚ü‚üƒü…üˆüŒü‘ü–üœü¤ü­ü·üÁüÍüÙüçüõýýý%ý6ýHý\ýoý„ý™ý®ýÄýÚýñþþþ6þMþdþ|þ“þ«þÂþØþîÿÿÿ-ÿAÿUÿhÿ{ÿÿžÿ¯ÿ¿ÿÏÿÝÿëÿù'1:BJQW]cgkoqtuwwwwvusrpnkifb_\XTQNJE@;72.*&" ÿÿÿþÿýÿüÿûÿûÿùÿøÿ÷ÿöÿõÿóÿòÿñÿïÿíÿêÿèÿæÿãÿáÿÞÿÜÿÚÿ×ÿÕÿÒÿÏÿËÿÆÿÁÿ¼ÿ·ÿ²ÿ­ÿ§ÿ¡ÿšÿ“ÿ‹ÿ„ÿ|ÿtÿkÿaÿXÿNÿDÿ9ÿ-ÿ"ÿÿ þüþïþáþÓþÅþ¶þ¨þ™þŠþ{þlþ\þMþ=þ-þþýþýïýßýÏý¿ý°ý¡ý’ý„ývýhý[ýNýAý5ý*ýýý ýüøüðüéüâüÛüÕüÐüËüÇüÄüÁü¿ü½ü½ü½ü¾üÀüÃüÇüÌüÑü×üÞüçüðüúýýýý+ý:ýIýXýhýyý‹ýžý±ýÄýØýìþþþ+þ@þUþkþþ–þ¬þÂþ×þëÿÿÿ'ÿ:ÿMÿ_ÿqÿƒÿ”ÿ¤ÿ´ÿÃÿÑÿßÿìÿø#-5=DKQV[_bfhjlmnnmlkjigec`]ZWTQNKGD?;72.*'# ÿÿÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿõÿôÿóÿòÿðÿîÿëÿéÿæÿäÿâÿàÿÝÿÛÿØÿÖÿÓÿÑÿÍÿÉÿÄÿÀÿ»ÿ¶ÿ±ÿ¬ÿ¦ÿ ÿ™ÿ’ÿ‹ÿ„ÿ|ÿtÿkÿbÿYÿOÿDÿ:ÿ/ÿ$ÿÿ ÿþóþæþÙþËþ½þ¯þ¡þ“þ…þwþhþYþKþ<þ.þþþýôýåý×ýÉý»ý®ý¡ý”ý‡ý{ýpýeýZýPýFý=ý4ý,ý%ýýýý ýýüÿüûüùü÷üöüöüöüøüúüýýýý ýýýý(ý1ý<ýFýRý_ýmý{ý‰ý˜ý¨ý¹ýÊýÜýîþþþ&þ9þLþ`þtþˆþœþ°þÄþØþëþÿÿÿ$ÿ6ÿHÿYÿjÿzÿ‹ÿšÿªÿ¹ÿÇÿÔÿàÿìÿø  )07>EJPTW[]`bcdeedcca`^][XVSQNKHEB>:62.*'$! ÿÿÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿõÿôÿóÿòÿðÿïÿìÿêÿçÿæÿãÿáÿÞÿÜÿÚÿØÿÖÿÓÿÐÿÌÿÈÿÄÿ¿ÿºÿµÿ±ÿ¬ÿ¦ÿ ÿ™ÿ’ÿ‹ÿ„ÿ}ÿuÿlÿcÿZÿQÿGÿ=ÿ3ÿ(ÿÿÿþùþíþàþÔþÆþºþ­þŸþ’þ„þwþiþ\þNþ@þ3þ&þþ ýþýñýäýØýËýÀý´ý©ýžý”ýŠýýxýoýgý`ýYýRýLýGýBý=ý:ý6ý3ý1ý0ý/ý/ý/ý1ý3ý6ý9ý=ýBýHýOýVý^ýgýqý{ý†ý’ýžý«ý¹ýÇýÖýåýõþþþ'þ8þJþ[þmþþ’þ¤þ¶þÉþÛþíÿÿÿ#ÿ3ÿDÿUÿeÿuÿ„ÿ“ÿ¢ÿ°ÿ½ÿÊÿ×ÿâÿíÿø %,39?DIMPSUWYZ[[[[ZZYWVUSQOLJGEB?<851.*'%! ÿÿÿÿÿþÿþÿýÿüÿûÿúÿùÿøÿöÿõÿôÿóÿñÿïÿíÿëÿéÿçÿåÿãÿàÿÞÿÜÿÚÿØÿÕÿÒÿÐÿÌÿÈÿÃÿ¿ÿºÿ¶ÿ±ÿ¬ÿ§ÿ¡ÿšÿ“ÿÿ†ÿ~ÿwÿnÿfÿ]ÿTÿKÿAÿ7ÿ-ÿ"ÿÿ ÿþõþêþÞþÒþÅþ¹þ¬þ þ”þ‡þ{þnþaþUþHþ<þ0þ$þþ þýöýëýàýÖýÌýÂý¹ý°ý¨ý ý™ý’ý‹ý†ý€ý{ývýsýoýlýjýhýfýfýfýfýhýjýmýpýtýyý~ý…ý‹ý“ý›ý¤ý®ý¸ýÃýÎýÚýçýôþþþþ-þ<þLþ\þlþ}þþžþ®þ¿þÐþáþòÿÿÿ$ÿ3ÿCÿRÿbÿpÿÿŽÿœÿ©ÿ¶ÿÂÿÎÿÙÿäÿîÿø !(.49>BFILNPQRSSSSRRQOONLJHFCA?<9630-*'%" ÿÿÿþÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿôÿóÿòÿñÿïÿíÿêÿèÿæÿäÿâÿàÿÞÿÜÿÙÿ×ÿÕÿÓÿÐÿÌÿÈÿÄÿÀÿ»ÿ·ÿ²ÿ®ÿ¨ÿ¢ÿœÿ•ÿÿˆÿÿzÿrÿjÿaÿYÿPÿGÿ>ÿ4ÿ*ÿ ÿÿ ÿþõþêþÞþÓþÈþ¼þ°þ¥þ™þŽþƒþwþkþ`þUþJþ?þ4þ*þ þþ þýúýñýèýàýØýÑýÊýÄý¾ý¹ý´ý¯ý«ý§ý¤ý¢ý ýžýýœýœýýžý ý£ý¦ýªý®ý³ý¹ýÀýÇýÎýÖýßýéýóýýþþþ þ,þ9þFþTþbþpþþŽþþ­þ¼þËþÚþéþùÿÿÿ'ÿ6ÿDÿRÿaÿoÿ|ÿŠÿ—ÿ¤ÿ°ÿ¼ÿÇÿÒÿÜÿæÿïÿù $*/48<?BDFHIJKKKKJJIHGFECA?<:8641.,)&$! ÿÿÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿõÿôÿóÿòÿðÿïÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÓÿÐÿÍÿÉÿÅÿÁÿ½ÿ¹ÿ´ÿ°ÿªÿ¥ÿžÿ˜ÿ’ÿ‹ÿ…ÿ~ÿvÿnÿgÿ_ÿWÿNÿEÿ<ÿ3ÿ)ÿÿÿ ÿþ÷þíþâþØþÍþÂþ¸þ­þ£þ™þŽþƒþzþpþfþ\þRþIþ?þ7þ.þ&þþþþþýûýõýðýëýæýâýÞýÛýØýÖýÔýÓýÒýÑýÑýÒýÓýÕýØýÛýÞýâýçýìýòýùþþþþþ!þ+þ5þ?þJþVþaþnþzþ‡þ“þ¡þ®þ½þËþÙþæþôÿÿÿÿ,ÿ:ÿGÿTÿbÿoÿ|ÿˆÿ”ÿ ÿ¬ÿ·ÿÂÿÌÿÖÿßÿèÿñÿù!&+/369;=?@BCCCCCCBBA@?><:86431/,*'%#! ÿÿÿÿÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿòÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÒÿÏÿËÿÇÿÃÿ¿ÿ»ÿ·ÿ²ÿ­ÿ¨ÿ¢ÿœÿ–ÿÿ‰ÿƒÿ|ÿuÿnÿfÿ^ÿVÿOÿFÿ=ÿ4ÿ,ÿ#ÿÿÿþýþóþéþßþÖþÍþÃþºþ°þ§þžþ•þŒþƒþzþrþiþaþYþRþKþDþ=þ6þ0þ+þ&þ!þþþþþþ þ þþþþþþþþ þ þþþþþþ$þ*þ0þ7þ?þGþOþXþaþjþtþ~þ‰þ”þ þ«þ·þÃþÏþÛþèþõÿÿÿÿ'ÿ3ÿ@ÿLÿYÿeÿqÿ}ÿˆÿ“ÿžÿ©ÿ³ÿ½ÿÇÿÑÿÚÿâÿêÿòÿú "'*-025689::;;;;;::98765420/-+*(&$" ÿÿÿÿÿþÿþÿýÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿòÿñÿïÿíÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿÙÿÖÿÔÿÐÿÍÿÊÿÆÿÂÿ¾ÿºÿµÿ°ÿ¬ÿ¦ÿ¡ÿ›ÿ•ÿÿ‰ÿƒÿ|ÿuÿoÿhÿaÿYÿQÿIÿAÿ9ÿ0ÿ(ÿÿÿÿþüþôþëþãþÚþÑþÉþÁþ¹þ±þ©þ¡þšþ’þ‹þ„þ}þwþqþjþdþ_þZþUþQþMþIþFþCþ@þ>þ<þ:þ9þ9þ9þ9þ9þ;þ<þ>þAþDþGþKþPþUþZþ`þfþmþtþ{þƒþ‹þ”þþ¦þ°þºþÄþÎþÙþäþïþúÿÿÿÿ'ÿ2ÿ=ÿHÿTÿ_ÿiÿtÿÿŠÿ”ÿžÿ¨ÿ²ÿ»ÿÄÿÍÿÕÿÞÿåÿíÿôÿû #&(+-.0122344444332210/.,+*('%$"  ÿÿÿÿÿþÿýÿýÿüÿûÿúÿùÿøÿøÿ÷ÿöÿõÿóÿòÿðÿïÿíÿëÿéÿçÿåÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÓÿÐÿÍÿÉÿÅÿÂÿ½ÿ¹ÿµÿ°ÿ«ÿ¦ÿ¡ÿœÿ–ÿ‘ÿ‹ÿ…ÿÿyÿsÿlÿeÿ]ÿVÿOÿHÿ@ÿ8ÿ0ÿ)ÿ!ÿÿÿ ÿþúþóþìþäþÝþÖþÏþÈþÂþ»þ´þ®þ¨þ£þþ˜þ’þþ‰þ…þþ}þzþwþtþrþpþnþmþlþkþkþkþlþmþoþpþsþuþxþ|þ€þ…þŠþþ”þšþ þ§þ®þµþ½þÅþÍþÖþÞþèþñþúÿÿÿÿ!ÿ+ÿ5ÿ?ÿIÿSÿ]ÿgÿqÿ{ÿ„ÿŽÿ—ÿ ÿ©ÿ²ÿ»ÿÃÿËÿÓÿÚÿâÿéÿðÿöÿü !#%'()*+,,,---,,,,++*)('&%#"  ÿÿÿÿÿÿÿþÿþÿýÿüÿûÿúÿùÿùÿøÿ÷ÿöÿõÿôÿóÿòÿðÿïÿíÿëÿéÿçÿæÿäÿâÿàÿÞÿÝÿÛÿÙÿÖÿÓÿÐÿÍÿÊÿÆÿÂÿ¾ÿºÿ¶ÿ±ÿ­ÿ¨ÿ£ÿžÿ™ÿ”ÿÿŠÿ„ÿ~ÿwÿqÿkÿdÿ^ÿXÿQÿJÿCÿ<ÿ6ÿ.ÿ(ÿ!ÿÿÿÿÿþúþôþïþéþãþÝþ×þÒþÍþÉþÄþ¿þ»þ·þ³þ¯þ¬þ©þ§þ¥þ£þ¡þŸþžþþþþþžþŸþ þ¡þ¤þ¦þ¨þ¬þ¯þ³þ¸þ¼þÁþÆþÌþÑþ×þÞþåþìþóþúÿÿ ÿÿÿ#ÿ,ÿ4ÿ=ÿFÿNÿWÿ`ÿiÿqÿzÿƒÿ‹ÿ“ÿœÿ¤ÿ¬ÿ´ÿ¼ÿÃÿËÿÒÿÙÿßÿæÿìÿòÿ÷ÿý  "#$%%&&&&&&&&&&%%%$#"!  ÿÿÿÿÿþÿýÿüÿüÿûÿûÿúÿùÿøÿøÿ÷ÿõÿôÿóÿòÿñÿïÿîÿìÿêÿèÿçÿåÿäÿâÿàÿÞÿÜÿÚÿ×ÿÔÿÑÿÎÿËÿÇÿÄÿÀÿ½ÿ¹ÿ´ÿ°ÿ¬ÿ¨ÿ¤ÿŸÿšÿ•ÿÿŠÿ…ÿ€ÿzÿuÿoÿiÿcÿ]ÿWÿRÿLÿFÿ@ÿ:ÿ5ÿ/ÿ*ÿ$ÿÿÿÿÿ ÿÿþüþøþôþðþìþèþäþáþÞþÛþÙþ×þÕþÓþÑþÐþÏþÎþÎþÎþÎþÏþÏþÐþÒþÔþÖþØþÛþÞþáþåþéþíþòþöþûÿÿÿ ÿÿÿÿ&ÿ-ÿ4ÿ;ÿBÿIÿQÿXÿ`ÿgÿoÿwÿ~ÿ†ÿÿ•ÿœÿ£ÿªÿ±ÿ¸ÿ¿ÿÆÿÌÿÒÿÙÿÞÿäÿêÿðÿôÿùÿý   ÿÿÿÿÿþÿýÿýÿüÿüÿûÿûÿúÿùÿùÿøÿ÷ÿöÿõÿôÿóÿñÿðÿîÿìÿëÿêÿèÿçÿæÿäÿâÿàÿÞÿÛÿÙÿÖÿÓÿÑÿÎÿËÿÈÿÄÿÀÿ½ÿºÿ¶ÿ³ÿ¯ÿ«ÿ¦ÿ¡ÿÿ˜ÿ”ÿÿ‹ÿ†ÿÿ|ÿwÿrÿmÿhÿcÿ^ÿYÿUÿPÿKÿGÿCÿ>ÿ:ÿ6ÿ1ÿ-ÿ)ÿ%ÿ!ÿÿÿÿÿÿ ÿ ÿ ÿÿÿÿÿÿþÿþþþþþþþþþÿþÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿ ÿ$ÿ)ÿ.ÿ3ÿ8ÿ=ÿCÿHÿNÿTÿZÿ`ÿfÿmÿsÿyÿ€ÿ†ÿÿ“ÿ™ÿ ÿ¦ÿ¬ÿ²ÿ¸ÿ¾ÿÄÿÊÿÏÿÕÿÚÿßÿäÿéÿîÿóÿ÷ÿûÿþ  ÿÿÿÿÿþÿþÿýÿýÿýÿýÿüÿûÿûÿúÿùÿøÿøÿ÷ÿöÿõÿôÿòÿñÿðÿïÿîÿíÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÕÿÓÿÐÿÍÿÊÿÇÿÄÿÁÿ¾ÿ»ÿ·ÿ³ÿ¯ÿ¬ÿ¨ÿ¥ÿ¡ÿÿ™ÿ•ÿ‘ÿŒÿˆÿ„ÿ€ÿ|ÿxÿtÿpÿmÿiÿeÿbÿ^ÿZÿWÿSÿPÿLÿIÿFÿCÿ@ÿ>ÿ;ÿ9ÿ7ÿ5ÿ3ÿ2ÿ1ÿ0ÿ/ÿ.ÿ.ÿ.ÿ.ÿ.ÿ.ÿ.ÿ.ÿ.ÿ/ÿ0ÿ2ÿ3ÿ5ÿ7ÿ9ÿ<ÿ?ÿBÿEÿHÿLÿPÿTÿXÿ\ÿ`ÿeÿjÿoÿtÿyÿ~ÿƒÿˆÿÿ’ÿ—ÿÿ¢ÿ§ÿ­ÿ²ÿ·ÿ¼ÿÁÿÆÿËÿÐÿÔÿÙÿÝÿáÿæÿêÿîÿòÿöÿùÿüÿÿ  ÿÿÿÿÿÿÿþÿþÿþÿþÿýÿýÿüÿüÿûÿúÿúÿùÿùÿøÿ÷ÿöÿõÿôÿóÿòÿòÿñÿðÿîÿìÿëÿéÿèÿæÿäÿãÿáÿßÿÝÿÛÿÙÿÖÿÔÿÒÿÏÿÍÿÊÿÇÿÄÿÂÿ¿ÿ¼ÿ¹ÿ¶ÿ³ÿ°ÿ­ÿ©ÿ¦ÿ¢ÿŸÿœÿ™ÿ–ÿ“ÿÿÿŠÿ‡ÿ„ÿÿ~ÿ{ÿxÿuÿsÿpÿmÿkÿiÿgÿeÿcÿaÿ`ÿ_ÿ^ÿ]ÿ\ÿ\ÿ\ÿ\ÿ\ÿ\ÿ\ÿ\ÿ\ÿ\ÿ\ÿ\ÿ]ÿ^ÿ_ÿ`ÿaÿcÿeÿhÿjÿmÿpÿsÿvÿyÿ|ÿÿ‚ÿ†ÿŠÿŽÿ’ÿ–ÿšÿžÿ¢ÿ¦ÿªÿ®ÿ²ÿ¶ÿ»ÿ¿ÿÃÿÇÿËÿÏÿÓÿ×ÿÛÿßÿâÿåÿéÿìÿðÿóÿöÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿþÿþÿþÿþÿýÿýÿüÿüÿüÿûÿúÿúÿùÿøÿøÿ÷ÿöÿöÿõÿôÿóÿòÿñÿïÿîÿíÿëÿêÿèÿçÿåÿäÿâÿàÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÌÿÊÿÈÿÆÿÃÿÁÿ¾ÿ»ÿ¹ÿ·ÿ´ÿ²ÿ°ÿ®ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿžÿœÿšÿ˜ÿ–ÿ”ÿ’ÿÿÿÿŒÿ‹ÿŠÿ‰ÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿˆÿ‰ÿŠÿ‹ÿŒÿŽÿÿ’ÿ”ÿ–ÿ˜ÿšÿœÿŸÿ¡ÿ£ÿ¦ÿ©ÿ¬ÿ¯ÿ²ÿµÿ¸ÿ»ÿ¾ÿÁÿÄÿÇÿÊÿÍÿÐÿÓÿÖÿÙÿÜÿßÿâÿåÿèÿëÿíÿðÿòÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿþÿþÿþÿþÿþÿýÿýÿüÿüÿüÿûÿûÿúÿúÿùÿùÿøÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿèÿçÿæÿäÿãÿâÿàÿßÿÝÿÜÿÚÿÙÿ×ÿÕÿÓÿÒÿÐÿÏÿÍÿÌÿÊÿÉÿÇÿÆÿÄÿÃÿÁÿÀÿ¾ÿ½ÿ¼ÿºÿ¹ÿ¸ÿ·ÿ¶ÿµÿ´ÿ³ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ²ÿ³ÿ´ÿµÿ¶ÿ¸ÿ¹ÿºÿ¼ÿ½ÿ¿ÿÀÿÂÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿöÿøÿùÿûÿüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿþÿþÿþÿýÿýÿýÿýÿüÿüÿûÿûÿúÿúÿùÿùÿøÿøÿ÷ÿ÷ÿöÿöÿõÿõÿôÿóÿóÿòÿñÿñÿðÿïÿîÿîÿíÿìÿëÿêÿéÿéÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿàÿàÿßÿÞÿÞÿÝÿÜÿÜÿÛÿÛÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿÞÿßÿàÿáÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿüÿýÿþÿþÿÿminc-2.2.00/README0000644000265600003100000001646212030075003010316 00000000000000MINC - Medical Image NetCDF INTRODUCTION ------------ The MINC file format is a highly flexible medical image file format built on the HDF5 generalized data format. The format is simple, self-describing, extensible, portable and N-dimensional, with programming interfaces for both low-level data access and high-level volume manipulation. On top of the libraries is a suite of generic image-file manipulation tools. The format, libraries and tools are designed for use in a medical-imaging research environment : they are simple and powerful and make no attempt to provide a pretty interface to users. Here's a list of some of the tools: * rawtominc, minctoraw, mincextract - format conversion * mincheader, mincdiff, mincinfo, minchistory - file information * mincedit, minc_modify_header - header manipulation * mincresample - arbitrary volume resampling * mincreshape - extraction of volume sub-cubes, image flipping, dimension re-ordering, type conversion * mincconcat - concatenating or interleaving images from multiple files * mincmath - perform simple math on files * minccalc - perform more complicated math on files through an expression * mincaverage - average minc files * mincstats - calculate statistics across voxels of a file * minclookup - lookup table operations for arbitrary re-mappings of intensities * worldtovoxel, voxeltoworld - coordinate conversion * xfmconcat, xfminvert - generalized transformation utilities * mincview - simple image display using xv or ImageMagick * mincpik - generate picture from slice through volume Additional tools are available from the Montreal Neurological Institute (MNI). http://packages.bic.mni.mcgill.ca/tgz MINC requires that NetCDF and HDF5 are installed. MINC development is performed on github http://github.com/BIC-MNI/minc SUPPORT FOR HDF5 "MINC 2.0" FORMAT FILES ---------------------------------------- This change requires that HDF5 must be installed before MINC can be built. The latest version of HDF5 is 1.6.2. You can obtain HDF5 from: http://www.hdfgroup.org/ You should NOT need to become an HDF5 expert to use MINC 2.0. However, two tools included with HDF5 may prove useful, "h5dump" and "h5ls". h5dump is roughly equivalent to netCDF's ncdump utility. There is no exact netCDF tool analogous to h5ls. h5ls is useful for exploring and extracting bits of the HDF5 hierarchy. 1.2 New command Line options All MINC tools which produce output MINC files now take a "-2" option which will tell the tool to output a MINC 2.0 format file. All MINC tools also take a "-version" flag. 1.3 Compatibility To the extent possible, the core MINC tools should operate "correctly" on MINC 1.0 and 2.0 files. There are a few notable exceptions. Scripts such as "mincdiff", "mincedit", and "mincheader" may not work, or will produce odd results since they depend on the ASCII format of the netCDF "ncdump" and "ncgen" utility. I'm open to suggestions for the best way to handle this. We have an unfinished "mincdump" tool which replaces "ncdump", but we do not yet have a replacement for "ncgen". 1.4 Conversion There is a new conversion utility called "mincconvert". This is just a trivial library wrapper that can copy a file from the input to the output while performing a conversion. 2. REVISED ERROR MESSAGE HANDLING. I have somewhat revised the ways in which MINC decides when and how to print error messages, with the hope to gradually improve the readability and usefulness of these messages. In some cases I have probably been too aggressive, and messages will now appear which really don't belong. Please let me know which ones are most annoying, and I'll try to get rid of them. 3. TENTATIVE ".mincrc" AND ENVIRONMENT VARIABLE SUPPORT This is implemented as a way to control certain behaviors of the library which are not readily available through other means. These variables may be defined either in your environment, or in the .mincrc file in your home directory. The value in the environment should override the one in .mincrc. Here's what exists so far: # Force output files to MINC 2.0 format, regardless of the "-2" option. # MINC_FORCE_V2 = {1, 0} # Desired ZLIB compression level. Zero implies no compression, a value # of 4 gives a good tradeoff of compression and performance. # MINC_COMPRESS = {0..9} # Desired HDF5 chunking dimension. This controls the size of the # "hypercube" used by HDF5 to store the file. If set to zero, the # file will not be stored in a chunked format, unless compression is # enabled. The chunk size will automatically be reduced if it exceeds # any actual dimension of the volume. If chunking is enabled # automatically because of compression, the default chunk dimension is # 32. # MINC_CHUNKING = {0..N} # Log file - path to the desirned output file for messages. The default # is the standard error (stderr) stream. To redirect to standard output, # set this variable to "stdout" or "-". Otherwise the variable is taken # to be the path to the desired log file. If the path name begins with # a '+' character, the log file should be appended rather than recreated. # MINC_LOGFILE = [+]|stdout|- # Logging level. Not really useful yet, but intended to allow setting # of 'verbosity' of messages. A value of zero would inhibit all but # fatal messages, a value of 4 would allow debugging messages. # MINC_LOGLEVEL = 0-4 4. NEW PROGRAMMING INTERFACE 4.1. New MINC 1.0 calls A couple of new things have been added to libminc: /* Returns a printable library version string */ const char * miget_version(); /* Appends "new_history" to the file's history attribute. */ int miappend_history(int fd, const char *new_history); 4.2. New MINC 2.0 calls This is a new set of calls, defined in "minc2.h" and the assorted source files found in the libsrc2 directory. The general philosophy is to provide a higher level interface than "libminc", but without some of the constraints and memory management of "volume_io". DOCUMENTATION ------------- http://en.wikibooks.org/wiki/MINC PROGRAMMING WITH THE MINC API ----------------------------- 1) NetCDF and HDF5 are basis, providing a C callable library for accessing data structures in a file at a low-level. 2) The low-level MINC library is used to do medical-image specific things. It provides some enhancements to NetCDF and HDF5 as well as image conversion routines for dealing with image pixel value issues as well as image size and orientation. Documentation consists of a programmer's guide and reference (minc_user.tex and minc_reference.tex in the doc directory). Example C programs exist in progs/mincexample. 3) A high-level C library called volume_io provides a Volume data type, with functions like input_volume to give simple access to data while handling issues of pixel range conversion and voxel-to-world coordinate conversion. Documentation consists of a programmer's reference volume_io/Documentation/volume_io.tex. Example programs exist in volume_io/Testing. The LaTeX documentation is not built by default. You can build these documents using cd doc; make docs cd volume_io/Documentation; make docs latex and dvips are required. Applications that use MINC alone need to #include and link with "-lminc2 -lnetcdf -lhdf5 -lz -lm". Applications built with VolumeIO need to #include and link with "-lvolume_io2 -lminc2 -lnetcdf -lhdf5 -lz -lm". minc-2.2.00/configure.in0000644000265600003100000000553212030075003011743 00000000000000dnl Process this file with autoconf to produce a configure script. AC_INIT([minc],[2.2.00],[a.janke@gmail.com]) AC_CONFIG_SRCDIR([libsrc2/minc2.h]) AC_CONFIG_AUX_DIR(ac_config_aux) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([config.h]) AC_REVISION($Revision: 6.45 $) AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AM_PROG_CC_C_O AC_PROG_F77 AM_PROG_LEX AC_PROG_YACC AC_HEADER_TIME AC_HEADER_DIRENT AC_CHECK_HEADERS(sys/time.h sys/stat.h sys/wait.h unistd.h) AC_CHECK_HEADERS(fcntl.h pwd.h float.h values.h) AC_CHECK_TYPES([int32_t, int16_t]) # dnl Build only static libs by default # AC_DISABLE_SHARED AC_PROG_LIBTOOL AC_PATH_PROGS(POD2MAN, pod2man) AM_CONDITIONAL(BUILD_POD_DOC, test "x$POD2MAN" != "x" ) if test "x$POD2MAN" = "x"; then AC_MSG_WARN([pod2man not installed, unable to build all manual pages]) fi AC_SUBST(POD2MAN) smr_WITH_BUILD_PATH # Check for required C libraries mni_REQUIRE_LIB(m,[#include ],[double x = sqrt(3.);]) mni_REQUIRE_LIB(netcdf,[#include ],[int i = ncopen("",0);]) AC_ARG_ENABLE(disminc2, [ --disable-minc2 disable HDF5 (MINC 2) functionality], [ case "${disableval}" in yes) disminc2=true ;; no) disminc2=false ;; *) AC_MSG_ERROR(bad value ${disableval} for --disable-minc2) ;; esac], [disminc2=false]) AM_CONDITIONAL(MINC2, test x$disminc2 = xfalse) # force certain HDF5 function calls to the 1.8.x versions AC_DEFINE_UNQUOTED([H5Acreate_vers],[2],[Force the 1.8.x version]) if test x$disminc2 = xfalse; then mni_REQUIRE_LIB(z, [#include ],[compress2;]) mni_REQUIRE_LIB(hdf5,[#include ],[int f = H5Fopen("",0,H5P_DEFAULT);]) AC_DEFINE_UNQUOTED([MINC2],[1],[Define if MINC 2.0 is enabled.]) else AC_DEFINE_UNQUOTED([MINC2],[0],[Define if MINC 2.0 is enabled.]) fi dnl Replacement implementations for systems that lack the function. dnl need ac 2.57 for this? AC_CONFIG_LIBOBJ_DIR(libsrc) AC_REPLACE_FUNCS(strdup) dnl Verify existence of mkstemp, tempnam, and tmpnam AC_CHECK_FUNCS(mkstemp tempnam tmpnam) dnl Verify existence of some functions we'd like to use AC_CHECK_FUNCS(getpwnam select strerror sysconf) # Functions required for execute_decompress_command(). AC_FUNC_FORK AC_CHECK_FUNCS(system popen) # Code to enable conditional build of ACR/NEMA tools AC_ARG_ENABLE(acr-nema, [ --enable-acr-nema install ACR/NEMA tools], [ case "${enableval}" in yes) acr_nema=true ;; no) acr_nema=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-acr-nema) ;; esac], [acr_nema=false]) AM_CONDITIONAL(ACR_NEMA_TOOLS, test x$acr_nema = xtrue) AC_CONFIG_FILES([ Makefile epm-header doc/Makefile testdir/Makefile libsrc2/test/Makefile volume_io/Makefile volume_io/Documentation/Makefile volume_io/Testing/Makefile ]) AC_OUTPUT( progs/xfm/xfmflip progs/minccomplete/minccomplete progs/minchistory/minchistory progs/mincpik/mincpik ) minc-2.2.00/aclocal.m40000644000265600003100000010526112030077512011301 00000000000000# generated automatically by aclocal 1.10.3 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],, [m4_warning([this file was generated for autoconf 2.67. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.10' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.10.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.10.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 10 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 13 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.60])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_PROG_LEX # ----------- # Autoconf leaves LEX=: if lex or flex can't be found. Change that to a # "missing" invocation, for better error output. AC_DEFUN([AM_PROG_LEX], [AC_PREREQ(2.50)dnl AC_REQUIRE([AM_MISSING_HAS_RUN])dnl AC_REQUIRE([AC_PROG_LEX])dnl if test "$LEX" = :; then LEX=${am_missing_run}flex fi]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/mni_REQUIRE_LIB.m4]) m4_include([m4/smr_WITH_BUILD_PATH.m4]) minc-2.2.00/Makefile.am0000644000265600003100000003754612030114702011500 00000000000000# Makefile.am for MINC2 # AUTOMAKE_OPTIONS = check-news subdir-objects ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = AM_YFLAGS = -d --debug SUBDIRS = . volume_io testdir doc if MINC2 SUBDIRS += libsrc2/test endif # how to build man pages from POD progs/minccomplete/minccomplete.man1: progs/minccomplete/minccomplete $(POD2MAN) --section=1 $< > $@ progs/minchistory/minchistory.man1: progs/minchistory/minchistory $(POD2MAN) --section=1 $< > $@ progs/mincpik/mincpik.man1: progs/mincpik/mincpik $(POD2MAN) --section=1 $< > $@ # Add these to the include searches. # INCLUDES = \ -I$(top_srcdir)/libsrc \ -I$(top_builddir)/volume_io/Include \ -I$(top_srcdir)/volume_io/Include \ -I$(top_srcdir)/progs/Proglib \ -I$(top_srcdir)/conversion/Acr_nema if MINC2 INCLUDES += -I$(top_srcdir)/libsrc2 endif # Headers which must be installed. # include_HEADERS = \ libsrc/minc.h \ libsrc/ParseArgv.h \ libsrc/voxel_loop.h \ libsrc/nd_loop.h \ libsrc/time_stamp.h \ libsrc/minc_compat.h \ volume_io/Include/volume_io.h \ libsrc2/minc2.h \ libsrc/minc_simple.h include_volume_iodir = $(includedir)/volume_io include_volume_io_HEADERS = \ volume_io/Include/volume_io/alloc.h \ volume_io/Include/volume_io/arrays.h \ volume_io/Include/volume_io/basic.h \ volume_io/Include/volume_io/def_math.h \ volume_io/Include/volume_io/files.h \ volume_io/Include/volume_io/geom_structs.h \ volume_io/Include/volume_io/geometry.h \ volume_io/Include/internal_volume_io.h \ volume_io/Include/volume_io/multidim.h \ volume_io/Include/volume_io/progress.h \ volume_io/Include/volume_io/string_funcs.h \ volume_io/Include/volume_io/system_dependent.h \ volume_io/Include/volume_io/transforms.h \ volume_io/Include/volume_io/vol_io_prototypes.h \ volume_io/Include/volume_io/volume.h \ volume_io/Include/volume_io/volume_cache.h # Header files which must be included in the distribution but which are # not part of the installation. # noinst_HEADERS = \ libsrc/read_file_names.h \ libsrc/minc_basic.h \ libsrc/minc_config.h \ libsrc/minc_error.h \ libsrc/minc_private.h \ libsrc/minc_routines.h \ libsrc/minc_structures.h \ libsrc/minc_useful.h \ libsrc/minc_varlists.h \ libsrc/type_limits.h \ libsrc/hdf_convenience.h \ progs/Proglib/convert_origin_to_start.h \ progs/Proglib/minc_def.h \ progs/minccalc/errx.h \ progs/minccalc/node.h \ progs/minccalc/gram.h \ progs/mincmorph/kernel_io.h \ progs/mincmorph/kernel_ops.h \ progs/mincresample/mincresample.h \ progs/mincreshape/mincreshape.h \ progs/mincsample/mt19937ar.h \ libsrc2/minc2_private.h \ progs/mincdump/mincdump.h \ progs/mincdump/dumplib.h \ progs/mincdump/vardata.h \ progs/mincgen/generic.h \ progs/mincgen/genlib.h \ progs/mincgen/ncgen.h \ progs/mincgen/ncgentab.h \ conversion/ecattominc/ecat_file.h \ conversion/ecattominc/machine_indep.h \ conversion/ecattominc/ecat_header_definition.h \ conversion/minctoecat/ecat_write.h \ conversion/minctoecat/machine_indep.h \ conversion/nifti1/nifti1.h \ conversion/nifti1/nifti1_io.h \ conversion/nifti1/nifti1_local.h \ conversion/nifti1/znzlib.h \ conversion/nifti1/analyze75.h \ conversion/dcm2mnc/acr_element_defs.h \ conversion/dcm2mnc/dcm2mnc.h \ conversion/dcm2mnc/dicom_read.h \ conversion/dcm2mnc/dicom_to_minc.h \ conversion/dcm2mnc/ext_element_defs.h \ conversion/dcm2mnc/minc_file.h \ conversion/dcm2mnc/progress.h \ conversion/dcm2mnc/siemens_to_dicom.h \ conversion/dcm2mnc/siemens_header_defs.h \ conversion/dcm2mnc/siemens_header_table.h \ conversion/dcm2mnc/spi_element_defs.h \ conversion/dcm2mnc/string_to_filename.h \ conversion/dcm2mnc/pms_element_defs.h \ conversion/dcm2mnc/gems_element_defs.h \ conversion/vff2mnc/vff2mnc.h if ACR_NEMA_TOOLS include_HEADERS += conversion/Acr_nema/acr_nema.h include_acr_nemadir = $(includedir)/acr_nema include_acr_nema_HEADERS = \ conversion/Acr_nema/acr_nema/acr_io.h \ conversion/Acr_nema/acr_nema/dicom_client_routines.h \ conversion/Acr_nema/acr_nema/dicom_network.h \ conversion/Acr_nema/acr_nema/element.h \ conversion/Acr_nema/acr_nema/file_io.h \ conversion/Acr_nema/acr_nema/group.h \ conversion/Acr_nema/acr_nema/message.h \ conversion/Acr_nema/acr_nema/value_repr.h else # # If not installing the full ACR/NEMA package, just add these headers to # list of headers not to be installed. # noinst_HEADERS += \ conversion/Acr_nema/acr_nema.h \ conversion/Acr_nema/acr_nema/acr_io.h \ conversion/Acr_nema/acr_nema/dicom_client_routines.h \ conversion/Acr_nema/acr_nema/dicom_network.h \ conversion/Acr_nema/acr_nema/element.h \ conversion/Acr_nema/acr_nema/file_io.h \ conversion/Acr_nema/acr_nema/group.h \ conversion/Acr_nema/acr_nema/message.h \ conversion/Acr_nema/acr_nema/value_repr.h endif # Libraries which must be built and installed. # lib_LTLIBRARIES = libminc2.la libvolume_io2.la # Conditionally install the libacr_nema.la library. It must always be # built even if it is not installed. # if ACR_NEMA_TOOLS lib_LTLIBRARIES += libacr_nema.la else noinst_LTLIBRARIES = libacr_nema.la endif # Scripts we install: sh or perl. # dist_bin_SCRIPTS = \ progs/mincdiff/mincdiff \ progs/mincedit/mincedit \ progs/mincheader/mincheader \ progs/mincview/mincview # Scripts that we process (to add version #s) before install bin_SCRIPTS = \ progs/minccomplete/minccomplete \ progs/minchistory/minchistory \ progs/mincpik/mincpik \ progs/xfm/xfmflip # Programs we build and install. # bin_PROGRAMS = \ voxeltoworld \ worldtovoxel \ minc_modify_header \ mincaverage \ mincblob \ minccalc \ minccmp \ mincconcat \ minccopy \ mincexpand \ mincextract \ mincgen \ mincinfo \ minclookup \ mincmakescalar \ mincmakevector \ mincmath \ mincmorph \ mincresample \ mincreshape \ mincsample \ mincstats \ minctoraw \ invert_raw_image \ mincwindow \ rawtominc \ transformtags \ xfm2def \ xfmconcat \ xfminvert \ mincconvert \ mincdump \ ecattominc \ minctoecat \ mnc2nii \ nii2mnc \ upet2mnc \ dcm2mnc \ vff2mnc if ACR_NEMA_TOOLS bin_PROGRAMS += \ acr_test \ dump_acr_nema \ extract_acr_nema \ read_acr_nema \ dicom_test \ copy_acr_nema \ byte_swap \ extract endif noinst_PROGRAMS = \ mincexample1 \ mincexample2 LDADD = libvolume_io2.la libminc2.la EXTRA_DIST = \ $(m4_files) \ $(ezMINC_files) \ progs/minccomplete/minccomplete.in \ progs/minchistory/minchistory.in \ progs/mincpik/mincpik.in \ progs/xfm/xfmflip.in \ libsrc/strdup.c \ epm-header.in \ libsrc/config.h.msvc-win32 \ Makefile.msvc-win32 \ conversion/Acr_nema/dicom.txt \ INSTALL.minc \ CMakeLists.txt \ config.h.cmake \ UseMINC2.cmake.in \ MINC2Config.cmake.in \ progs/CMakeLists.txt \ conversion/CMakeLists.txt \ cmake-modules/FindHDF5.cmake \ cmake-modules/FindNETCDF.cmake m4_files = \ m4/mni_REQUIRE_LIB.m4 \ m4/smr_WITH_BUILD_PATH.m4 ezMINC_files = \ ezminc/examples/volume_msq_dist.cpp ezminc/examples/CMakeLists.txt ezminc/examples/fuzzy_volume_similarity.cpp ezminc/examples/trilinear_resample.cpp ezminc/examples/volume_avg.cpp ezminc/examples/volume_gtc_similarity.cpp ezminc/examples/volume_similarity.cpp ezminc/minc_1_simple_rw.cpp ezminc/minc_1_simple_rw.h ezminc/minc_io_4d_volume.h ezminc/minc_io_fixed_vector.h ezminc/minc_io_simple_volume.h ezminc/tests/minc_rw_test2.cpp ezminc/tests/minc_rw_test_4d.cpp ezminc/tests/minc_rw_test_simple.cpp ezminc/tests/CMakeLists.txt ezminc/tests/ezminc_rw_test.cpp ezminc/tests/ezminc_stats.cpp ezminc/minc_1_simple.h ezminc/CMakeLists.txt ezminc/minc_1_rw.cpp ezminc/minc_1_rw.h ezminc/minc_io_exceptions.h voxeltoworld_SOURCES = progs/coordinates/voxeltoworld.c worldtovoxel_SOURCES = progs/coordinates/worldtovoxel.c minc_modify_header_SOURCES = progs/minc_modify_header/minc_modify_header.c mincaverage_SOURCES = progs/mincaverage/mincaverage.c mincblob_SOURCES = progs/mincblob/mincblob.c minccalc_CFLAGS = -Iprogs/minccalc -I$(srcdir)/progs/minccalc minccalc_SOURCES = \ progs/minccalc/minccalc.c \ progs/minccalc/gram.y \ progs/minccalc/eval.c \ progs/minccalc/ident.c \ progs/minccalc/lex.l \ progs/minccalc/node.c \ progs/minccalc/optim.c \ progs/minccalc/scalar.c \ progs/minccalc/sym.c \ progs/minccalc/vector.c mincconcat_SOURCES = progs/mincconcat/mincconcat.c minccopy_SOURCES = progs/minccopy/minccopy.c minccmp_SOURCES = progs/minccmp/minccmp.c mincexample1_SOURCES = progs/mincexample/mincexample1.c mincexample2_SOURCES = progs/mincexample/mincexample2.c mincexpand_SOURCES = progs/mincexpand/mincexpand.c mincextract_SOURCES = progs/mincextract/mincextract.c mincgen_SOURCES = \ progs/mincgen/escapes.c \ progs/mincgen/genlib.c \ progs/mincgen/getfill.c \ progs/mincgen/init.c \ progs/mincgen/load.c \ progs/mincgen/main.c \ progs/mincgen/ncgentab.y \ progs/mincgen/ncgenyy.l mincinfo_SOURCES = progs/mincinfo/mincinfo.c minclookup_SOURCES = progs/minclookup/minclookup.c mincmakescalar_SOURCES = progs/mincmakescalar/mincmakescalar.c mincmakevector_SOURCES = progs/mincmakevector/mincmakevector.c mincmath_SOURCES = progs/mincmath/mincmath.c mincmorph_CFLAGS = -Iprogs/mincmorph -I$(srcdir)/progs/mincmorph mincmorph_SOURCES = \ progs/mincmorph/mincmorph.c \ progs/mincmorph/kernel_io.c \ progs/mincmorph/kernel_ops.c mincsample_CFLAGS = -Iprogs/mincsample -I$(srcdir)/progs/mincsample mincresample_SOURCES = \ progs/mincresample/mincresample.c \ progs/mincresample/resample_volumes.c \ progs/Proglib/convert_origin_to_start.c mincreshape_SOURCES = \ progs/mincreshape/mincreshape.c \ progs/mincreshape/copy_data.c mincsample_SOURCES = \ progs/mincsample/mincsample.c \ progs/mincsample/mt19937ar.c mincstats_SOURCES = progs/mincstats/mincstats.c minctoraw_SOURCES = progs/minctoraw/minctoraw.c invert_raw_image_SOURCES = progs/mincview/invert_raw_image.c mincwindow_SOURCES = progs/mincwindow/mincwindow.c rawtominc_SOURCES = \ progs/rawtominc/rawtominc.c \ progs/Proglib/convert_origin_to_start.c transformtags_SOURCES = progs/xfm/transformtags.c xfm2def_SOURCES = progs/xfm/xfm2def.c xfmconcat_SOURCES = progs/xfm/xfmconcat.c xfminvert_SOURCES = progs/xfm/xfminvert.c mincconvert_SOURCES = progs/mincconvert/mincconvert.c mincdump_SOURCES = \ progs/mincdump/mincdump.c \ progs/mincdump/vardata.c \ progs/mincdump/dumplib.c ecattominc_SOURCES = \ conversion/ecattominc/ecattominc.c \ conversion/ecattominc/insertblood.c \ conversion/ecattominc/ecat_file.c \ conversion/ecattominc/machine_indep.c minctoecat_SOURCES = \ conversion/minctoecat/minctoecat.c \ conversion/minctoecat/ecat_write.c \ conversion/minctoecat/machine_indep.c nii2mnc_SOURCES = \ conversion/nifti1/nii2mnc.c \ conversion/nifti1/nifti1_io.c \ conversion/nifti1/znzlib.c mnc2nii_SOURCES = \ conversion/nifti1/mnc2nii.c \ conversion/nifti1/nifti1_io.c \ conversion/nifti1/znzlib.c upet2mnc_SOURCES = \ conversion/micropet/upet2mnc.c dcm2mnc_LDADD = libacr_nema.la $(LDADD) dcm2mnc_SOURCES = \ conversion/dcm2mnc/dcm2mnc.c \ conversion/dcm2mnc/dicom_to_minc.c \ conversion/dcm2mnc/siemens_to_dicom.c \ conversion/dcm2mnc/dicom_read.c \ conversion/dcm2mnc/minc_file.c \ conversion/dcm2mnc/progress.c \ conversion/dcm2mnc/string_to_filename.c vff2mnc_SOURCES = \ conversion/vff2mnc/vff2mnc.c acr_test_LDADD = libacr_nema.la acr_test_SOURCES = conversion/Acr_nema/acr_test.c dump_acr_nema_LDADD = libacr_nema.la dump_acr_nema_SOURCES = conversion/Acr_nema/dump_acr_nema.c extract_acr_nema_LDADD = libacr_nema.la extract_acr_nema_SOURCES = conversion/Acr_nema/extract_acr_nema.c read_acr_nema_LDADD = libacr_nema.la read_acr_nema_SOURCES = conversion/Acr_nema/read_acr_nema.c dicom_test_LDADD = libacr_nema.la dicom_test_SOURCES = conversion/Acr_nema/dicom_test.c copy_acr_nema_LDADD = libacr_nema.la copy_acr_nema_SOURCES = conversion/Acr_nema/copy_acr_nema.c extract_SOURCES = conversion/image_filters/extract.c byte_swap_SOURCES = conversion/image_filters/byte_swap.c libminc2_la_LDFLAGS = -version-info 3:0:0 libminc2_la_SOURCES = \ libsrc/ParseArgv.c \ libsrc/read_file_names.c \ libsrc/dim_conversion.c \ libsrc/image_conversion.c \ libsrc/minc_convenience.c \ libsrc/minc_error.c \ libsrc/nd_loop.c \ libsrc/netcdf_convenience.c \ libsrc/time_stamp.c \ libsrc/value_conversion.c \ libsrc/voxel_loop.c \ libsrc/hdf_convenience.c \ libsrc/minc_compat.c \ libsrc/minc_simple.c if MINC2 libminc2_la_SOURCES += \ libsrc2/convert.c \ libsrc2/datatype.c \ libsrc2/dimension.c \ libsrc2/free.c \ libsrc2/grpattr.c \ libsrc2/hyper.c \ libsrc2/label.c \ libsrc2/m2util.c \ libsrc2/record.c \ libsrc2/slice.c \ libsrc2/valid.c \ libsrc2/volprops.c \ libsrc2/volume.c else EXTRA_DIST += \ libsrc2/convert.c \ libsrc2/datatype.c \ libsrc2/dimension.c \ libsrc2/free.c \ libsrc2/grpattr.c \ libsrc2/hyper.c \ libsrc2/label.c \ libsrc2/m2util.c \ libsrc2/record.c \ libsrc2/slice.c \ libsrc2/valid.c \ libsrc2/volprops.c \ libsrc2/volume.c endif libvolume_io2_la_LDFLAGS = -version-info 3:0:0 libvolume_io2_la_SOURCES = \ volume_io/Geometry/colour.c \ volume_io/Geometry/colour_def.c \ volume_io/Geometry/gaussian.c \ volume_io/Geometry/inverse.c \ volume_io/Geometry/newton.c \ volume_io/Geometry/points.c \ volume_io/Geometry/splines.c \ volume_io/Geometry/tensors.c \ volume_io/Geometry/transforms.c \ volume_io/MNI_formats/gen_xf_io.c \ volume_io/MNI_formats/gen_xfs.c \ volume_io/MNI_formats/grid_transforms.c \ volume_io/MNI_formats/mni_io.c \ volume_io/MNI_formats/tag_points.c \ volume_io/MNI_formats/thin_plate_spline.c \ volume_io/Prog_utils/alloc.c \ volume_io/Prog_utils/alloc_check.c \ volume_io/Prog_utils/arrays.c \ volume_io/Prog_utils/files.c \ volume_io/Prog_utils/print.c \ volume_io/Prog_utils/progress.c \ volume_io/Prog_utils/string.c \ volume_io/Prog_utils/time.c \ volume_io/Volumes/evaluate.c \ volume_io/Volumes/get_hyperslab.c \ volume_io/Volumes/input_free.c \ volume_io/Volumes/input_mnc.c \ volume_io/Volumes/input_volume.c \ volume_io/Volumes/multidim_arrays.c \ volume_io/Volumes/output_mnc.c \ volume_io/Volumes/output_volume.c \ volume_io/Volumes/set_hyperslab.c \ volume_io/Volumes/volume_cache.c \ volume_io/Volumes/volumes.c libacr_nema_la_SOURCES = \ conversion/Acr_nema/acr_io.c \ conversion/Acr_nema/dicom_client_routines.c \ conversion/Acr_nema/dicom_network.c \ conversion/Acr_nema/element.c \ conversion/Acr_nema/file_io.c \ conversion/Acr_nema/globals.c \ conversion/Acr_nema/group.c \ conversion/Acr_nema/message.c \ conversion/Acr_nema/value_repr.c # MAN pages go here. The "dist_" prefix signals that they # are to be included in source distribution. # dist_man1_MANS = \ progs/coordinates/voxeltoworld.man1 \ progs/minc_modify_header/minc_modify_header.man1 \ progs/mincaverage/mincaverage.man1 \ progs/mincblob/mincblob.man1 \ progs/minccalc/minccalc.man1 \ progs/minccomplete/minccomplete.man1 \ progs/mincconcat/mincconcat.man1 \ progs/minccmp/minccmp.man1 \ progs/minccopy/minccopy.man1 \ progs/mincdiff/mincdiff.man1 \ progs/mincedit/mincedit.man1 \ progs/mincexpand/mincexpand.man1 \ progs/mincextract/mincextract.man1 \ progs/mincgen/mincgen.man1 \ progs/mincheader/mincheader.man1 \ progs/minchistory/minchistory.man1 \ progs/mincinfo/mincinfo.man1 \ progs/minclookup/minclookup.man1 \ progs/mincmakescalar/mincmakescalar.man1 \ progs/mincmakevector/mincmakevector.man1 \ progs/mincmath/mincmath.man1 \ progs/mincpik/mincpik.man1 \ progs/mincresample/mincresample.man1 \ progs/mincreshape/mincreshape.man1 \ progs/mincstats/mincstats.man1 \ progs/minctoraw/minctoraw.man1 \ progs/mincview/invert_raw_image.man1 \ progs/mincview/mincview.man1 \ progs/mincwindow/mincwindow.man1 \ progs/rawtominc/rawtominc.man1 \ progs/xfm/transformtags.man1 \ progs/xfm/xfm2def.man1 \ progs/xfm/xfmconcat.man1 \ progs/xfm/xfminvert.man1 \ progs/xfm/xfmflip.man1 \ progs/mincconvert/mincconvert.man1 \ conversion/ecattominc/ecattominc.man1 \ conversion/minctoecat/minctoecat.man1 \ conversion/nifti1/nii2mnc.man1 \ conversion/nifti1/mnc2nii.man1 \ conversion/micropet/upet2mnc.man1 \ conversion/dcm2mnc/dcm2mnc.man1 \ conversion/vff2mnc/vff2mnc.man1 dist_man3_MANS = libsrc/ParseArgv.man3 minc-2.2.00/Makefile.in0000644000265600003100000052525712030114714011515 00000000000000# Makefile.in generated by automake 1.10.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @MINC2_TRUE@am__append_1 = libsrc2/test @MINC2_TRUE@am__append_2 = -I$(top_srcdir)/libsrc2 @ACR_NEMA_TOOLS_TRUE@am__append_3 = conversion/Acr_nema/acr_nema.h # # If not installing the full ACR/NEMA package, just add these headers to # list of headers not to be installed. # @ACR_NEMA_TOOLS_FALSE@am__append_4 = \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/acr_io.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/dicom_client_routines.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/dicom_network.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/element.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/file_io.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/group.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/message.h \ @ACR_NEMA_TOOLS_FALSE@ conversion/Acr_nema/acr_nema/value_repr.h # Conditionally install the libacr_nema.la library. It must always be # built even if it is not installed. # @ACR_NEMA_TOOLS_TRUE@am__append_5 = libacr_nema.la bin_PROGRAMS = voxeltoworld$(EXEEXT) worldtovoxel$(EXEEXT) \ minc_modify_header$(EXEEXT) mincaverage$(EXEEXT) \ mincblob$(EXEEXT) minccalc$(EXEEXT) minccmp$(EXEEXT) \ mincconcat$(EXEEXT) minccopy$(EXEEXT) mincexpand$(EXEEXT) \ mincextract$(EXEEXT) mincgen$(EXEEXT) mincinfo$(EXEEXT) \ minclookup$(EXEEXT) mincmakescalar$(EXEEXT) \ mincmakevector$(EXEEXT) mincmath$(EXEEXT) mincmorph$(EXEEXT) \ mincresample$(EXEEXT) mincreshape$(EXEEXT) mincsample$(EXEEXT) \ mincstats$(EXEEXT) minctoraw$(EXEEXT) \ invert_raw_image$(EXEEXT) mincwindow$(EXEEXT) \ rawtominc$(EXEEXT) transformtags$(EXEEXT) xfm2def$(EXEEXT) \ xfmconcat$(EXEEXT) xfminvert$(EXEEXT) mincconvert$(EXEEXT) \ mincdump$(EXEEXT) ecattominc$(EXEEXT) minctoecat$(EXEEXT) \ mnc2nii$(EXEEXT) nii2mnc$(EXEEXT) upet2mnc$(EXEEXT) \ dcm2mnc$(EXEEXT) vff2mnc$(EXEEXT) $(am__EXEEXT_1) @ACR_NEMA_TOOLS_TRUE@am__append_6 = \ @ACR_NEMA_TOOLS_TRUE@ acr_test \ @ACR_NEMA_TOOLS_TRUE@ dump_acr_nema \ @ACR_NEMA_TOOLS_TRUE@ extract_acr_nema \ @ACR_NEMA_TOOLS_TRUE@ read_acr_nema \ @ACR_NEMA_TOOLS_TRUE@ dicom_test \ @ACR_NEMA_TOOLS_TRUE@ copy_acr_nema \ @ACR_NEMA_TOOLS_TRUE@ byte_swap \ @ACR_NEMA_TOOLS_TRUE@ extract noinst_PROGRAMS = mincexample1$(EXEEXT) mincexample2$(EXEEXT) @MINC2_TRUE@am__append_7 = \ @MINC2_TRUE@ libsrc2/convert.c \ @MINC2_TRUE@ libsrc2/datatype.c \ @MINC2_TRUE@ libsrc2/dimension.c \ @MINC2_TRUE@ libsrc2/free.c \ @MINC2_TRUE@ libsrc2/grpattr.c \ @MINC2_TRUE@ libsrc2/hyper.c \ @MINC2_TRUE@ libsrc2/label.c \ @MINC2_TRUE@ libsrc2/m2util.c \ @MINC2_TRUE@ libsrc2/record.c \ @MINC2_TRUE@ libsrc2/slice.c \ @MINC2_TRUE@ libsrc2/valid.c \ @MINC2_TRUE@ libsrc2/volprops.c \ @MINC2_TRUE@ libsrc2/volume.c @MINC2_FALSE@am__append_8 = \ @MINC2_FALSE@ libsrc2/convert.c \ @MINC2_FALSE@ libsrc2/datatype.c \ @MINC2_FALSE@ libsrc2/dimension.c \ @MINC2_FALSE@ libsrc2/free.c \ @MINC2_FALSE@ libsrc2/grpattr.c \ @MINC2_FALSE@ libsrc2/hyper.c \ @MINC2_FALSE@ libsrc2/label.c \ @MINC2_FALSE@ libsrc2/m2util.c \ @MINC2_FALSE@ libsrc2/record.c \ @MINC2_FALSE@ libsrc2/slice.c \ @MINC2_FALSE@ libsrc2/valid.c \ @MINC2_FALSE@ libsrc2/volprops.c \ @MINC2_FALSE@ libsrc2/volume.c subdir = . DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \ $(am__include_acr_nema_HEADERS_DIST) \ $(am__noinst_HEADERS_DIST) $(dist_bin_SCRIPTS) \ $(dist_man1_MANS) $(dist_man3_MANS) \ $(include_volume_io_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/epm-header.in $(top_srcdir)/configure \ $(top_srcdir)/progs/minccomplete/minccomplete.in \ $(top_srcdir)/progs/minchistory/minchistory.in \ $(top_srcdir)/progs/mincpik/mincpik.in \ $(top_srcdir)/progs/xfm/xfmflip.in AUTHORS COPYING ChangeLog \ INSTALL NEWS ac_config_aux/compile ac_config_aux/config.guess \ ac_config_aux/config.sub ac_config_aux/depcomp \ ac_config_aux/install-sh ac_config_aux/ltmain.sh \ ac_config_aux/missing ac_config_aux/ylwrap \ progs/minccalc/gram.c progs/minccalc/gram.h \ progs/minccalc/lex.c progs/mincgen/ncgentab.c \ progs/mincgen/ncgentab.h progs/mincgen/ncgenyy.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mni_REQUIRE_LIB.m4 \ $(top_srcdir)/m4/smr_WITH_BUILD_PATH.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = epm-header progs/xfm/xfmflip \ progs/minccomplete/minccomplete progs/minchistory/minchistory \ progs/mincpik/mincpik am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" \ "$(DESTDIR)$(includedir)" "$(DESTDIR)$(include_acr_nemadir)" \ "$(DESTDIR)$(include_volume_iodir)" libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) libacr_nema_la_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_libacr_nema_la_OBJECTS = conversion/Acr_nema/acr_io.lo \ conversion/Acr_nema/dicom_client_routines.lo \ conversion/Acr_nema/dicom_network.lo \ conversion/Acr_nema/element.lo conversion/Acr_nema/file_io.lo \ conversion/Acr_nema/globals.lo conversion/Acr_nema/group.lo \ conversion/Acr_nema/message.lo \ conversion/Acr_nema/value_repr.lo libacr_nema_la_OBJECTS = $(am_libacr_nema_la_OBJECTS) @ACR_NEMA_TOOLS_FALSE@am_libacr_nema_la_rpath = @ACR_NEMA_TOOLS_TRUE@am_libacr_nema_la_rpath = -rpath $(libdir) libminc2_la_LIBADD = am__libminc2_la_SOURCES_DIST = libsrc/ParseArgv.c \ libsrc/read_file_names.c libsrc/dim_conversion.c \ libsrc/image_conversion.c libsrc/minc_convenience.c \ libsrc/minc_error.c libsrc/nd_loop.c \ libsrc/netcdf_convenience.c libsrc/time_stamp.c \ libsrc/value_conversion.c libsrc/voxel_loop.c \ libsrc/hdf_convenience.c libsrc/minc_compat.c \ libsrc/minc_simple.c libsrc2/convert.c libsrc2/datatype.c \ libsrc2/dimension.c libsrc2/free.c libsrc2/grpattr.c \ libsrc2/hyper.c libsrc2/label.c libsrc2/m2util.c \ libsrc2/record.c libsrc2/slice.c libsrc2/valid.c \ libsrc2/volprops.c libsrc2/volume.c @MINC2_TRUE@am__objects_1 = libsrc2/convert.lo libsrc2/datatype.lo \ @MINC2_TRUE@ libsrc2/dimension.lo libsrc2/free.lo \ @MINC2_TRUE@ libsrc2/grpattr.lo libsrc2/hyper.lo \ @MINC2_TRUE@ libsrc2/label.lo libsrc2/m2util.lo \ @MINC2_TRUE@ libsrc2/record.lo libsrc2/slice.lo \ @MINC2_TRUE@ libsrc2/valid.lo libsrc2/volprops.lo \ @MINC2_TRUE@ libsrc2/volume.lo am_libminc2_la_OBJECTS = libsrc/ParseArgv.lo libsrc/read_file_names.lo \ libsrc/dim_conversion.lo libsrc/image_conversion.lo \ libsrc/minc_convenience.lo libsrc/minc_error.lo \ libsrc/nd_loop.lo libsrc/netcdf_convenience.lo \ libsrc/time_stamp.lo libsrc/value_conversion.lo \ libsrc/voxel_loop.lo libsrc/hdf_convenience.lo \ libsrc/minc_compat.lo libsrc/minc_simple.lo $(am__objects_1) libminc2_la_OBJECTS = $(am_libminc2_la_OBJECTS) libminc2_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libminc2_la_LDFLAGS) $(LDFLAGS) -o $@ libvolume_io2_la_LIBADD = am_libvolume_io2_la_OBJECTS = volume_io/Geometry/colour.lo \ volume_io/Geometry/colour_def.lo \ volume_io/Geometry/gaussian.lo volume_io/Geometry/inverse.lo \ volume_io/Geometry/newton.lo volume_io/Geometry/points.lo \ volume_io/Geometry/splines.lo volume_io/Geometry/tensors.lo \ volume_io/Geometry/transforms.lo \ volume_io/MNI_formats/gen_xf_io.lo \ volume_io/MNI_formats/gen_xfs.lo \ volume_io/MNI_formats/grid_transforms.lo \ volume_io/MNI_formats/mni_io.lo \ volume_io/MNI_formats/tag_points.lo \ volume_io/MNI_formats/thin_plate_spline.lo \ volume_io/Prog_utils/alloc.lo \ volume_io/Prog_utils/alloc_check.lo \ volume_io/Prog_utils/arrays.lo volume_io/Prog_utils/files.lo \ volume_io/Prog_utils/print.lo volume_io/Prog_utils/progress.lo \ volume_io/Prog_utils/string.lo volume_io/Prog_utils/time.lo \ volume_io/Volumes/evaluate.lo \ volume_io/Volumes/get_hyperslab.lo \ volume_io/Volumes/input_free.lo volume_io/Volumes/input_mnc.lo \ volume_io/Volumes/input_volume.lo \ volume_io/Volumes/multidim_arrays.lo \ volume_io/Volumes/output_mnc.lo \ volume_io/Volumes/output_volume.lo \ volume_io/Volumes/set_hyperslab.lo \ volume_io/Volumes/volume_cache.lo volume_io/Volumes/volumes.lo libvolume_io2_la_OBJECTS = $(am_libvolume_io2_la_OBJECTS) libvolume_io2_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libvolume_io2_la_LDFLAGS) $(LDFLAGS) -o $@ @ACR_NEMA_TOOLS_TRUE@am__EXEEXT_1 = acr_test$(EXEEXT) \ @ACR_NEMA_TOOLS_TRUE@ dump_acr_nema$(EXEEXT) \ @ACR_NEMA_TOOLS_TRUE@ extract_acr_nema$(EXEEXT) \ @ACR_NEMA_TOOLS_TRUE@ read_acr_nema$(EXEEXT) \ @ACR_NEMA_TOOLS_TRUE@ dicom_test$(EXEEXT) \ @ACR_NEMA_TOOLS_TRUE@ copy_acr_nema$(EXEEXT) byte_swap$(EXEEXT) \ @ACR_NEMA_TOOLS_TRUE@ extract$(EXEEXT) binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_acr_test_OBJECTS = conversion/Acr_nema/acr_test.$(OBJEXT) acr_test_OBJECTS = $(am_acr_test_OBJECTS) acr_test_DEPENDENCIES = libacr_nema.la am_byte_swap_OBJECTS = conversion/image_filters/byte_swap.$(OBJEXT) byte_swap_OBJECTS = $(am_byte_swap_OBJECTS) byte_swap_LDADD = $(LDADD) byte_swap_DEPENDENCIES = libvolume_io2.la libminc2.la am_copy_acr_nema_OBJECTS = \ conversion/Acr_nema/copy_acr_nema.$(OBJEXT) copy_acr_nema_OBJECTS = $(am_copy_acr_nema_OBJECTS) copy_acr_nema_DEPENDENCIES = libacr_nema.la am_dcm2mnc_OBJECTS = conversion/dcm2mnc/dcm2mnc.$(OBJEXT) \ conversion/dcm2mnc/dicom_to_minc.$(OBJEXT) \ conversion/dcm2mnc/siemens_to_dicom.$(OBJEXT) \ conversion/dcm2mnc/dicom_read.$(OBJEXT) \ conversion/dcm2mnc/minc_file.$(OBJEXT) \ conversion/dcm2mnc/progress.$(OBJEXT) \ conversion/dcm2mnc/string_to_filename.$(OBJEXT) dcm2mnc_OBJECTS = $(am_dcm2mnc_OBJECTS) dcm2mnc_DEPENDENCIES = libacr_nema.la $(LDADD) am_dicom_test_OBJECTS = conversion/Acr_nema/dicom_test.$(OBJEXT) dicom_test_OBJECTS = $(am_dicom_test_OBJECTS) dicom_test_DEPENDENCIES = libacr_nema.la am_dump_acr_nema_OBJECTS = \ conversion/Acr_nema/dump_acr_nema.$(OBJEXT) dump_acr_nema_OBJECTS = $(am_dump_acr_nema_OBJECTS) dump_acr_nema_DEPENDENCIES = libacr_nema.la am_ecattominc_OBJECTS = conversion/ecattominc/ecattominc.$(OBJEXT) \ conversion/ecattominc/insertblood.$(OBJEXT) \ conversion/ecattominc/ecat_file.$(OBJEXT) \ conversion/ecattominc/machine_indep.$(OBJEXT) ecattominc_OBJECTS = $(am_ecattominc_OBJECTS) ecattominc_LDADD = $(LDADD) ecattominc_DEPENDENCIES = libvolume_io2.la libminc2.la am_extract_OBJECTS = conversion/image_filters/extract.$(OBJEXT) extract_OBJECTS = $(am_extract_OBJECTS) extract_LDADD = $(LDADD) extract_DEPENDENCIES = libvolume_io2.la libminc2.la am_extract_acr_nema_OBJECTS = \ conversion/Acr_nema/extract_acr_nema.$(OBJEXT) extract_acr_nema_OBJECTS = $(am_extract_acr_nema_OBJECTS) extract_acr_nema_DEPENDENCIES = libacr_nema.la am_invert_raw_image_OBJECTS = \ progs/mincview/invert_raw_image.$(OBJEXT) invert_raw_image_OBJECTS = $(am_invert_raw_image_OBJECTS) invert_raw_image_LDADD = $(LDADD) invert_raw_image_DEPENDENCIES = libvolume_io2.la libminc2.la am_minc_modify_header_OBJECTS = \ progs/minc_modify_header/minc_modify_header.$(OBJEXT) minc_modify_header_OBJECTS = $(am_minc_modify_header_OBJECTS) minc_modify_header_LDADD = $(LDADD) minc_modify_header_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincaverage_OBJECTS = progs/mincaverage/mincaverage.$(OBJEXT) mincaverage_OBJECTS = $(am_mincaverage_OBJECTS) mincaverage_LDADD = $(LDADD) mincaverage_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincblob_OBJECTS = progs/mincblob/mincblob.$(OBJEXT) mincblob_OBJECTS = $(am_mincblob_OBJECTS) mincblob_LDADD = $(LDADD) mincblob_DEPENDENCIES = libvolume_io2.la libminc2.la am_minccalc_OBJECTS = progs/minccalc/minccalc-minccalc.$(OBJEXT) \ progs/minccalc/minccalc-gram.$(OBJEXT) \ progs/minccalc/minccalc-eval.$(OBJEXT) \ progs/minccalc/minccalc-ident.$(OBJEXT) \ progs/minccalc/minccalc-lex.$(OBJEXT) \ progs/minccalc/minccalc-node.$(OBJEXT) \ progs/minccalc/minccalc-optim.$(OBJEXT) \ progs/minccalc/minccalc-scalar.$(OBJEXT) \ progs/minccalc/minccalc-sym.$(OBJEXT) \ progs/minccalc/minccalc-vector.$(OBJEXT) minccalc_OBJECTS = $(am_minccalc_OBJECTS) minccalc_LDADD = $(LDADD) minccalc_DEPENDENCIES = libvolume_io2.la libminc2.la minccalc_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(minccalc_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_minccmp_OBJECTS = progs/minccmp/minccmp.$(OBJEXT) minccmp_OBJECTS = $(am_minccmp_OBJECTS) minccmp_LDADD = $(LDADD) minccmp_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincconcat_OBJECTS = progs/mincconcat/mincconcat.$(OBJEXT) mincconcat_OBJECTS = $(am_mincconcat_OBJECTS) mincconcat_LDADD = $(LDADD) mincconcat_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincconvert_OBJECTS = progs/mincconvert/mincconvert.$(OBJEXT) mincconvert_OBJECTS = $(am_mincconvert_OBJECTS) mincconvert_LDADD = $(LDADD) mincconvert_DEPENDENCIES = libvolume_io2.la libminc2.la am_minccopy_OBJECTS = progs/minccopy/minccopy.$(OBJEXT) minccopy_OBJECTS = $(am_minccopy_OBJECTS) minccopy_LDADD = $(LDADD) minccopy_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincdump_OBJECTS = progs/mincdump/mincdump.$(OBJEXT) \ progs/mincdump/vardata.$(OBJEXT) \ progs/mincdump/dumplib.$(OBJEXT) mincdump_OBJECTS = $(am_mincdump_OBJECTS) mincdump_LDADD = $(LDADD) mincdump_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincexample1_OBJECTS = progs/mincexample/mincexample1.$(OBJEXT) mincexample1_OBJECTS = $(am_mincexample1_OBJECTS) mincexample1_LDADD = $(LDADD) mincexample1_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincexample2_OBJECTS = progs/mincexample/mincexample2.$(OBJEXT) mincexample2_OBJECTS = $(am_mincexample2_OBJECTS) mincexample2_LDADD = $(LDADD) mincexample2_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincexpand_OBJECTS = progs/mincexpand/mincexpand.$(OBJEXT) mincexpand_OBJECTS = $(am_mincexpand_OBJECTS) mincexpand_LDADD = $(LDADD) mincexpand_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincextract_OBJECTS = progs/mincextract/mincextract.$(OBJEXT) mincextract_OBJECTS = $(am_mincextract_OBJECTS) mincextract_LDADD = $(LDADD) mincextract_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincgen_OBJECTS = progs/mincgen/escapes.$(OBJEXT) \ progs/mincgen/genlib.$(OBJEXT) progs/mincgen/getfill.$(OBJEXT) \ progs/mincgen/init.$(OBJEXT) progs/mincgen/load.$(OBJEXT) \ progs/mincgen/main.$(OBJEXT) progs/mincgen/ncgentab.$(OBJEXT) \ progs/mincgen/ncgenyy.$(OBJEXT) mincgen_OBJECTS = $(am_mincgen_OBJECTS) mincgen_LDADD = $(LDADD) mincgen_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincinfo_OBJECTS = progs/mincinfo/mincinfo.$(OBJEXT) mincinfo_OBJECTS = $(am_mincinfo_OBJECTS) mincinfo_LDADD = $(LDADD) mincinfo_DEPENDENCIES = libvolume_io2.la libminc2.la am_minclookup_OBJECTS = progs/minclookup/minclookup.$(OBJEXT) minclookup_OBJECTS = $(am_minclookup_OBJECTS) minclookup_LDADD = $(LDADD) minclookup_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincmakescalar_OBJECTS = \ progs/mincmakescalar/mincmakescalar.$(OBJEXT) mincmakescalar_OBJECTS = $(am_mincmakescalar_OBJECTS) mincmakescalar_LDADD = $(LDADD) mincmakescalar_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincmakevector_OBJECTS = \ progs/mincmakevector/mincmakevector.$(OBJEXT) mincmakevector_OBJECTS = $(am_mincmakevector_OBJECTS) mincmakevector_LDADD = $(LDADD) mincmakevector_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincmath_OBJECTS = progs/mincmath/mincmath.$(OBJEXT) mincmath_OBJECTS = $(am_mincmath_OBJECTS) mincmath_LDADD = $(LDADD) mincmath_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincmorph_OBJECTS = progs/mincmorph/mincmorph-mincmorph.$(OBJEXT) \ progs/mincmorph/mincmorph-kernel_io.$(OBJEXT) \ progs/mincmorph/mincmorph-kernel_ops.$(OBJEXT) mincmorph_OBJECTS = $(am_mincmorph_OBJECTS) mincmorph_LDADD = $(LDADD) mincmorph_DEPENDENCIES = libvolume_io2.la libminc2.la mincmorph_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(mincmorph_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_mincresample_OBJECTS = progs/mincresample/mincresample.$(OBJEXT) \ progs/mincresample/resample_volumes.$(OBJEXT) \ progs/Proglib/convert_origin_to_start.$(OBJEXT) mincresample_OBJECTS = $(am_mincresample_OBJECTS) mincresample_LDADD = $(LDADD) mincresample_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincreshape_OBJECTS = progs/mincreshape/mincreshape.$(OBJEXT) \ progs/mincreshape/copy_data.$(OBJEXT) mincreshape_OBJECTS = $(am_mincreshape_OBJECTS) mincreshape_LDADD = $(LDADD) mincreshape_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincsample_OBJECTS = \ progs/mincsample/mincsample-mincsample.$(OBJEXT) \ progs/mincsample/mincsample-mt19937ar.$(OBJEXT) mincsample_OBJECTS = $(am_mincsample_OBJECTS) mincsample_LDADD = $(LDADD) mincsample_DEPENDENCIES = libvolume_io2.la libminc2.la mincsample_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(mincsample_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_mincstats_OBJECTS = progs/mincstats/mincstats.$(OBJEXT) mincstats_OBJECTS = $(am_mincstats_OBJECTS) mincstats_LDADD = $(LDADD) mincstats_DEPENDENCIES = libvolume_io2.la libminc2.la am_minctoecat_OBJECTS = conversion/minctoecat/minctoecat.$(OBJEXT) \ conversion/minctoecat/ecat_write.$(OBJEXT) \ conversion/minctoecat/machine_indep.$(OBJEXT) minctoecat_OBJECTS = $(am_minctoecat_OBJECTS) minctoecat_LDADD = $(LDADD) minctoecat_DEPENDENCIES = libvolume_io2.la libminc2.la am_minctoraw_OBJECTS = progs/minctoraw/minctoraw.$(OBJEXT) minctoraw_OBJECTS = $(am_minctoraw_OBJECTS) minctoraw_LDADD = $(LDADD) minctoraw_DEPENDENCIES = libvolume_io2.la libminc2.la am_mincwindow_OBJECTS = progs/mincwindow/mincwindow.$(OBJEXT) mincwindow_OBJECTS = $(am_mincwindow_OBJECTS) mincwindow_LDADD = $(LDADD) mincwindow_DEPENDENCIES = libvolume_io2.la libminc2.la am_mnc2nii_OBJECTS = conversion/nifti1/mnc2nii.$(OBJEXT) \ conversion/nifti1/nifti1_io.$(OBJEXT) \ conversion/nifti1/znzlib.$(OBJEXT) mnc2nii_OBJECTS = $(am_mnc2nii_OBJECTS) mnc2nii_LDADD = $(LDADD) mnc2nii_DEPENDENCIES = libvolume_io2.la libminc2.la am_nii2mnc_OBJECTS = conversion/nifti1/nii2mnc.$(OBJEXT) \ conversion/nifti1/nifti1_io.$(OBJEXT) \ conversion/nifti1/znzlib.$(OBJEXT) nii2mnc_OBJECTS = $(am_nii2mnc_OBJECTS) nii2mnc_LDADD = $(LDADD) nii2mnc_DEPENDENCIES = libvolume_io2.la libminc2.la am_rawtominc_OBJECTS = progs/rawtominc/rawtominc.$(OBJEXT) \ progs/Proglib/convert_origin_to_start.$(OBJEXT) rawtominc_OBJECTS = $(am_rawtominc_OBJECTS) rawtominc_LDADD = $(LDADD) rawtominc_DEPENDENCIES = libvolume_io2.la libminc2.la am_read_acr_nema_OBJECTS = \ conversion/Acr_nema/read_acr_nema.$(OBJEXT) read_acr_nema_OBJECTS = $(am_read_acr_nema_OBJECTS) read_acr_nema_DEPENDENCIES = libacr_nema.la am_transformtags_OBJECTS = progs/xfm/transformtags.$(OBJEXT) transformtags_OBJECTS = $(am_transformtags_OBJECTS) transformtags_LDADD = $(LDADD) transformtags_DEPENDENCIES = libvolume_io2.la libminc2.la am_upet2mnc_OBJECTS = conversion/micropet/upet2mnc.$(OBJEXT) upet2mnc_OBJECTS = $(am_upet2mnc_OBJECTS) upet2mnc_LDADD = $(LDADD) upet2mnc_DEPENDENCIES = libvolume_io2.la libminc2.la am_vff2mnc_OBJECTS = conversion/vff2mnc/vff2mnc.$(OBJEXT) vff2mnc_OBJECTS = $(am_vff2mnc_OBJECTS) vff2mnc_LDADD = $(LDADD) vff2mnc_DEPENDENCIES = libvolume_io2.la libminc2.la am_voxeltoworld_OBJECTS = progs/coordinates/voxeltoworld.$(OBJEXT) voxeltoworld_OBJECTS = $(am_voxeltoworld_OBJECTS) voxeltoworld_LDADD = $(LDADD) voxeltoworld_DEPENDENCIES = libvolume_io2.la libminc2.la am_worldtovoxel_OBJECTS = progs/coordinates/worldtovoxel.$(OBJEXT) worldtovoxel_OBJECTS = $(am_worldtovoxel_OBJECTS) worldtovoxel_LDADD = $(LDADD) worldtovoxel_DEPENDENCIES = libvolume_io2.la libminc2.la am_xfm2def_OBJECTS = progs/xfm/xfm2def.$(OBJEXT) xfm2def_OBJECTS = $(am_xfm2def_OBJECTS) xfm2def_LDADD = $(LDADD) xfm2def_DEPENDENCIES = libvolume_io2.la libminc2.la am_xfmconcat_OBJECTS = progs/xfm/xfmconcat.$(OBJEXT) xfmconcat_OBJECTS = $(am_xfmconcat_OBJECTS) xfmconcat_LDADD = $(LDADD) xfmconcat_DEPENDENCIES = libvolume_io2.la libminc2.la am_xfminvert_OBJECTS = progs/xfm/xfminvert.$(OBJEXT) xfminvert_OBJECTS = $(am_xfminvert_OBJECTS) xfminvert_LDADD = $(LDADD) xfminvert_DEPENDENCIES = libvolume_io2.la libminc2.la binSCRIPT_INSTALL = $(INSTALL_SCRIPT) dist_binSCRIPT_INSTALL = $(INSTALL_SCRIPT) SCRIPTS = $(bin_SCRIPTS) $(dist_bin_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/ac_config_aux/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS) YLWRAP = $(top_srcdir)/ac_config_aux/ylwrap YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS) SOURCES = $(libacr_nema_la_SOURCES) $(libminc2_la_SOURCES) \ $(libvolume_io2_la_SOURCES) $(acr_test_SOURCES) \ $(byte_swap_SOURCES) $(copy_acr_nema_SOURCES) \ $(dcm2mnc_SOURCES) $(dicom_test_SOURCES) \ $(dump_acr_nema_SOURCES) $(ecattominc_SOURCES) \ $(extract_SOURCES) $(extract_acr_nema_SOURCES) \ $(invert_raw_image_SOURCES) $(minc_modify_header_SOURCES) \ $(mincaverage_SOURCES) $(mincblob_SOURCES) $(minccalc_SOURCES) \ $(minccmp_SOURCES) $(mincconcat_SOURCES) \ $(mincconvert_SOURCES) $(minccopy_SOURCES) $(mincdump_SOURCES) \ $(mincexample1_SOURCES) $(mincexample2_SOURCES) \ $(mincexpand_SOURCES) $(mincextract_SOURCES) \ $(mincgen_SOURCES) $(mincinfo_SOURCES) $(minclookup_SOURCES) \ $(mincmakescalar_SOURCES) $(mincmakevector_SOURCES) \ $(mincmath_SOURCES) $(mincmorph_SOURCES) \ $(mincresample_SOURCES) $(mincreshape_SOURCES) \ $(mincsample_SOURCES) $(mincstats_SOURCES) \ $(minctoecat_SOURCES) $(minctoraw_SOURCES) \ $(mincwindow_SOURCES) $(mnc2nii_SOURCES) $(nii2mnc_SOURCES) \ $(rawtominc_SOURCES) $(read_acr_nema_SOURCES) \ $(transformtags_SOURCES) $(upet2mnc_SOURCES) \ $(vff2mnc_SOURCES) $(voxeltoworld_SOURCES) \ $(worldtovoxel_SOURCES) $(xfm2def_SOURCES) \ $(xfmconcat_SOURCES) $(xfminvert_SOURCES) DIST_SOURCES = $(libacr_nema_la_SOURCES) \ $(am__libminc2_la_SOURCES_DIST) $(libvolume_io2_la_SOURCES) \ $(acr_test_SOURCES) $(byte_swap_SOURCES) \ $(copy_acr_nema_SOURCES) $(dcm2mnc_SOURCES) \ $(dicom_test_SOURCES) $(dump_acr_nema_SOURCES) \ $(ecattominc_SOURCES) $(extract_SOURCES) \ $(extract_acr_nema_SOURCES) $(invert_raw_image_SOURCES) \ $(minc_modify_header_SOURCES) $(mincaverage_SOURCES) \ $(mincblob_SOURCES) $(minccalc_SOURCES) $(minccmp_SOURCES) \ $(mincconcat_SOURCES) $(mincconvert_SOURCES) \ $(minccopy_SOURCES) $(mincdump_SOURCES) \ $(mincexample1_SOURCES) $(mincexample2_SOURCES) \ $(mincexpand_SOURCES) $(mincextract_SOURCES) \ $(mincgen_SOURCES) $(mincinfo_SOURCES) $(minclookup_SOURCES) \ $(mincmakescalar_SOURCES) $(mincmakevector_SOURCES) \ $(mincmath_SOURCES) $(mincmorph_SOURCES) \ $(mincresample_SOURCES) $(mincreshape_SOURCES) \ $(mincsample_SOURCES) $(mincstats_SOURCES) \ $(minctoecat_SOURCES) $(minctoraw_SOURCES) \ $(mincwindow_SOURCES) $(mnc2nii_SOURCES) $(nii2mnc_SOURCES) \ $(rawtominc_SOURCES) $(read_acr_nema_SOURCES) \ $(transformtags_SOURCES) $(upet2mnc_SOURCES) \ $(vff2mnc_SOURCES) $(voxeltoworld_SOURCES) \ $(worldtovoxel_SOURCES) $(xfm2def_SOURCES) \ $(xfmconcat_SOURCES) $(xfminvert_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive man1dir = $(mandir)/man1 man3dir = $(mandir)/man3 NROFF = nroff MANS = $(dist_man1_MANS) $(dist_man3_MANS) am__include_HEADERS_DIST = libsrc/minc.h libsrc/ParseArgv.h \ libsrc/voxel_loop.h libsrc/nd_loop.h libsrc/time_stamp.h \ libsrc/minc_compat.h volume_io/Include/volume_io.h \ libsrc2/minc2.h libsrc/minc_simple.h \ conversion/Acr_nema/acr_nema.h includeHEADERS_INSTALL = $(INSTALL_HEADER) am__include_acr_nema_HEADERS_DIST = \ conversion/Acr_nema/acr_nema/acr_io.h \ conversion/Acr_nema/acr_nema/dicom_client_routines.h \ conversion/Acr_nema/acr_nema/dicom_network.h \ conversion/Acr_nema/acr_nema/element.h \ conversion/Acr_nema/acr_nema/file_io.h \ conversion/Acr_nema/acr_nema/group.h \ conversion/Acr_nema/acr_nema/message.h \ conversion/Acr_nema/acr_nema/value_repr.h include_acr_nemaHEADERS_INSTALL = $(INSTALL_HEADER) include_volume_ioHEADERS_INSTALL = $(INSTALL_HEADER) am__noinst_HEADERS_DIST = libsrc/read_file_names.h libsrc/minc_basic.h \ libsrc/minc_config.h libsrc/minc_error.h libsrc/minc_private.h \ libsrc/minc_routines.h libsrc/minc_structures.h \ libsrc/minc_useful.h libsrc/minc_varlists.h \ libsrc/type_limits.h libsrc/hdf_convenience.h \ progs/Proglib/convert_origin_to_start.h \ progs/Proglib/minc_def.h progs/minccalc/errx.h \ progs/minccalc/node.h progs/minccalc/gram.h \ progs/mincmorph/kernel_io.h progs/mincmorph/kernel_ops.h \ progs/mincresample/mincresample.h \ progs/mincreshape/mincreshape.h progs/mincsample/mt19937ar.h \ libsrc2/minc2_private.h progs/mincdump/mincdump.h \ progs/mincdump/dumplib.h progs/mincdump/vardata.h \ progs/mincgen/generic.h progs/mincgen/genlib.h \ progs/mincgen/ncgen.h progs/mincgen/ncgentab.h \ conversion/ecattominc/ecat_file.h \ conversion/ecattominc/machine_indep.h \ conversion/ecattominc/ecat_header_definition.h \ conversion/minctoecat/ecat_write.h \ conversion/minctoecat/machine_indep.h \ conversion/nifti1/nifti1.h conversion/nifti1/nifti1_io.h \ conversion/nifti1/nifti1_local.h conversion/nifti1/znzlib.h \ conversion/nifti1/analyze75.h \ conversion/dcm2mnc/acr_element_defs.h \ conversion/dcm2mnc/dcm2mnc.h conversion/dcm2mnc/dicom_read.h \ conversion/dcm2mnc/dicom_to_minc.h \ conversion/dcm2mnc/ext_element_defs.h \ conversion/dcm2mnc/minc_file.h conversion/dcm2mnc/progress.h \ conversion/dcm2mnc/siemens_to_dicom.h \ conversion/dcm2mnc/siemens_header_defs.h \ conversion/dcm2mnc/siemens_header_table.h \ conversion/dcm2mnc/spi_element_defs.h \ conversion/dcm2mnc/string_to_filename.h \ conversion/dcm2mnc/pms_element_defs.h \ conversion/dcm2mnc/gems_element_defs.h \ conversion/vff2mnc/vff2mnc.h conversion/Acr_nema/acr_nema.h \ conversion/Acr_nema/acr_nema/acr_io.h \ conversion/Acr_nema/acr_nema/dicom_client_routines.h \ conversion/Acr_nema/acr_nema/dicom_network.h \ conversion/Acr_nema/acr_nema/element.h \ conversion/Acr_nema/acr_nema/file_io.h \ conversion/Acr_nema/acr_nema/group.h \ conversion/Acr_nema/acr_nema/message.h \ conversion/Acr_nema/acr_nema/value_repr.h HEADERS = $(include_HEADERS) $(include_acr_nema_HEADERS) \ $(include_volume_io_HEADERS) $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = . volume_io testdir doc libsrc2/test DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POD2MAN = @POD2MAN@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_F77 = @ac_ct_F77@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # Makefile.am for MINC2 # AUTOMAKE_OPTIONS = check-news subdir-objects ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = AM_YFLAGS = -d --debug SUBDIRS = . volume_io testdir doc $(am__append_1) # Add these to the include searches. # INCLUDES = -I$(top_srcdir)/libsrc -I$(top_builddir)/volume_io/Include \ -I$(top_srcdir)/volume_io/Include \ -I$(top_srcdir)/progs/Proglib \ -I$(top_srcdir)/conversion/Acr_nema $(am__append_2) # Headers which must be installed. # include_HEADERS = libsrc/minc.h libsrc/ParseArgv.h libsrc/voxel_loop.h \ libsrc/nd_loop.h libsrc/time_stamp.h libsrc/minc_compat.h \ volume_io/Include/volume_io.h libsrc2/minc2.h \ libsrc/minc_simple.h $(am__append_3) include_volume_iodir = $(includedir)/volume_io include_volume_io_HEADERS = \ volume_io/Include/volume_io/alloc.h \ volume_io/Include/volume_io/arrays.h \ volume_io/Include/volume_io/basic.h \ volume_io/Include/volume_io/def_math.h \ volume_io/Include/volume_io/files.h \ volume_io/Include/volume_io/geom_structs.h \ volume_io/Include/volume_io/geometry.h \ volume_io/Include/internal_volume_io.h \ volume_io/Include/volume_io/multidim.h \ volume_io/Include/volume_io/progress.h \ volume_io/Include/volume_io/string_funcs.h \ volume_io/Include/volume_io/system_dependent.h \ volume_io/Include/volume_io/transforms.h \ volume_io/Include/volume_io/vol_io_prototypes.h \ volume_io/Include/volume_io/volume.h \ volume_io/Include/volume_io/volume_cache.h # Header files which must be included in the distribution but which are # not part of the installation. # noinst_HEADERS = libsrc/read_file_names.h libsrc/minc_basic.h \ libsrc/minc_config.h libsrc/minc_error.h libsrc/minc_private.h \ libsrc/minc_routines.h libsrc/minc_structures.h \ libsrc/minc_useful.h libsrc/minc_varlists.h \ libsrc/type_limits.h libsrc/hdf_convenience.h \ progs/Proglib/convert_origin_to_start.h \ progs/Proglib/minc_def.h progs/minccalc/errx.h \ progs/minccalc/node.h progs/minccalc/gram.h \ progs/mincmorph/kernel_io.h progs/mincmorph/kernel_ops.h \ progs/mincresample/mincresample.h \ progs/mincreshape/mincreshape.h progs/mincsample/mt19937ar.h \ libsrc2/minc2_private.h progs/mincdump/mincdump.h \ progs/mincdump/dumplib.h progs/mincdump/vardata.h \ progs/mincgen/generic.h progs/mincgen/genlib.h \ progs/mincgen/ncgen.h progs/mincgen/ncgentab.h \ conversion/ecattominc/ecat_file.h \ conversion/ecattominc/machine_indep.h \ conversion/ecattominc/ecat_header_definition.h \ conversion/minctoecat/ecat_write.h \ conversion/minctoecat/machine_indep.h \ conversion/nifti1/nifti1.h conversion/nifti1/nifti1_io.h \ conversion/nifti1/nifti1_local.h conversion/nifti1/znzlib.h \ conversion/nifti1/analyze75.h \ conversion/dcm2mnc/acr_element_defs.h \ conversion/dcm2mnc/dcm2mnc.h conversion/dcm2mnc/dicom_read.h \ conversion/dcm2mnc/dicom_to_minc.h \ conversion/dcm2mnc/ext_element_defs.h \ conversion/dcm2mnc/minc_file.h conversion/dcm2mnc/progress.h \ conversion/dcm2mnc/siemens_to_dicom.h \ conversion/dcm2mnc/siemens_header_defs.h \ conversion/dcm2mnc/siemens_header_table.h \ conversion/dcm2mnc/spi_element_defs.h \ conversion/dcm2mnc/string_to_filename.h \ conversion/dcm2mnc/pms_element_defs.h \ conversion/dcm2mnc/gems_element_defs.h \ conversion/vff2mnc/vff2mnc.h $(am__append_4) @ACR_NEMA_TOOLS_TRUE@include_acr_nemadir = $(includedir)/acr_nema @ACR_NEMA_TOOLS_TRUE@include_acr_nema_HEADERS = \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/acr_io.h \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/dicom_client_routines.h \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/dicom_network.h \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/element.h \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/file_io.h \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/group.h \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/message.h \ @ACR_NEMA_TOOLS_TRUE@ conversion/Acr_nema/acr_nema/value_repr.h # Libraries which must be built and installed. # lib_LTLIBRARIES = libminc2.la libvolume_io2.la $(am__append_5) @ACR_NEMA_TOOLS_FALSE@noinst_LTLIBRARIES = libacr_nema.la # Scripts we install: sh or perl. # dist_bin_SCRIPTS = \ progs/mincdiff/mincdiff \ progs/mincedit/mincedit \ progs/mincheader/mincheader \ progs/mincview/mincview # Scripts that we process (to add version #s) before install bin_SCRIPTS = \ progs/minccomplete/minccomplete \ progs/minchistory/minchistory \ progs/mincpik/mincpik \ progs/xfm/xfmflip LDADD = libvolume_io2.la libminc2.la EXTRA_DIST = $(m4_files) $(ezMINC_files) \ progs/minccomplete/minccomplete.in \ progs/minchistory/minchistory.in progs/mincpik/mincpik.in \ progs/xfm/xfmflip.in libsrc/strdup.c epm-header.in \ libsrc/config.h.msvc-win32 Makefile.msvc-win32 \ conversion/Acr_nema/dicom.txt INSTALL.minc CMakeLists.txt \ config.h.cmake UseMINC2.cmake.in MINC2Config.cmake.in \ progs/CMakeLists.txt conversion/CMakeLists.txt \ cmake-modules/FindHDF5.cmake cmake-modules/FindNETCDF.cmake \ $(am__append_8) m4_files = \ m4/mni_REQUIRE_LIB.m4 \ m4/smr_WITH_BUILD_PATH.m4 ezMINC_files = \ ezminc/examples/volume_msq_dist.cpp voxeltoworld_SOURCES = progs/coordinates/voxeltoworld.c worldtovoxel_SOURCES = progs/coordinates/worldtovoxel.c minc_modify_header_SOURCES = progs/minc_modify_header/minc_modify_header.c mincaverage_SOURCES = progs/mincaverage/mincaverage.c mincblob_SOURCES = progs/mincblob/mincblob.c minccalc_CFLAGS = -Iprogs/minccalc -I$(srcdir)/progs/minccalc minccalc_SOURCES = \ progs/minccalc/minccalc.c \ progs/minccalc/gram.y \ progs/minccalc/eval.c \ progs/minccalc/ident.c \ progs/minccalc/lex.l \ progs/minccalc/node.c \ progs/minccalc/optim.c \ progs/minccalc/scalar.c \ progs/minccalc/sym.c \ progs/minccalc/vector.c mincconcat_SOURCES = progs/mincconcat/mincconcat.c minccopy_SOURCES = progs/minccopy/minccopy.c minccmp_SOURCES = progs/minccmp/minccmp.c mincexample1_SOURCES = progs/mincexample/mincexample1.c mincexample2_SOURCES = progs/mincexample/mincexample2.c mincexpand_SOURCES = progs/mincexpand/mincexpand.c mincextract_SOURCES = progs/mincextract/mincextract.c mincgen_SOURCES = \ progs/mincgen/escapes.c \ progs/mincgen/genlib.c \ progs/mincgen/getfill.c \ progs/mincgen/init.c \ progs/mincgen/load.c \ progs/mincgen/main.c \ progs/mincgen/ncgentab.y \ progs/mincgen/ncgenyy.l mincinfo_SOURCES = progs/mincinfo/mincinfo.c minclookup_SOURCES = progs/minclookup/minclookup.c mincmakescalar_SOURCES = progs/mincmakescalar/mincmakescalar.c mincmakevector_SOURCES = progs/mincmakevector/mincmakevector.c mincmath_SOURCES = progs/mincmath/mincmath.c mincmorph_CFLAGS = -Iprogs/mincmorph -I$(srcdir)/progs/mincmorph mincmorph_SOURCES = \ progs/mincmorph/mincmorph.c \ progs/mincmorph/kernel_io.c \ progs/mincmorph/kernel_ops.c mincsample_CFLAGS = -Iprogs/mincsample -I$(srcdir)/progs/mincsample mincresample_SOURCES = \ progs/mincresample/mincresample.c \ progs/mincresample/resample_volumes.c \ progs/Proglib/convert_origin_to_start.c mincreshape_SOURCES = \ progs/mincreshape/mincreshape.c \ progs/mincreshape/copy_data.c mincsample_SOURCES = \ progs/mincsample/mincsample.c \ progs/mincsample/mt19937ar.c mincstats_SOURCES = progs/mincstats/mincstats.c minctoraw_SOURCES = progs/minctoraw/minctoraw.c invert_raw_image_SOURCES = progs/mincview/invert_raw_image.c mincwindow_SOURCES = progs/mincwindow/mincwindow.c rawtominc_SOURCES = \ progs/rawtominc/rawtominc.c \ progs/Proglib/convert_origin_to_start.c transformtags_SOURCES = progs/xfm/transformtags.c xfm2def_SOURCES = progs/xfm/xfm2def.c xfmconcat_SOURCES = progs/xfm/xfmconcat.c xfminvert_SOURCES = progs/xfm/xfminvert.c mincconvert_SOURCES = progs/mincconvert/mincconvert.c mincdump_SOURCES = \ progs/mincdump/mincdump.c \ progs/mincdump/vardata.c \ progs/mincdump/dumplib.c ecattominc_SOURCES = \ conversion/ecattominc/ecattominc.c \ conversion/ecattominc/insertblood.c \ conversion/ecattominc/ecat_file.c \ conversion/ecattominc/machine_indep.c minctoecat_SOURCES = \ conversion/minctoecat/minctoecat.c \ conversion/minctoecat/ecat_write.c \ conversion/minctoecat/machine_indep.c nii2mnc_SOURCES = \ conversion/nifti1/nii2mnc.c \ conversion/nifti1/nifti1_io.c \ conversion/nifti1/znzlib.c mnc2nii_SOURCES = \ conversion/nifti1/mnc2nii.c \ conversion/nifti1/nifti1_io.c \ conversion/nifti1/znzlib.c upet2mnc_SOURCES = \ conversion/micropet/upet2mnc.c dcm2mnc_LDADD = libacr_nema.la $(LDADD) dcm2mnc_SOURCES = \ conversion/dcm2mnc/dcm2mnc.c \ conversion/dcm2mnc/dicom_to_minc.c \ conversion/dcm2mnc/siemens_to_dicom.c \ conversion/dcm2mnc/dicom_read.c \ conversion/dcm2mnc/minc_file.c \ conversion/dcm2mnc/progress.c \ conversion/dcm2mnc/string_to_filename.c vff2mnc_SOURCES = \ conversion/vff2mnc/vff2mnc.c acr_test_LDADD = libacr_nema.la acr_test_SOURCES = conversion/Acr_nema/acr_test.c dump_acr_nema_LDADD = libacr_nema.la dump_acr_nema_SOURCES = conversion/Acr_nema/dump_acr_nema.c extract_acr_nema_LDADD = libacr_nema.la extract_acr_nema_SOURCES = conversion/Acr_nema/extract_acr_nema.c read_acr_nema_LDADD = libacr_nema.la read_acr_nema_SOURCES = conversion/Acr_nema/read_acr_nema.c dicom_test_LDADD = libacr_nema.la dicom_test_SOURCES = conversion/Acr_nema/dicom_test.c copy_acr_nema_LDADD = libacr_nema.la copy_acr_nema_SOURCES = conversion/Acr_nema/copy_acr_nema.c extract_SOURCES = conversion/image_filters/extract.c byte_swap_SOURCES = conversion/image_filters/byte_swap.c libminc2_la_LDFLAGS = -version-info 3:0:0 libminc2_la_SOURCES = libsrc/ParseArgv.c libsrc/read_file_names.c \ libsrc/dim_conversion.c libsrc/image_conversion.c \ libsrc/minc_convenience.c libsrc/minc_error.c libsrc/nd_loop.c \ libsrc/netcdf_convenience.c libsrc/time_stamp.c \ libsrc/value_conversion.c libsrc/voxel_loop.c \ libsrc/hdf_convenience.c libsrc/minc_compat.c \ libsrc/minc_simple.c $(am__append_7) libvolume_io2_la_LDFLAGS = -version-info 3:0:0 libvolume_io2_la_SOURCES = \ volume_io/Geometry/colour.c \ volume_io/Geometry/colour_def.c \ volume_io/Geometry/gaussian.c \ volume_io/Geometry/inverse.c \ volume_io/Geometry/newton.c \ volume_io/Geometry/points.c \ volume_io/Geometry/splines.c \ volume_io/Geometry/tensors.c \ volume_io/Geometry/transforms.c \ volume_io/MNI_formats/gen_xf_io.c \ volume_io/MNI_formats/gen_xfs.c \ volume_io/MNI_formats/grid_transforms.c \ volume_io/MNI_formats/mni_io.c \ volume_io/MNI_formats/tag_points.c \ volume_io/MNI_formats/thin_plate_spline.c \ volume_io/Prog_utils/alloc.c \ volume_io/Prog_utils/alloc_check.c \ volume_io/Prog_utils/arrays.c \ volume_io/Prog_utils/files.c \ volume_io/Prog_utils/print.c \ volume_io/Prog_utils/progress.c \ volume_io/Prog_utils/string.c \ volume_io/Prog_utils/time.c \ volume_io/Volumes/evaluate.c \ volume_io/Volumes/get_hyperslab.c \ volume_io/Volumes/input_free.c \ volume_io/Volumes/input_mnc.c \ volume_io/Volumes/input_volume.c \ volume_io/Volumes/multidim_arrays.c \ volume_io/Volumes/output_mnc.c \ volume_io/Volumes/output_volume.c \ volume_io/Volumes/set_hyperslab.c \ volume_io/Volumes/volume_cache.c \ volume_io/Volumes/volumes.c libacr_nema_la_SOURCES = \ conversion/Acr_nema/acr_io.c \ conversion/Acr_nema/dicom_client_routines.c \ conversion/Acr_nema/dicom_network.c \ conversion/Acr_nema/element.c \ conversion/Acr_nema/file_io.c \ conversion/Acr_nema/globals.c \ conversion/Acr_nema/group.c \ conversion/Acr_nema/message.c \ conversion/Acr_nema/value_repr.c # MAN pages go here. The "dist_" prefix signals that they # are to be included in source distribution. # dist_man1_MANS = \ progs/coordinates/voxeltoworld.man1 \ progs/minc_modify_header/minc_modify_header.man1 \ progs/mincaverage/mincaverage.man1 \ progs/mincblob/mincblob.man1 \ progs/minccalc/minccalc.man1 \ progs/minccomplete/minccomplete.man1 \ progs/mincconcat/mincconcat.man1 \ progs/minccmp/minccmp.man1 \ progs/minccopy/minccopy.man1 \ progs/mincdiff/mincdiff.man1 \ progs/mincedit/mincedit.man1 \ progs/mincexpand/mincexpand.man1 \ progs/mincextract/mincextract.man1 \ progs/mincgen/mincgen.man1 \ progs/mincheader/mincheader.man1 \ progs/minchistory/minchistory.man1 \ progs/mincinfo/mincinfo.man1 \ progs/minclookup/minclookup.man1 \ progs/mincmakescalar/mincmakescalar.man1 \ progs/mincmakevector/mincmakevector.man1 \ progs/mincmath/mincmath.man1 \ progs/mincpik/mincpik.man1 \ progs/mincresample/mincresample.man1 \ progs/mincreshape/mincreshape.man1 \ progs/mincstats/mincstats.man1 \ progs/minctoraw/minctoraw.man1 \ progs/mincview/invert_raw_image.man1 \ progs/mincview/mincview.man1 \ progs/mincwindow/mincwindow.man1 \ progs/rawtominc/rawtominc.man1 \ progs/xfm/transformtags.man1 \ progs/xfm/xfm2def.man1 \ progs/xfm/xfmconcat.man1 \ progs/xfm/xfminvert.man1 \ progs/xfm/xfmflip.man1 \ progs/mincconvert/mincconvert.man1 \ conversion/ecattominc/ecattominc.man1 \ conversion/minctoecat/minctoecat.man1 \ conversion/nifti1/nii2mnc.man1 \ conversion/nifti1/mnc2nii.man1 \ conversion/micropet/upet2mnc.man1 \ conversion/dcm2mnc/dcm2mnc.man1 \ conversion/vff2mnc/vff2mnc.man1 dist_man3_MANS = libsrc/ParseArgv.man3 all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .l .lo .o .obj .y am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \ cd $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) cd $(top_srcdir) && $(AUTOHEADER) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 epm-header: $(top_builddir)/config.status $(srcdir)/epm-header.in cd $(top_builddir) && $(SHELL) ./config.status $@ progs/xfm/xfmflip: $(top_builddir)/config.status $(top_srcdir)/progs/xfm/xfmflip.in cd $(top_builddir) && $(SHELL) ./config.status $@ progs/minccomplete/minccomplete: $(top_builddir)/config.status $(top_srcdir)/progs/minccomplete/minccomplete.in cd $(top_builddir) && $(SHELL) ./config.status $@ progs/minchistory/minchistory: $(top_builddir)/config.status $(top_srcdir)/progs/minchistory/minchistory.in cd $(top_builddir) && $(SHELL) ./config.status $@ progs/mincpik/mincpik: $(top_builddir)/config.status $(top_srcdir)/progs/mincpik/mincpik.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ else :; fi; \ done uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done conversion/Acr_nema/$(am__dirstamp): @$(MKDIR_P) conversion/Acr_nema @: > conversion/Acr_nema/$(am__dirstamp) conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/Acr_nema/$(DEPDIR) @: > conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/acr_io.lo: conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/dicom_client_routines.lo: \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/dicom_network.lo: \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/element.lo: conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/file_io.lo: conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/globals.lo: conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/group.lo: conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/message.lo: conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) conversion/Acr_nema/value_repr.lo: \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) libacr_nema.la: $(libacr_nema_la_OBJECTS) $(libacr_nema_la_DEPENDENCIES) $(LINK) $(am_libacr_nema_la_rpath) $(libacr_nema_la_OBJECTS) $(libacr_nema_la_LIBADD) $(LIBS) libsrc/$(am__dirstamp): @$(MKDIR_P) libsrc @: > libsrc/$(am__dirstamp) libsrc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) libsrc/$(DEPDIR) @: > libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/ParseArgv.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/read_file_names.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/dim_conversion.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/image_conversion.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/minc_convenience.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/minc_error.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/nd_loop.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/netcdf_convenience.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/time_stamp.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/value_conversion.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/voxel_loop.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/hdf_convenience.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/minc_compat.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc/minc_simple.lo: libsrc/$(am__dirstamp) \ libsrc/$(DEPDIR)/$(am__dirstamp) libsrc2/$(am__dirstamp): @$(MKDIR_P) libsrc2 @: > libsrc2/$(am__dirstamp) libsrc2/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) libsrc2/$(DEPDIR) @: > libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/convert.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/datatype.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/dimension.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/free.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/grpattr.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/hyper.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/label.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/m2util.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/record.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/slice.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/valid.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/volprops.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libsrc2/volume.lo: libsrc2/$(am__dirstamp) \ libsrc2/$(DEPDIR)/$(am__dirstamp) libminc2.la: $(libminc2_la_OBJECTS) $(libminc2_la_DEPENDENCIES) $(libminc2_la_LINK) -rpath $(libdir) $(libminc2_la_OBJECTS) $(libminc2_la_LIBADD) $(LIBS) volume_io/Geometry/$(am__dirstamp): @$(MKDIR_P) volume_io/Geometry @: > volume_io/Geometry/$(am__dirstamp) volume_io/Geometry/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) volume_io/Geometry/$(DEPDIR) @: > volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/colour.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/colour_def.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/gaussian.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/inverse.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/newton.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/points.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/splines.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/tensors.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/Geometry/transforms.lo: volume_io/Geometry/$(am__dirstamp) \ volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) volume_io/MNI_formats/$(am__dirstamp): @$(MKDIR_P) volume_io/MNI_formats @: > volume_io/MNI_formats/$(am__dirstamp) volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) volume_io/MNI_formats/$(DEPDIR) @: > volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) volume_io/MNI_formats/gen_xf_io.lo: \ volume_io/MNI_formats/$(am__dirstamp) \ volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) volume_io/MNI_formats/gen_xfs.lo: \ volume_io/MNI_formats/$(am__dirstamp) \ volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) volume_io/MNI_formats/grid_transforms.lo: \ volume_io/MNI_formats/$(am__dirstamp) \ volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) volume_io/MNI_formats/mni_io.lo: \ volume_io/MNI_formats/$(am__dirstamp) \ volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) volume_io/MNI_formats/tag_points.lo: \ volume_io/MNI_formats/$(am__dirstamp) \ volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) volume_io/MNI_formats/thin_plate_spline.lo: \ volume_io/MNI_formats/$(am__dirstamp) \ volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/$(am__dirstamp): @$(MKDIR_P) volume_io/Prog_utils @: > volume_io/Prog_utils/$(am__dirstamp) volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) volume_io/Prog_utils/$(DEPDIR) @: > volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/alloc.lo: volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/alloc_check.lo: \ volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/arrays.lo: volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/files.lo: volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/print.lo: volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/progress.lo: \ volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/string.lo: volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Prog_utils/time.lo: volume_io/Prog_utils/$(am__dirstamp) \ volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/$(am__dirstamp): @$(MKDIR_P) volume_io/Volumes @: > volume_io/Volumes/$(am__dirstamp) volume_io/Volumes/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) volume_io/Volumes/$(DEPDIR) @: > volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/evaluate.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/get_hyperslab.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/input_free.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/input_mnc.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/input_volume.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/multidim_arrays.lo: \ volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/output_mnc.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/output_volume.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/set_hyperslab.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/volume_cache.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) volume_io/Volumes/volumes.lo: volume_io/Volumes/$(am__dirstamp) \ volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) libvolume_io2.la: $(libvolume_io2_la_OBJECTS) $(libvolume_io2_la_DEPENDENCIES) $(libvolume_io2_la_LINK) -rpath $(libdir) $(libvolume_io2_la_OBJECTS) $(libvolume_io2_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done conversion/Acr_nema/acr_test.$(OBJEXT): \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) acr_test$(EXEEXT): $(acr_test_OBJECTS) $(acr_test_DEPENDENCIES) @rm -f acr_test$(EXEEXT) $(LINK) $(acr_test_OBJECTS) $(acr_test_LDADD) $(LIBS) conversion/image_filters/$(am__dirstamp): @$(MKDIR_P) conversion/image_filters @: > conversion/image_filters/$(am__dirstamp) conversion/image_filters/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/image_filters/$(DEPDIR) @: > conversion/image_filters/$(DEPDIR)/$(am__dirstamp) conversion/image_filters/byte_swap.$(OBJEXT): \ conversion/image_filters/$(am__dirstamp) \ conversion/image_filters/$(DEPDIR)/$(am__dirstamp) byte_swap$(EXEEXT): $(byte_swap_OBJECTS) $(byte_swap_DEPENDENCIES) @rm -f byte_swap$(EXEEXT) $(LINK) $(byte_swap_OBJECTS) $(byte_swap_LDADD) $(LIBS) conversion/Acr_nema/copy_acr_nema.$(OBJEXT): \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) copy_acr_nema$(EXEEXT): $(copy_acr_nema_OBJECTS) $(copy_acr_nema_DEPENDENCIES) @rm -f copy_acr_nema$(EXEEXT) $(LINK) $(copy_acr_nema_OBJECTS) $(copy_acr_nema_LDADD) $(LIBS) conversion/dcm2mnc/$(am__dirstamp): @$(MKDIR_P) conversion/dcm2mnc @: > conversion/dcm2mnc/$(am__dirstamp) conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/dcm2mnc/$(DEPDIR) @: > conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) conversion/dcm2mnc/dcm2mnc.$(OBJEXT): \ conversion/dcm2mnc/$(am__dirstamp) \ conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) conversion/dcm2mnc/dicom_to_minc.$(OBJEXT): \ conversion/dcm2mnc/$(am__dirstamp) \ conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) conversion/dcm2mnc/siemens_to_dicom.$(OBJEXT): \ conversion/dcm2mnc/$(am__dirstamp) \ conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) conversion/dcm2mnc/dicom_read.$(OBJEXT): \ conversion/dcm2mnc/$(am__dirstamp) \ conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) conversion/dcm2mnc/minc_file.$(OBJEXT): \ conversion/dcm2mnc/$(am__dirstamp) \ conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) conversion/dcm2mnc/progress.$(OBJEXT): \ conversion/dcm2mnc/$(am__dirstamp) \ conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) conversion/dcm2mnc/string_to_filename.$(OBJEXT): \ conversion/dcm2mnc/$(am__dirstamp) \ conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) dcm2mnc$(EXEEXT): $(dcm2mnc_OBJECTS) $(dcm2mnc_DEPENDENCIES) @rm -f dcm2mnc$(EXEEXT) $(LINK) $(dcm2mnc_OBJECTS) $(dcm2mnc_LDADD) $(LIBS) conversion/Acr_nema/dicom_test.$(OBJEXT): \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) dicom_test$(EXEEXT): $(dicom_test_OBJECTS) $(dicom_test_DEPENDENCIES) @rm -f dicom_test$(EXEEXT) $(LINK) $(dicom_test_OBJECTS) $(dicom_test_LDADD) $(LIBS) conversion/Acr_nema/dump_acr_nema.$(OBJEXT): \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) dump_acr_nema$(EXEEXT): $(dump_acr_nema_OBJECTS) $(dump_acr_nema_DEPENDENCIES) @rm -f dump_acr_nema$(EXEEXT) $(LINK) $(dump_acr_nema_OBJECTS) $(dump_acr_nema_LDADD) $(LIBS) conversion/ecattominc/$(am__dirstamp): @$(MKDIR_P) conversion/ecattominc @: > conversion/ecattominc/$(am__dirstamp) conversion/ecattominc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/ecattominc/$(DEPDIR) @: > conversion/ecattominc/$(DEPDIR)/$(am__dirstamp) conversion/ecattominc/ecattominc.$(OBJEXT): \ conversion/ecattominc/$(am__dirstamp) \ conversion/ecattominc/$(DEPDIR)/$(am__dirstamp) conversion/ecattominc/insertblood.$(OBJEXT): \ conversion/ecattominc/$(am__dirstamp) \ conversion/ecattominc/$(DEPDIR)/$(am__dirstamp) conversion/ecattominc/ecat_file.$(OBJEXT): \ conversion/ecattominc/$(am__dirstamp) \ conversion/ecattominc/$(DEPDIR)/$(am__dirstamp) conversion/ecattominc/machine_indep.$(OBJEXT): \ conversion/ecattominc/$(am__dirstamp) \ conversion/ecattominc/$(DEPDIR)/$(am__dirstamp) ecattominc$(EXEEXT): $(ecattominc_OBJECTS) $(ecattominc_DEPENDENCIES) @rm -f ecattominc$(EXEEXT) $(LINK) $(ecattominc_OBJECTS) $(ecattominc_LDADD) $(LIBS) conversion/image_filters/extract.$(OBJEXT): \ conversion/image_filters/$(am__dirstamp) \ conversion/image_filters/$(DEPDIR)/$(am__dirstamp) extract$(EXEEXT): $(extract_OBJECTS) $(extract_DEPENDENCIES) @rm -f extract$(EXEEXT) $(LINK) $(extract_OBJECTS) $(extract_LDADD) $(LIBS) conversion/Acr_nema/extract_acr_nema.$(OBJEXT): \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) extract_acr_nema$(EXEEXT): $(extract_acr_nema_OBJECTS) $(extract_acr_nema_DEPENDENCIES) @rm -f extract_acr_nema$(EXEEXT) $(LINK) $(extract_acr_nema_OBJECTS) $(extract_acr_nema_LDADD) $(LIBS) progs/mincview/$(am__dirstamp): @$(MKDIR_P) progs/mincview @: > progs/mincview/$(am__dirstamp) progs/mincview/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincview/$(DEPDIR) @: > progs/mincview/$(DEPDIR)/$(am__dirstamp) progs/mincview/invert_raw_image.$(OBJEXT): \ progs/mincview/$(am__dirstamp) \ progs/mincview/$(DEPDIR)/$(am__dirstamp) invert_raw_image$(EXEEXT): $(invert_raw_image_OBJECTS) $(invert_raw_image_DEPENDENCIES) @rm -f invert_raw_image$(EXEEXT) $(LINK) $(invert_raw_image_OBJECTS) $(invert_raw_image_LDADD) $(LIBS) progs/minc_modify_header/$(am__dirstamp): @$(MKDIR_P) progs/minc_modify_header @: > progs/minc_modify_header/$(am__dirstamp) progs/minc_modify_header/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/minc_modify_header/$(DEPDIR) @: > progs/minc_modify_header/$(DEPDIR)/$(am__dirstamp) progs/minc_modify_header/minc_modify_header.$(OBJEXT): \ progs/minc_modify_header/$(am__dirstamp) \ progs/minc_modify_header/$(DEPDIR)/$(am__dirstamp) minc_modify_header$(EXEEXT): $(minc_modify_header_OBJECTS) $(minc_modify_header_DEPENDENCIES) @rm -f minc_modify_header$(EXEEXT) $(LINK) $(minc_modify_header_OBJECTS) $(minc_modify_header_LDADD) $(LIBS) progs/mincaverage/$(am__dirstamp): @$(MKDIR_P) progs/mincaverage @: > progs/mincaverage/$(am__dirstamp) progs/mincaverage/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincaverage/$(DEPDIR) @: > progs/mincaverage/$(DEPDIR)/$(am__dirstamp) progs/mincaverage/mincaverage.$(OBJEXT): \ progs/mincaverage/$(am__dirstamp) \ progs/mincaverage/$(DEPDIR)/$(am__dirstamp) mincaverage$(EXEEXT): $(mincaverage_OBJECTS) $(mincaverage_DEPENDENCIES) @rm -f mincaverage$(EXEEXT) $(LINK) $(mincaverage_OBJECTS) $(mincaverage_LDADD) $(LIBS) progs/mincblob/$(am__dirstamp): @$(MKDIR_P) progs/mincblob @: > progs/mincblob/$(am__dirstamp) progs/mincblob/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincblob/$(DEPDIR) @: > progs/mincblob/$(DEPDIR)/$(am__dirstamp) progs/mincblob/mincblob.$(OBJEXT): progs/mincblob/$(am__dirstamp) \ progs/mincblob/$(DEPDIR)/$(am__dirstamp) mincblob$(EXEEXT): $(mincblob_OBJECTS) $(mincblob_DEPENDENCIES) @rm -f mincblob$(EXEEXT) $(LINK) $(mincblob_OBJECTS) $(mincblob_LDADD) $(LIBS) progs/minccalc/$(am__dirstamp): @$(MKDIR_P) progs/minccalc @: > progs/minccalc/$(am__dirstamp) progs/minccalc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/minccalc/$(DEPDIR) @: > progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-minccalc.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/gram.h: progs/minccalc/gram.c @if test ! -f $@; then \ rm -f progs/minccalc/gram.c; \ $(MAKE) $(AM_MAKEFLAGS) progs/minccalc/gram.c; \ else :; fi progs/minccalc/minccalc-gram.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-eval.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-ident.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-lex.$(OBJEXT): progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-node.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-optim.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-scalar.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-sym.$(OBJEXT): progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) progs/minccalc/minccalc-vector.$(OBJEXT): \ progs/minccalc/$(am__dirstamp) \ progs/minccalc/$(DEPDIR)/$(am__dirstamp) minccalc$(EXEEXT): $(minccalc_OBJECTS) $(minccalc_DEPENDENCIES) @rm -f minccalc$(EXEEXT) $(minccalc_LINK) $(minccalc_OBJECTS) $(minccalc_LDADD) $(LIBS) progs/minccmp/$(am__dirstamp): @$(MKDIR_P) progs/minccmp @: > progs/minccmp/$(am__dirstamp) progs/minccmp/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/minccmp/$(DEPDIR) @: > progs/minccmp/$(DEPDIR)/$(am__dirstamp) progs/minccmp/minccmp.$(OBJEXT): progs/minccmp/$(am__dirstamp) \ progs/minccmp/$(DEPDIR)/$(am__dirstamp) minccmp$(EXEEXT): $(minccmp_OBJECTS) $(minccmp_DEPENDENCIES) @rm -f minccmp$(EXEEXT) $(LINK) $(minccmp_OBJECTS) $(minccmp_LDADD) $(LIBS) progs/mincconcat/$(am__dirstamp): @$(MKDIR_P) progs/mincconcat @: > progs/mincconcat/$(am__dirstamp) progs/mincconcat/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincconcat/$(DEPDIR) @: > progs/mincconcat/$(DEPDIR)/$(am__dirstamp) progs/mincconcat/mincconcat.$(OBJEXT): \ progs/mincconcat/$(am__dirstamp) \ progs/mincconcat/$(DEPDIR)/$(am__dirstamp) mincconcat$(EXEEXT): $(mincconcat_OBJECTS) $(mincconcat_DEPENDENCIES) @rm -f mincconcat$(EXEEXT) $(LINK) $(mincconcat_OBJECTS) $(mincconcat_LDADD) $(LIBS) progs/mincconvert/$(am__dirstamp): @$(MKDIR_P) progs/mincconvert @: > progs/mincconvert/$(am__dirstamp) progs/mincconvert/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincconvert/$(DEPDIR) @: > progs/mincconvert/$(DEPDIR)/$(am__dirstamp) progs/mincconvert/mincconvert.$(OBJEXT): \ progs/mincconvert/$(am__dirstamp) \ progs/mincconvert/$(DEPDIR)/$(am__dirstamp) mincconvert$(EXEEXT): $(mincconvert_OBJECTS) $(mincconvert_DEPENDENCIES) @rm -f mincconvert$(EXEEXT) $(LINK) $(mincconvert_OBJECTS) $(mincconvert_LDADD) $(LIBS) progs/minccopy/$(am__dirstamp): @$(MKDIR_P) progs/minccopy @: > progs/minccopy/$(am__dirstamp) progs/minccopy/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/minccopy/$(DEPDIR) @: > progs/minccopy/$(DEPDIR)/$(am__dirstamp) progs/minccopy/minccopy.$(OBJEXT): progs/minccopy/$(am__dirstamp) \ progs/minccopy/$(DEPDIR)/$(am__dirstamp) minccopy$(EXEEXT): $(minccopy_OBJECTS) $(minccopy_DEPENDENCIES) @rm -f minccopy$(EXEEXT) $(LINK) $(minccopy_OBJECTS) $(minccopy_LDADD) $(LIBS) progs/mincdump/$(am__dirstamp): @$(MKDIR_P) progs/mincdump @: > progs/mincdump/$(am__dirstamp) progs/mincdump/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincdump/$(DEPDIR) @: > progs/mincdump/$(DEPDIR)/$(am__dirstamp) progs/mincdump/mincdump.$(OBJEXT): progs/mincdump/$(am__dirstamp) \ progs/mincdump/$(DEPDIR)/$(am__dirstamp) progs/mincdump/vardata.$(OBJEXT): progs/mincdump/$(am__dirstamp) \ progs/mincdump/$(DEPDIR)/$(am__dirstamp) progs/mincdump/dumplib.$(OBJEXT): progs/mincdump/$(am__dirstamp) \ progs/mincdump/$(DEPDIR)/$(am__dirstamp) mincdump$(EXEEXT): $(mincdump_OBJECTS) $(mincdump_DEPENDENCIES) @rm -f mincdump$(EXEEXT) $(LINK) $(mincdump_OBJECTS) $(mincdump_LDADD) $(LIBS) progs/mincexample/$(am__dirstamp): @$(MKDIR_P) progs/mincexample @: > progs/mincexample/$(am__dirstamp) progs/mincexample/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincexample/$(DEPDIR) @: > progs/mincexample/$(DEPDIR)/$(am__dirstamp) progs/mincexample/mincexample1.$(OBJEXT): \ progs/mincexample/$(am__dirstamp) \ progs/mincexample/$(DEPDIR)/$(am__dirstamp) mincexample1$(EXEEXT): $(mincexample1_OBJECTS) $(mincexample1_DEPENDENCIES) @rm -f mincexample1$(EXEEXT) $(LINK) $(mincexample1_OBJECTS) $(mincexample1_LDADD) $(LIBS) progs/mincexample/mincexample2.$(OBJEXT): \ progs/mincexample/$(am__dirstamp) \ progs/mincexample/$(DEPDIR)/$(am__dirstamp) mincexample2$(EXEEXT): $(mincexample2_OBJECTS) $(mincexample2_DEPENDENCIES) @rm -f mincexample2$(EXEEXT) $(LINK) $(mincexample2_OBJECTS) $(mincexample2_LDADD) $(LIBS) progs/mincexpand/$(am__dirstamp): @$(MKDIR_P) progs/mincexpand @: > progs/mincexpand/$(am__dirstamp) progs/mincexpand/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincexpand/$(DEPDIR) @: > progs/mincexpand/$(DEPDIR)/$(am__dirstamp) progs/mincexpand/mincexpand.$(OBJEXT): \ progs/mincexpand/$(am__dirstamp) \ progs/mincexpand/$(DEPDIR)/$(am__dirstamp) mincexpand$(EXEEXT): $(mincexpand_OBJECTS) $(mincexpand_DEPENDENCIES) @rm -f mincexpand$(EXEEXT) $(LINK) $(mincexpand_OBJECTS) $(mincexpand_LDADD) $(LIBS) progs/mincextract/$(am__dirstamp): @$(MKDIR_P) progs/mincextract @: > progs/mincextract/$(am__dirstamp) progs/mincextract/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincextract/$(DEPDIR) @: > progs/mincextract/$(DEPDIR)/$(am__dirstamp) progs/mincextract/mincextract.$(OBJEXT): \ progs/mincextract/$(am__dirstamp) \ progs/mincextract/$(DEPDIR)/$(am__dirstamp) mincextract$(EXEEXT): $(mincextract_OBJECTS) $(mincextract_DEPENDENCIES) @rm -f mincextract$(EXEEXT) $(LINK) $(mincextract_OBJECTS) $(mincextract_LDADD) $(LIBS) progs/mincgen/$(am__dirstamp): @$(MKDIR_P) progs/mincgen @: > progs/mincgen/$(am__dirstamp) progs/mincgen/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincgen/$(DEPDIR) @: > progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/escapes.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/genlib.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/getfill.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/init.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/load.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/main.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/ncgentab.h: progs/mincgen/ncgentab.c @if test ! -f $@; then \ rm -f progs/mincgen/ncgentab.c; \ $(MAKE) $(AM_MAKEFLAGS) progs/mincgen/ncgentab.c; \ else :; fi progs/mincgen/ncgentab.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) progs/mincgen/ncgenyy.$(OBJEXT): progs/mincgen/$(am__dirstamp) \ progs/mincgen/$(DEPDIR)/$(am__dirstamp) mincgen$(EXEEXT): $(mincgen_OBJECTS) $(mincgen_DEPENDENCIES) @rm -f mincgen$(EXEEXT) $(LINK) $(mincgen_OBJECTS) $(mincgen_LDADD) $(LIBS) progs/mincinfo/$(am__dirstamp): @$(MKDIR_P) progs/mincinfo @: > progs/mincinfo/$(am__dirstamp) progs/mincinfo/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincinfo/$(DEPDIR) @: > progs/mincinfo/$(DEPDIR)/$(am__dirstamp) progs/mincinfo/mincinfo.$(OBJEXT): progs/mincinfo/$(am__dirstamp) \ progs/mincinfo/$(DEPDIR)/$(am__dirstamp) mincinfo$(EXEEXT): $(mincinfo_OBJECTS) $(mincinfo_DEPENDENCIES) @rm -f mincinfo$(EXEEXT) $(LINK) $(mincinfo_OBJECTS) $(mincinfo_LDADD) $(LIBS) progs/minclookup/$(am__dirstamp): @$(MKDIR_P) progs/minclookup @: > progs/minclookup/$(am__dirstamp) progs/minclookup/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/minclookup/$(DEPDIR) @: > progs/minclookup/$(DEPDIR)/$(am__dirstamp) progs/minclookup/minclookup.$(OBJEXT): \ progs/minclookup/$(am__dirstamp) \ progs/minclookup/$(DEPDIR)/$(am__dirstamp) minclookup$(EXEEXT): $(minclookup_OBJECTS) $(minclookup_DEPENDENCIES) @rm -f minclookup$(EXEEXT) $(LINK) $(minclookup_OBJECTS) $(minclookup_LDADD) $(LIBS) progs/mincmakescalar/$(am__dirstamp): @$(MKDIR_P) progs/mincmakescalar @: > progs/mincmakescalar/$(am__dirstamp) progs/mincmakescalar/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincmakescalar/$(DEPDIR) @: > progs/mincmakescalar/$(DEPDIR)/$(am__dirstamp) progs/mincmakescalar/mincmakescalar.$(OBJEXT): \ progs/mincmakescalar/$(am__dirstamp) \ progs/mincmakescalar/$(DEPDIR)/$(am__dirstamp) mincmakescalar$(EXEEXT): $(mincmakescalar_OBJECTS) $(mincmakescalar_DEPENDENCIES) @rm -f mincmakescalar$(EXEEXT) $(LINK) $(mincmakescalar_OBJECTS) $(mincmakescalar_LDADD) $(LIBS) progs/mincmakevector/$(am__dirstamp): @$(MKDIR_P) progs/mincmakevector @: > progs/mincmakevector/$(am__dirstamp) progs/mincmakevector/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincmakevector/$(DEPDIR) @: > progs/mincmakevector/$(DEPDIR)/$(am__dirstamp) progs/mincmakevector/mincmakevector.$(OBJEXT): \ progs/mincmakevector/$(am__dirstamp) \ progs/mincmakevector/$(DEPDIR)/$(am__dirstamp) mincmakevector$(EXEEXT): $(mincmakevector_OBJECTS) $(mincmakevector_DEPENDENCIES) @rm -f mincmakevector$(EXEEXT) $(LINK) $(mincmakevector_OBJECTS) $(mincmakevector_LDADD) $(LIBS) progs/mincmath/$(am__dirstamp): @$(MKDIR_P) progs/mincmath @: > progs/mincmath/$(am__dirstamp) progs/mincmath/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincmath/$(DEPDIR) @: > progs/mincmath/$(DEPDIR)/$(am__dirstamp) progs/mincmath/mincmath.$(OBJEXT): progs/mincmath/$(am__dirstamp) \ progs/mincmath/$(DEPDIR)/$(am__dirstamp) mincmath$(EXEEXT): $(mincmath_OBJECTS) $(mincmath_DEPENDENCIES) @rm -f mincmath$(EXEEXT) $(LINK) $(mincmath_OBJECTS) $(mincmath_LDADD) $(LIBS) progs/mincmorph/$(am__dirstamp): @$(MKDIR_P) progs/mincmorph @: > progs/mincmorph/$(am__dirstamp) progs/mincmorph/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincmorph/$(DEPDIR) @: > progs/mincmorph/$(DEPDIR)/$(am__dirstamp) progs/mincmorph/mincmorph-mincmorph.$(OBJEXT): \ progs/mincmorph/$(am__dirstamp) \ progs/mincmorph/$(DEPDIR)/$(am__dirstamp) progs/mincmorph/mincmorph-kernel_io.$(OBJEXT): \ progs/mincmorph/$(am__dirstamp) \ progs/mincmorph/$(DEPDIR)/$(am__dirstamp) progs/mincmorph/mincmorph-kernel_ops.$(OBJEXT): \ progs/mincmorph/$(am__dirstamp) \ progs/mincmorph/$(DEPDIR)/$(am__dirstamp) mincmorph$(EXEEXT): $(mincmorph_OBJECTS) $(mincmorph_DEPENDENCIES) @rm -f mincmorph$(EXEEXT) $(mincmorph_LINK) $(mincmorph_OBJECTS) $(mincmorph_LDADD) $(LIBS) progs/mincresample/$(am__dirstamp): @$(MKDIR_P) progs/mincresample @: > progs/mincresample/$(am__dirstamp) progs/mincresample/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincresample/$(DEPDIR) @: > progs/mincresample/$(DEPDIR)/$(am__dirstamp) progs/mincresample/mincresample.$(OBJEXT): \ progs/mincresample/$(am__dirstamp) \ progs/mincresample/$(DEPDIR)/$(am__dirstamp) progs/mincresample/resample_volumes.$(OBJEXT): \ progs/mincresample/$(am__dirstamp) \ progs/mincresample/$(DEPDIR)/$(am__dirstamp) progs/Proglib/$(am__dirstamp): @$(MKDIR_P) progs/Proglib @: > progs/Proglib/$(am__dirstamp) progs/Proglib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/Proglib/$(DEPDIR) @: > progs/Proglib/$(DEPDIR)/$(am__dirstamp) progs/Proglib/convert_origin_to_start.$(OBJEXT): \ progs/Proglib/$(am__dirstamp) \ progs/Proglib/$(DEPDIR)/$(am__dirstamp) mincresample$(EXEEXT): $(mincresample_OBJECTS) $(mincresample_DEPENDENCIES) @rm -f mincresample$(EXEEXT) $(LINK) $(mincresample_OBJECTS) $(mincresample_LDADD) $(LIBS) progs/mincreshape/$(am__dirstamp): @$(MKDIR_P) progs/mincreshape @: > progs/mincreshape/$(am__dirstamp) progs/mincreshape/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincreshape/$(DEPDIR) @: > progs/mincreshape/$(DEPDIR)/$(am__dirstamp) progs/mincreshape/mincreshape.$(OBJEXT): \ progs/mincreshape/$(am__dirstamp) \ progs/mincreshape/$(DEPDIR)/$(am__dirstamp) progs/mincreshape/copy_data.$(OBJEXT): \ progs/mincreshape/$(am__dirstamp) \ progs/mincreshape/$(DEPDIR)/$(am__dirstamp) mincreshape$(EXEEXT): $(mincreshape_OBJECTS) $(mincreshape_DEPENDENCIES) @rm -f mincreshape$(EXEEXT) $(LINK) $(mincreshape_OBJECTS) $(mincreshape_LDADD) $(LIBS) progs/mincsample/$(am__dirstamp): @$(MKDIR_P) progs/mincsample @: > progs/mincsample/$(am__dirstamp) progs/mincsample/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincsample/$(DEPDIR) @: > progs/mincsample/$(DEPDIR)/$(am__dirstamp) progs/mincsample/mincsample-mincsample.$(OBJEXT): \ progs/mincsample/$(am__dirstamp) \ progs/mincsample/$(DEPDIR)/$(am__dirstamp) progs/mincsample/mincsample-mt19937ar.$(OBJEXT): \ progs/mincsample/$(am__dirstamp) \ progs/mincsample/$(DEPDIR)/$(am__dirstamp) mincsample$(EXEEXT): $(mincsample_OBJECTS) $(mincsample_DEPENDENCIES) @rm -f mincsample$(EXEEXT) $(mincsample_LINK) $(mincsample_OBJECTS) $(mincsample_LDADD) $(LIBS) progs/mincstats/$(am__dirstamp): @$(MKDIR_P) progs/mincstats @: > progs/mincstats/$(am__dirstamp) progs/mincstats/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincstats/$(DEPDIR) @: > progs/mincstats/$(DEPDIR)/$(am__dirstamp) progs/mincstats/mincstats.$(OBJEXT): progs/mincstats/$(am__dirstamp) \ progs/mincstats/$(DEPDIR)/$(am__dirstamp) mincstats$(EXEEXT): $(mincstats_OBJECTS) $(mincstats_DEPENDENCIES) @rm -f mincstats$(EXEEXT) $(LINK) $(mincstats_OBJECTS) $(mincstats_LDADD) $(LIBS) conversion/minctoecat/$(am__dirstamp): @$(MKDIR_P) conversion/minctoecat @: > conversion/minctoecat/$(am__dirstamp) conversion/minctoecat/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/minctoecat/$(DEPDIR) @: > conversion/minctoecat/$(DEPDIR)/$(am__dirstamp) conversion/minctoecat/minctoecat.$(OBJEXT): \ conversion/minctoecat/$(am__dirstamp) \ conversion/minctoecat/$(DEPDIR)/$(am__dirstamp) conversion/minctoecat/ecat_write.$(OBJEXT): \ conversion/minctoecat/$(am__dirstamp) \ conversion/minctoecat/$(DEPDIR)/$(am__dirstamp) conversion/minctoecat/machine_indep.$(OBJEXT): \ conversion/minctoecat/$(am__dirstamp) \ conversion/minctoecat/$(DEPDIR)/$(am__dirstamp) minctoecat$(EXEEXT): $(minctoecat_OBJECTS) $(minctoecat_DEPENDENCIES) @rm -f minctoecat$(EXEEXT) $(LINK) $(minctoecat_OBJECTS) $(minctoecat_LDADD) $(LIBS) progs/minctoraw/$(am__dirstamp): @$(MKDIR_P) progs/minctoraw @: > progs/minctoraw/$(am__dirstamp) progs/minctoraw/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/minctoraw/$(DEPDIR) @: > progs/minctoraw/$(DEPDIR)/$(am__dirstamp) progs/minctoraw/minctoraw.$(OBJEXT): progs/minctoraw/$(am__dirstamp) \ progs/minctoraw/$(DEPDIR)/$(am__dirstamp) minctoraw$(EXEEXT): $(minctoraw_OBJECTS) $(minctoraw_DEPENDENCIES) @rm -f minctoraw$(EXEEXT) $(LINK) $(minctoraw_OBJECTS) $(minctoraw_LDADD) $(LIBS) progs/mincwindow/$(am__dirstamp): @$(MKDIR_P) progs/mincwindow @: > progs/mincwindow/$(am__dirstamp) progs/mincwindow/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/mincwindow/$(DEPDIR) @: > progs/mincwindow/$(DEPDIR)/$(am__dirstamp) progs/mincwindow/mincwindow.$(OBJEXT): \ progs/mincwindow/$(am__dirstamp) \ progs/mincwindow/$(DEPDIR)/$(am__dirstamp) mincwindow$(EXEEXT): $(mincwindow_OBJECTS) $(mincwindow_DEPENDENCIES) @rm -f mincwindow$(EXEEXT) $(LINK) $(mincwindow_OBJECTS) $(mincwindow_LDADD) $(LIBS) conversion/nifti1/$(am__dirstamp): @$(MKDIR_P) conversion/nifti1 @: > conversion/nifti1/$(am__dirstamp) conversion/nifti1/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/nifti1/$(DEPDIR) @: > conversion/nifti1/$(DEPDIR)/$(am__dirstamp) conversion/nifti1/mnc2nii.$(OBJEXT): \ conversion/nifti1/$(am__dirstamp) \ conversion/nifti1/$(DEPDIR)/$(am__dirstamp) conversion/nifti1/nifti1_io.$(OBJEXT): \ conversion/nifti1/$(am__dirstamp) \ conversion/nifti1/$(DEPDIR)/$(am__dirstamp) conversion/nifti1/znzlib.$(OBJEXT): conversion/nifti1/$(am__dirstamp) \ conversion/nifti1/$(DEPDIR)/$(am__dirstamp) mnc2nii$(EXEEXT): $(mnc2nii_OBJECTS) $(mnc2nii_DEPENDENCIES) @rm -f mnc2nii$(EXEEXT) $(LINK) $(mnc2nii_OBJECTS) $(mnc2nii_LDADD) $(LIBS) conversion/nifti1/nii2mnc.$(OBJEXT): \ conversion/nifti1/$(am__dirstamp) \ conversion/nifti1/$(DEPDIR)/$(am__dirstamp) nii2mnc$(EXEEXT): $(nii2mnc_OBJECTS) $(nii2mnc_DEPENDENCIES) @rm -f nii2mnc$(EXEEXT) $(LINK) $(nii2mnc_OBJECTS) $(nii2mnc_LDADD) $(LIBS) progs/rawtominc/$(am__dirstamp): @$(MKDIR_P) progs/rawtominc @: > progs/rawtominc/$(am__dirstamp) progs/rawtominc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/rawtominc/$(DEPDIR) @: > progs/rawtominc/$(DEPDIR)/$(am__dirstamp) progs/rawtominc/rawtominc.$(OBJEXT): progs/rawtominc/$(am__dirstamp) \ progs/rawtominc/$(DEPDIR)/$(am__dirstamp) rawtominc$(EXEEXT): $(rawtominc_OBJECTS) $(rawtominc_DEPENDENCIES) @rm -f rawtominc$(EXEEXT) $(LINK) $(rawtominc_OBJECTS) $(rawtominc_LDADD) $(LIBS) conversion/Acr_nema/read_acr_nema.$(OBJEXT): \ conversion/Acr_nema/$(am__dirstamp) \ conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) read_acr_nema$(EXEEXT): $(read_acr_nema_OBJECTS) $(read_acr_nema_DEPENDENCIES) @rm -f read_acr_nema$(EXEEXT) $(LINK) $(read_acr_nema_OBJECTS) $(read_acr_nema_LDADD) $(LIBS) progs/xfm/$(am__dirstamp): @$(MKDIR_P) progs/xfm @: > progs/xfm/$(am__dirstamp) progs/xfm/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/xfm/$(DEPDIR) @: > progs/xfm/$(DEPDIR)/$(am__dirstamp) progs/xfm/transformtags.$(OBJEXT): progs/xfm/$(am__dirstamp) \ progs/xfm/$(DEPDIR)/$(am__dirstamp) transformtags$(EXEEXT): $(transformtags_OBJECTS) $(transformtags_DEPENDENCIES) @rm -f transformtags$(EXEEXT) $(LINK) $(transformtags_OBJECTS) $(transformtags_LDADD) $(LIBS) conversion/micropet/$(am__dirstamp): @$(MKDIR_P) conversion/micropet @: > conversion/micropet/$(am__dirstamp) conversion/micropet/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/micropet/$(DEPDIR) @: > conversion/micropet/$(DEPDIR)/$(am__dirstamp) conversion/micropet/upet2mnc.$(OBJEXT): \ conversion/micropet/$(am__dirstamp) \ conversion/micropet/$(DEPDIR)/$(am__dirstamp) upet2mnc$(EXEEXT): $(upet2mnc_OBJECTS) $(upet2mnc_DEPENDENCIES) @rm -f upet2mnc$(EXEEXT) $(LINK) $(upet2mnc_OBJECTS) $(upet2mnc_LDADD) $(LIBS) conversion/vff2mnc/$(am__dirstamp): @$(MKDIR_P) conversion/vff2mnc @: > conversion/vff2mnc/$(am__dirstamp) conversion/vff2mnc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) conversion/vff2mnc/$(DEPDIR) @: > conversion/vff2mnc/$(DEPDIR)/$(am__dirstamp) conversion/vff2mnc/vff2mnc.$(OBJEXT): \ conversion/vff2mnc/$(am__dirstamp) \ conversion/vff2mnc/$(DEPDIR)/$(am__dirstamp) vff2mnc$(EXEEXT): $(vff2mnc_OBJECTS) $(vff2mnc_DEPENDENCIES) @rm -f vff2mnc$(EXEEXT) $(LINK) $(vff2mnc_OBJECTS) $(vff2mnc_LDADD) $(LIBS) progs/coordinates/$(am__dirstamp): @$(MKDIR_P) progs/coordinates @: > progs/coordinates/$(am__dirstamp) progs/coordinates/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) progs/coordinates/$(DEPDIR) @: > progs/coordinates/$(DEPDIR)/$(am__dirstamp) progs/coordinates/voxeltoworld.$(OBJEXT): \ progs/coordinates/$(am__dirstamp) \ progs/coordinates/$(DEPDIR)/$(am__dirstamp) voxeltoworld$(EXEEXT): $(voxeltoworld_OBJECTS) $(voxeltoworld_DEPENDENCIES) @rm -f voxeltoworld$(EXEEXT) $(LINK) $(voxeltoworld_OBJECTS) $(voxeltoworld_LDADD) $(LIBS) progs/coordinates/worldtovoxel.$(OBJEXT): \ progs/coordinates/$(am__dirstamp) \ progs/coordinates/$(DEPDIR)/$(am__dirstamp) worldtovoxel$(EXEEXT): $(worldtovoxel_OBJECTS) $(worldtovoxel_DEPENDENCIES) @rm -f worldtovoxel$(EXEEXT) $(LINK) $(worldtovoxel_OBJECTS) $(worldtovoxel_LDADD) $(LIBS) progs/xfm/xfm2def.$(OBJEXT): progs/xfm/$(am__dirstamp) \ progs/xfm/$(DEPDIR)/$(am__dirstamp) xfm2def$(EXEEXT): $(xfm2def_OBJECTS) $(xfm2def_DEPENDENCIES) @rm -f xfm2def$(EXEEXT) $(LINK) $(xfm2def_OBJECTS) $(xfm2def_LDADD) $(LIBS) progs/xfm/xfmconcat.$(OBJEXT): progs/xfm/$(am__dirstamp) \ progs/xfm/$(DEPDIR)/$(am__dirstamp) xfmconcat$(EXEEXT): $(xfmconcat_OBJECTS) $(xfmconcat_DEPENDENCIES) @rm -f xfmconcat$(EXEEXT) $(LINK) $(xfmconcat_OBJECTS) $(xfmconcat_LDADD) $(LIBS) progs/xfm/xfminvert.$(OBJEXT): progs/xfm/$(am__dirstamp) \ progs/xfm/$(DEPDIR)/$(am__dirstamp) xfminvert$(EXEEXT): $(xfminvert_OBJECTS) $(xfminvert_DEPENDENCIES) @rm -f xfminvert$(EXEEXT) $(LINK) $(xfminvert_OBJECTS) $(xfminvert_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_SCRIPTS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f $$d$$p; then \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \ else :; fi; \ done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; for p in $$list; do \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(dist_bin_SCRIPTS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f $$d$$p; then \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " $(dist_binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(dist_binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \ else :; fi; \ done uninstall-dist_binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_bin_SCRIPTS)'; for p in $$list; do \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f conversion/Acr_nema/acr_io.$(OBJEXT) -rm -f conversion/Acr_nema/acr_io.lo -rm -f conversion/Acr_nema/acr_test.$(OBJEXT) -rm -f conversion/Acr_nema/copy_acr_nema.$(OBJEXT) -rm -f conversion/Acr_nema/dicom_client_routines.$(OBJEXT) -rm -f conversion/Acr_nema/dicom_client_routines.lo -rm -f conversion/Acr_nema/dicom_network.$(OBJEXT) -rm -f conversion/Acr_nema/dicom_network.lo -rm -f conversion/Acr_nema/dicom_test.$(OBJEXT) -rm -f conversion/Acr_nema/dump_acr_nema.$(OBJEXT) -rm -f conversion/Acr_nema/element.$(OBJEXT) -rm -f conversion/Acr_nema/element.lo -rm -f conversion/Acr_nema/extract_acr_nema.$(OBJEXT) -rm -f conversion/Acr_nema/file_io.$(OBJEXT) -rm -f conversion/Acr_nema/file_io.lo -rm -f conversion/Acr_nema/globals.$(OBJEXT) -rm -f conversion/Acr_nema/globals.lo -rm -f conversion/Acr_nema/group.$(OBJEXT) -rm -f conversion/Acr_nema/group.lo -rm -f conversion/Acr_nema/message.$(OBJEXT) -rm -f conversion/Acr_nema/message.lo -rm -f conversion/Acr_nema/read_acr_nema.$(OBJEXT) -rm -f conversion/Acr_nema/value_repr.$(OBJEXT) -rm -f conversion/Acr_nema/value_repr.lo -rm -f conversion/dcm2mnc/dcm2mnc.$(OBJEXT) -rm -f conversion/dcm2mnc/dicom_read.$(OBJEXT) -rm -f conversion/dcm2mnc/dicom_to_minc.$(OBJEXT) -rm -f conversion/dcm2mnc/minc_file.$(OBJEXT) -rm -f conversion/dcm2mnc/progress.$(OBJEXT) -rm -f conversion/dcm2mnc/siemens_to_dicom.$(OBJEXT) -rm -f conversion/dcm2mnc/string_to_filename.$(OBJEXT) -rm -f conversion/ecattominc/ecat_file.$(OBJEXT) -rm -f conversion/ecattominc/ecattominc.$(OBJEXT) -rm -f conversion/ecattominc/insertblood.$(OBJEXT) -rm -f conversion/ecattominc/machine_indep.$(OBJEXT) -rm -f conversion/image_filters/byte_swap.$(OBJEXT) -rm -f conversion/image_filters/extract.$(OBJEXT) -rm -f conversion/micropet/upet2mnc.$(OBJEXT) -rm -f conversion/minctoecat/ecat_write.$(OBJEXT) -rm -f conversion/minctoecat/machine_indep.$(OBJEXT) -rm -f conversion/minctoecat/minctoecat.$(OBJEXT) -rm -f conversion/nifti1/mnc2nii.$(OBJEXT) -rm -f conversion/nifti1/nifti1_io.$(OBJEXT) -rm -f conversion/nifti1/nii2mnc.$(OBJEXT) -rm -f conversion/nifti1/znzlib.$(OBJEXT) -rm -f conversion/vff2mnc/vff2mnc.$(OBJEXT) -rm -f libsrc/ParseArgv.$(OBJEXT) -rm -f libsrc/ParseArgv.lo -rm -f libsrc/dim_conversion.$(OBJEXT) -rm -f libsrc/dim_conversion.lo -rm -f libsrc/hdf_convenience.$(OBJEXT) -rm -f libsrc/hdf_convenience.lo -rm -f libsrc/image_conversion.$(OBJEXT) -rm -f libsrc/image_conversion.lo -rm -f libsrc/minc_compat.$(OBJEXT) -rm -f libsrc/minc_compat.lo -rm -f libsrc/minc_convenience.$(OBJEXT) -rm -f libsrc/minc_convenience.lo -rm -f libsrc/minc_error.$(OBJEXT) -rm -f libsrc/minc_error.lo -rm -f libsrc/minc_simple.$(OBJEXT) -rm -f libsrc/minc_simple.lo -rm -f libsrc/nd_loop.$(OBJEXT) -rm -f libsrc/nd_loop.lo -rm -f libsrc/netcdf_convenience.$(OBJEXT) -rm -f libsrc/netcdf_convenience.lo -rm -f libsrc/read_file_names.$(OBJEXT) -rm -f libsrc/read_file_names.lo -rm -f libsrc/time_stamp.$(OBJEXT) -rm -f libsrc/time_stamp.lo -rm -f libsrc/value_conversion.$(OBJEXT) -rm -f libsrc/value_conversion.lo -rm -f libsrc/voxel_loop.$(OBJEXT) -rm -f libsrc/voxel_loop.lo -rm -f libsrc2/convert.$(OBJEXT) -rm -f libsrc2/convert.lo -rm -f libsrc2/datatype.$(OBJEXT) -rm -f libsrc2/datatype.lo -rm -f libsrc2/dimension.$(OBJEXT) -rm -f libsrc2/dimension.lo -rm -f libsrc2/free.$(OBJEXT) -rm -f libsrc2/free.lo -rm -f libsrc2/grpattr.$(OBJEXT) -rm -f libsrc2/grpattr.lo -rm -f libsrc2/hyper.$(OBJEXT) -rm -f libsrc2/hyper.lo -rm -f libsrc2/label.$(OBJEXT) -rm -f libsrc2/label.lo -rm -f libsrc2/m2util.$(OBJEXT) -rm -f libsrc2/m2util.lo -rm -f libsrc2/record.$(OBJEXT) -rm -f libsrc2/record.lo -rm -f libsrc2/slice.$(OBJEXT) -rm -f libsrc2/slice.lo -rm -f libsrc2/valid.$(OBJEXT) -rm -f libsrc2/valid.lo -rm -f libsrc2/volprops.$(OBJEXT) -rm -f libsrc2/volprops.lo -rm -f libsrc2/volume.$(OBJEXT) -rm -f libsrc2/volume.lo -rm -f progs/Proglib/convert_origin_to_start.$(OBJEXT) -rm -f progs/coordinates/voxeltoworld.$(OBJEXT) -rm -f progs/coordinates/worldtovoxel.$(OBJEXT) -rm -f progs/minc_modify_header/minc_modify_header.$(OBJEXT) -rm -f progs/mincaverage/mincaverage.$(OBJEXT) -rm -f progs/mincblob/mincblob.$(OBJEXT) -rm -f progs/minccalc/minccalc-eval.$(OBJEXT) -rm -f progs/minccalc/minccalc-gram.$(OBJEXT) -rm -f progs/minccalc/minccalc-ident.$(OBJEXT) -rm -f progs/minccalc/minccalc-lex.$(OBJEXT) -rm -f progs/minccalc/minccalc-minccalc.$(OBJEXT) -rm -f progs/minccalc/minccalc-node.$(OBJEXT) -rm -f progs/minccalc/minccalc-optim.$(OBJEXT) -rm -f progs/minccalc/minccalc-scalar.$(OBJEXT) -rm -f progs/minccalc/minccalc-sym.$(OBJEXT) -rm -f progs/minccalc/minccalc-vector.$(OBJEXT) -rm -f progs/minccmp/minccmp.$(OBJEXT) -rm -f progs/mincconcat/mincconcat.$(OBJEXT) -rm -f progs/mincconvert/mincconvert.$(OBJEXT) -rm -f progs/minccopy/minccopy.$(OBJEXT) -rm -f progs/mincdump/dumplib.$(OBJEXT) -rm -f progs/mincdump/mincdump.$(OBJEXT) -rm -f progs/mincdump/vardata.$(OBJEXT) -rm -f progs/mincexample/mincexample1.$(OBJEXT) -rm -f progs/mincexample/mincexample2.$(OBJEXT) -rm -f progs/mincexpand/mincexpand.$(OBJEXT) -rm -f progs/mincextract/mincextract.$(OBJEXT) -rm -f progs/mincgen/escapes.$(OBJEXT) -rm -f progs/mincgen/genlib.$(OBJEXT) -rm -f progs/mincgen/getfill.$(OBJEXT) -rm -f progs/mincgen/init.$(OBJEXT) -rm -f progs/mincgen/load.$(OBJEXT) -rm -f progs/mincgen/main.$(OBJEXT) -rm -f progs/mincgen/ncgentab.$(OBJEXT) -rm -f progs/mincgen/ncgenyy.$(OBJEXT) -rm -f progs/mincinfo/mincinfo.$(OBJEXT) -rm -f progs/minclookup/minclookup.$(OBJEXT) -rm -f progs/mincmakescalar/mincmakescalar.$(OBJEXT) -rm -f progs/mincmakevector/mincmakevector.$(OBJEXT) -rm -f progs/mincmath/mincmath.$(OBJEXT) -rm -f progs/mincmorph/mincmorph-kernel_io.$(OBJEXT) -rm -f progs/mincmorph/mincmorph-kernel_ops.$(OBJEXT) -rm -f progs/mincmorph/mincmorph-mincmorph.$(OBJEXT) -rm -f progs/mincresample/mincresample.$(OBJEXT) -rm -f progs/mincresample/resample_volumes.$(OBJEXT) -rm -f progs/mincreshape/copy_data.$(OBJEXT) -rm -f progs/mincreshape/mincreshape.$(OBJEXT) -rm -f progs/mincsample/mincsample-mincsample.$(OBJEXT) -rm -f progs/mincsample/mincsample-mt19937ar.$(OBJEXT) -rm -f progs/mincstats/mincstats.$(OBJEXT) -rm -f progs/minctoraw/minctoraw.$(OBJEXT) -rm -f progs/mincview/invert_raw_image.$(OBJEXT) -rm -f progs/mincwindow/mincwindow.$(OBJEXT) -rm -f progs/rawtominc/rawtominc.$(OBJEXT) -rm -f progs/xfm/transformtags.$(OBJEXT) -rm -f progs/xfm/xfm2def.$(OBJEXT) -rm -f progs/xfm/xfmconcat.$(OBJEXT) -rm -f progs/xfm/xfminvert.$(OBJEXT) -rm -f volume_io/Geometry/colour.$(OBJEXT) -rm -f volume_io/Geometry/colour.lo -rm -f volume_io/Geometry/colour_def.$(OBJEXT) -rm -f volume_io/Geometry/colour_def.lo -rm -f volume_io/Geometry/gaussian.$(OBJEXT) -rm -f volume_io/Geometry/gaussian.lo -rm -f volume_io/Geometry/inverse.$(OBJEXT) -rm -f volume_io/Geometry/inverse.lo -rm -f volume_io/Geometry/newton.$(OBJEXT) -rm -f volume_io/Geometry/newton.lo -rm -f volume_io/Geometry/points.$(OBJEXT) -rm -f volume_io/Geometry/points.lo -rm -f volume_io/Geometry/splines.$(OBJEXT) -rm -f volume_io/Geometry/splines.lo -rm -f volume_io/Geometry/tensors.$(OBJEXT) -rm -f volume_io/Geometry/tensors.lo -rm -f volume_io/Geometry/transforms.$(OBJEXT) -rm -f volume_io/Geometry/transforms.lo -rm -f volume_io/MNI_formats/gen_xf_io.$(OBJEXT) -rm -f volume_io/MNI_formats/gen_xf_io.lo -rm -f volume_io/MNI_formats/gen_xfs.$(OBJEXT) -rm -f volume_io/MNI_formats/gen_xfs.lo -rm -f volume_io/MNI_formats/grid_transforms.$(OBJEXT) -rm -f volume_io/MNI_formats/grid_transforms.lo -rm -f volume_io/MNI_formats/mni_io.$(OBJEXT) -rm -f volume_io/MNI_formats/mni_io.lo -rm -f volume_io/MNI_formats/tag_points.$(OBJEXT) -rm -f volume_io/MNI_formats/tag_points.lo -rm -f volume_io/MNI_formats/thin_plate_spline.$(OBJEXT) -rm -f volume_io/MNI_formats/thin_plate_spline.lo -rm -f volume_io/Prog_utils/alloc.$(OBJEXT) -rm -f volume_io/Prog_utils/alloc.lo -rm -f volume_io/Prog_utils/alloc_check.$(OBJEXT) -rm -f volume_io/Prog_utils/alloc_check.lo -rm -f volume_io/Prog_utils/arrays.$(OBJEXT) -rm -f volume_io/Prog_utils/arrays.lo -rm -f volume_io/Prog_utils/files.$(OBJEXT) -rm -f volume_io/Prog_utils/files.lo -rm -f volume_io/Prog_utils/print.$(OBJEXT) -rm -f volume_io/Prog_utils/print.lo -rm -f volume_io/Prog_utils/progress.$(OBJEXT) -rm -f volume_io/Prog_utils/progress.lo -rm -f volume_io/Prog_utils/string.$(OBJEXT) -rm -f volume_io/Prog_utils/string.lo -rm -f volume_io/Prog_utils/time.$(OBJEXT) -rm -f volume_io/Prog_utils/time.lo -rm -f volume_io/Volumes/evaluate.$(OBJEXT) -rm -f volume_io/Volumes/evaluate.lo -rm -f volume_io/Volumes/get_hyperslab.$(OBJEXT) -rm -f volume_io/Volumes/get_hyperslab.lo -rm -f volume_io/Volumes/input_free.$(OBJEXT) -rm -f volume_io/Volumes/input_free.lo -rm -f volume_io/Volumes/input_mnc.$(OBJEXT) -rm -f volume_io/Volumes/input_mnc.lo -rm -f volume_io/Volumes/input_volume.$(OBJEXT) -rm -f volume_io/Volumes/input_volume.lo -rm -f volume_io/Volumes/multidim_arrays.$(OBJEXT) -rm -f volume_io/Volumes/multidim_arrays.lo -rm -f volume_io/Volumes/output_mnc.$(OBJEXT) -rm -f volume_io/Volumes/output_mnc.lo -rm -f volume_io/Volumes/output_volume.$(OBJEXT) -rm -f volume_io/Volumes/output_volume.lo -rm -f volume_io/Volumes/set_hyperslab.$(OBJEXT) -rm -f volume_io/Volumes/set_hyperslab.lo -rm -f volume_io/Volumes/volume_cache.$(OBJEXT) -rm -f volume_io/Volumes/volume_cache.lo -rm -f volume_io/Volumes/volumes.$(OBJEXT) -rm -f volume_io/Volumes/volumes.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/acr_io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/acr_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/copy_acr_nema.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/dicom_client_routines.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/dicom_network.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/dicom_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/dump_acr_nema.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/element.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/extract_acr_nema.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/file_io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/globals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/group.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/message.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/read_acr_nema.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/Acr_nema/$(DEPDIR)/value_repr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/dcm2mnc/$(DEPDIR)/dcm2mnc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/dcm2mnc/$(DEPDIR)/dicom_read.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/dcm2mnc/$(DEPDIR)/dicom_to_minc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/dcm2mnc/$(DEPDIR)/minc_file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/dcm2mnc/$(DEPDIR)/progress.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/dcm2mnc/$(DEPDIR)/siemens_to_dicom.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/dcm2mnc/$(DEPDIR)/string_to_filename.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/ecattominc/$(DEPDIR)/ecat_file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/ecattominc/$(DEPDIR)/ecattominc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/ecattominc/$(DEPDIR)/insertblood.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/ecattominc/$(DEPDIR)/machine_indep.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/image_filters/$(DEPDIR)/byte_swap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/image_filters/$(DEPDIR)/extract.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/micropet/$(DEPDIR)/upet2mnc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/minctoecat/$(DEPDIR)/ecat_write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/minctoecat/$(DEPDIR)/machine_indep.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/minctoecat/$(DEPDIR)/minctoecat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/nifti1/$(DEPDIR)/mnc2nii.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/nifti1/$(DEPDIR)/nifti1_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/nifti1/$(DEPDIR)/nii2mnc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/nifti1/$(DEPDIR)/znzlib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@conversion/vff2mnc/$(DEPDIR)/vff2mnc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/ParseArgv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/dim_conversion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/hdf_convenience.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/image_conversion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/minc_compat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/minc_convenience.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/minc_error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/minc_simple.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/nd_loop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/netcdf_convenience.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/read_file_names.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/time_stamp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/value_conversion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc/$(DEPDIR)/voxel_loop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/convert.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/datatype.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/dimension.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/free.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/grpattr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/hyper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/label.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/m2util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/slice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/valid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/volprops.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libsrc2/$(DEPDIR)/volume.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/Proglib/$(DEPDIR)/convert_origin_to_start.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/coordinates/$(DEPDIR)/voxeltoworld.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/coordinates/$(DEPDIR)/worldtovoxel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minc_modify_header/$(DEPDIR)/minc_modify_header.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincaverage/$(DEPDIR)/mincaverage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincblob/$(DEPDIR)/mincblob.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-eval.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-gram.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-ident.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-lex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-minccalc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-node.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-optim.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-scalar.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-sym.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccalc/$(DEPDIR)/minccalc-vector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccmp/$(DEPDIR)/minccmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincconcat/$(DEPDIR)/mincconcat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincconvert/$(DEPDIR)/mincconvert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minccopy/$(DEPDIR)/minccopy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincdump/$(DEPDIR)/dumplib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincdump/$(DEPDIR)/mincdump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincdump/$(DEPDIR)/vardata.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincexample/$(DEPDIR)/mincexample1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincexample/$(DEPDIR)/mincexample2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincexpand/$(DEPDIR)/mincexpand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincextract/$(DEPDIR)/mincextract.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/escapes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/genlib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/getfill.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/ncgentab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincgen/$(DEPDIR)/ncgenyy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincinfo/$(DEPDIR)/mincinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minclookup/$(DEPDIR)/minclookup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincmakescalar/$(DEPDIR)/mincmakescalar.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincmakevector/$(DEPDIR)/mincmakevector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincmath/$(DEPDIR)/mincmath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincmorph/$(DEPDIR)/mincmorph-kernel_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincmorph/$(DEPDIR)/mincmorph-kernel_ops.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincmorph/$(DEPDIR)/mincmorph-mincmorph.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincresample/$(DEPDIR)/mincresample.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincresample/$(DEPDIR)/resample_volumes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincreshape/$(DEPDIR)/copy_data.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincreshape/$(DEPDIR)/mincreshape.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincsample/$(DEPDIR)/mincsample-mincsample.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincsample/$(DEPDIR)/mincsample-mt19937ar.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincstats/$(DEPDIR)/mincstats.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/minctoraw/$(DEPDIR)/minctoraw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincview/$(DEPDIR)/invert_raw_image.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/mincwindow/$(DEPDIR)/mincwindow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/rawtominc/$(DEPDIR)/rawtominc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/xfm/$(DEPDIR)/transformtags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/xfm/$(DEPDIR)/xfm2def.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/xfm/$(DEPDIR)/xfmconcat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@progs/xfm/$(DEPDIR)/xfminvert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/colour.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/colour_def.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/gaussian.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/inverse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/newton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/points.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/splines.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/tensors.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Geometry/$(DEPDIR)/transforms.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/MNI_formats/$(DEPDIR)/gen_xf_io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/MNI_formats/$(DEPDIR)/gen_xfs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/MNI_formats/$(DEPDIR)/grid_transforms.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/MNI_formats/$(DEPDIR)/mni_io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/MNI_formats/$(DEPDIR)/tag_points.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/MNI_formats/$(DEPDIR)/thin_plate_spline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/alloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/alloc_check.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/arrays.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/files.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/print.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/progress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Prog_utils/$(DEPDIR)/time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/evaluate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/get_hyperslab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/input_free.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/input_mnc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/input_volume.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/multidim_arrays.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/output_mnc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/output_volume.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/set_hyperslab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/volume_cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@volume_io/Volumes/$(DEPDIR)/volumes.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ mv -f $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ mv -f $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ mv -f $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< progs/minccalc/minccalc-minccalc.o: progs/minccalc/minccalc.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-minccalc.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-minccalc.Tpo -c -o progs/minccalc/minccalc-minccalc.o `test -f 'progs/minccalc/minccalc.c' || echo '$(srcdir)/'`progs/minccalc/minccalc.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-minccalc.Tpo progs/minccalc/$(DEPDIR)/minccalc-minccalc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/minccalc.c' object='progs/minccalc/minccalc-minccalc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-minccalc.o `test -f 'progs/minccalc/minccalc.c' || echo '$(srcdir)/'`progs/minccalc/minccalc.c progs/minccalc/minccalc-minccalc.obj: progs/minccalc/minccalc.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-minccalc.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-minccalc.Tpo -c -o progs/minccalc/minccalc-minccalc.obj `if test -f 'progs/minccalc/minccalc.c'; then $(CYGPATH_W) 'progs/minccalc/minccalc.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/minccalc.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-minccalc.Tpo progs/minccalc/$(DEPDIR)/minccalc-minccalc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/minccalc.c' object='progs/minccalc/minccalc-minccalc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-minccalc.obj `if test -f 'progs/minccalc/minccalc.c'; then $(CYGPATH_W) 'progs/minccalc/minccalc.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/minccalc.c'; fi` progs/minccalc/minccalc-gram.o: progs/minccalc/gram.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-gram.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-gram.Tpo -c -o progs/minccalc/minccalc-gram.o `test -f 'progs/minccalc/gram.c' || echo '$(srcdir)/'`progs/minccalc/gram.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-gram.Tpo progs/minccalc/$(DEPDIR)/minccalc-gram.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/gram.c' object='progs/minccalc/minccalc-gram.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-gram.o `test -f 'progs/minccalc/gram.c' || echo '$(srcdir)/'`progs/minccalc/gram.c progs/minccalc/minccalc-gram.obj: progs/minccalc/gram.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-gram.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-gram.Tpo -c -o progs/minccalc/minccalc-gram.obj `if test -f 'progs/minccalc/gram.c'; then $(CYGPATH_W) 'progs/minccalc/gram.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/gram.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-gram.Tpo progs/minccalc/$(DEPDIR)/minccalc-gram.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/gram.c' object='progs/minccalc/minccalc-gram.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-gram.obj `if test -f 'progs/minccalc/gram.c'; then $(CYGPATH_W) 'progs/minccalc/gram.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/gram.c'; fi` progs/minccalc/minccalc-eval.o: progs/minccalc/eval.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-eval.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-eval.Tpo -c -o progs/minccalc/minccalc-eval.o `test -f 'progs/minccalc/eval.c' || echo '$(srcdir)/'`progs/minccalc/eval.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-eval.Tpo progs/minccalc/$(DEPDIR)/minccalc-eval.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/eval.c' object='progs/minccalc/minccalc-eval.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-eval.o `test -f 'progs/minccalc/eval.c' || echo '$(srcdir)/'`progs/minccalc/eval.c progs/minccalc/minccalc-eval.obj: progs/minccalc/eval.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-eval.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-eval.Tpo -c -o progs/minccalc/minccalc-eval.obj `if test -f 'progs/minccalc/eval.c'; then $(CYGPATH_W) 'progs/minccalc/eval.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/eval.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-eval.Tpo progs/minccalc/$(DEPDIR)/minccalc-eval.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/eval.c' object='progs/minccalc/minccalc-eval.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-eval.obj `if test -f 'progs/minccalc/eval.c'; then $(CYGPATH_W) 'progs/minccalc/eval.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/eval.c'; fi` progs/minccalc/minccalc-ident.o: progs/minccalc/ident.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-ident.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-ident.Tpo -c -o progs/minccalc/minccalc-ident.o `test -f 'progs/minccalc/ident.c' || echo '$(srcdir)/'`progs/minccalc/ident.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-ident.Tpo progs/minccalc/$(DEPDIR)/minccalc-ident.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/ident.c' object='progs/minccalc/minccalc-ident.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-ident.o `test -f 'progs/minccalc/ident.c' || echo '$(srcdir)/'`progs/minccalc/ident.c progs/minccalc/minccalc-ident.obj: progs/minccalc/ident.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-ident.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-ident.Tpo -c -o progs/minccalc/minccalc-ident.obj `if test -f 'progs/minccalc/ident.c'; then $(CYGPATH_W) 'progs/minccalc/ident.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/ident.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-ident.Tpo progs/minccalc/$(DEPDIR)/minccalc-ident.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/ident.c' object='progs/minccalc/minccalc-ident.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-ident.obj `if test -f 'progs/minccalc/ident.c'; then $(CYGPATH_W) 'progs/minccalc/ident.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/ident.c'; fi` progs/minccalc/minccalc-lex.o: progs/minccalc/lex.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-lex.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-lex.Tpo -c -o progs/minccalc/minccalc-lex.o `test -f 'progs/minccalc/lex.c' || echo '$(srcdir)/'`progs/minccalc/lex.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-lex.Tpo progs/minccalc/$(DEPDIR)/minccalc-lex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/lex.c' object='progs/minccalc/minccalc-lex.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-lex.o `test -f 'progs/minccalc/lex.c' || echo '$(srcdir)/'`progs/minccalc/lex.c progs/minccalc/minccalc-lex.obj: progs/minccalc/lex.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-lex.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-lex.Tpo -c -o progs/minccalc/minccalc-lex.obj `if test -f 'progs/minccalc/lex.c'; then $(CYGPATH_W) 'progs/minccalc/lex.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/lex.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-lex.Tpo progs/minccalc/$(DEPDIR)/minccalc-lex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/lex.c' object='progs/minccalc/minccalc-lex.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-lex.obj `if test -f 'progs/minccalc/lex.c'; then $(CYGPATH_W) 'progs/minccalc/lex.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/lex.c'; fi` progs/minccalc/minccalc-node.o: progs/minccalc/node.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-node.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-node.Tpo -c -o progs/minccalc/minccalc-node.o `test -f 'progs/minccalc/node.c' || echo '$(srcdir)/'`progs/minccalc/node.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-node.Tpo progs/minccalc/$(DEPDIR)/minccalc-node.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/node.c' object='progs/minccalc/minccalc-node.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-node.o `test -f 'progs/minccalc/node.c' || echo '$(srcdir)/'`progs/minccalc/node.c progs/minccalc/minccalc-node.obj: progs/minccalc/node.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-node.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-node.Tpo -c -o progs/minccalc/minccalc-node.obj `if test -f 'progs/minccalc/node.c'; then $(CYGPATH_W) 'progs/minccalc/node.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/node.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-node.Tpo progs/minccalc/$(DEPDIR)/minccalc-node.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/node.c' object='progs/minccalc/minccalc-node.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-node.obj `if test -f 'progs/minccalc/node.c'; then $(CYGPATH_W) 'progs/minccalc/node.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/node.c'; fi` progs/minccalc/minccalc-optim.o: progs/minccalc/optim.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-optim.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-optim.Tpo -c -o progs/minccalc/minccalc-optim.o `test -f 'progs/minccalc/optim.c' || echo '$(srcdir)/'`progs/minccalc/optim.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-optim.Tpo progs/minccalc/$(DEPDIR)/minccalc-optim.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/optim.c' object='progs/minccalc/minccalc-optim.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-optim.o `test -f 'progs/minccalc/optim.c' || echo '$(srcdir)/'`progs/minccalc/optim.c progs/minccalc/minccalc-optim.obj: progs/minccalc/optim.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-optim.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-optim.Tpo -c -o progs/minccalc/minccalc-optim.obj `if test -f 'progs/minccalc/optim.c'; then $(CYGPATH_W) 'progs/minccalc/optim.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/optim.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-optim.Tpo progs/minccalc/$(DEPDIR)/minccalc-optim.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/optim.c' object='progs/minccalc/minccalc-optim.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-optim.obj `if test -f 'progs/minccalc/optim.c'; then $(CYGPATH_W) 'progs/minccalc/optim.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/optim.c'; fi` progs/minccalc/minccalc-scalar.o: progs/minccalc/scalar.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-scalar.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-scalar.Tpo -c -o progs/minccalc/minccalc-scalar.o `test -f 'progs/minccalc/scalar.c' || echo '$(srcdir)/'`progs/minccalc/scalar.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-scalar.Tpo progs/minccalc/$(DEPDIR)/minccalc-scalar.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/scalar.c' object='progs/minccalc/minccalc-scalar.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-scalar.o `test -f 'progs/minccalc/scalar.c' || echo '$(srcdir)/'`progs/minccalc/scalar.c progs/minccalc/minccalc-scalar.obj: progs/minccalc/scalar.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-scalar.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-scalar.Tpo -c -o progs/minccalc/minccalc-scalar.obj `if test -f 'progs/minccalc/scalar.c'; then $(CYGPATH_W) 'progs/minccalc/scalar.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/scalar.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-scalar.Tpo progs/minccalc/$(DEPDIR)/minccalc-scalar.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/scalar.c' object='progs/minccalc/minccalc-scalar.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-scalar.obj `if test -f 'progs/minccalc/scalar.c'; then $(CYGPATH_W) 'progs/minccalc/scalar.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/scalar.c'; fi` progs/minccalc/minccalc-sym.o: progs/minccalc/sym.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-sym.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-sym.Tpo -c -o progs/minccalc/minccalc-sym.o `test -f 'progs/minccalc/sym.c' || echo '$(srcdir)/'`progs/minccalc/sym.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-sym.Tpo progs/minccalc/$(DEPDIR)/minccalc-sym.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/sym.c' object='progs/minccalc/minccalc-sym.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-sym.o `test -f 'progs/minccalc/sym.c' || echo '$(srcdir)/'`progs/minccalc/sym.c progs/minccalc/minccalc-sym.obj: progs/minccalc/sym.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-sym.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-sym.Tpo -c -o progs/minccalc/minccalc-sym.obj `if test -f 'progs/minccalc/sym.c'; then $(CYGPATH_W) 'progs/minccalc/sym.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/sym.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-sym.Tpo progs/minccalc/$(DEPDIR)/minccalc-sym.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/sym.c' object='progs/minccalc/minccalc-sym.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-sym.obj `if test -f 'progs/minccalc/sym.c'; then $(CYGPATH_W) 'progs/minccalc/sym.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/sym.c'; fi` progs/minccalc/minccalc-vector.o: progs/minccalc/vector.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-vector.o -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-vector.Tpo -c -o progs/minccalc/minccalc-vector.o `test -f 'progs/minccalc/vector.c' || echo '$(srcdir)/'`progs/minccalc/vector.c @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-vector.Tpo progs/minccalc/$(DEPDIR)/minccalc-vector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/vector.c' object='progs/minccalc/minccalc-vector.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-vector.o `test -f 'progs/minccalc/vector.c' || echo '$(srcdir)/'`progs/minccalc/vector.c progs/minccalc/minccalc-vector.obj: progs/minccalc/vector.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -MT progs/minccalc/minccalc-vector.obj -MD -MP -MF progs/minccalc/$(DEPDIR)/minccalc-vector.Tpo -c -o progs/minccalc/minccalc-vector.obj `if test -f 'progs/minccalc/vector.c'; then $(CYGPATH_W) 'progs/minccalc/vector.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/vector.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/minccalc/$(DEPDIR)/minccalc-vector.Tpo progs/minccalc/$(DEPDIR)/minccalc-vector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/minccalc/vector.c' object='progs/minccalc/minccalc-vector.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(minccalc_CFLAGS) $(CFLAGS) -c -o progs/minccalc/minccalc-vector.obj `if test -f 'progs/minccalc/vector.c'; then $(CYGPATH_W) 'progs/minccalc/vector.c'; else $(CYGPATH_W) '$(srcdir)/progs/minccalc/vector.c'; fi` progs/mincmorph/mincmorph-mincmorph.o: progs/mincmorph/mincmorph.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -MT progs/mincmorph/mincmorph-mincmorph.o -MD -MP -MF progs/mincmorph/$(DEPDIR)/mincmorph-mincmorph.Tpo -c -o progs/mincmorph/mincmorph-mincmorph.o `test -f 'progs/mincmorph/mincmorph.c' || echo '$(srcdir)/'`progs/mincmorph/mincmorph.c @am__fastdepCC_TRUE@ mv -f progs/mincmorph/$(DEPDIR)/mincmorph-mincmorph.Tpo progs/mincmorph/$(DEPDIR)/mincmorph-mincmorph.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincmorph/mincmorph.c' object='progs/mincmorph/mincmorph-mincmorph.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -c -o progs/mincmorph/mincmorph-mincmorph.o `test -f 'progs/mincmorph/mincmorph.c' || echo '$(srcdir)/'`progs/mincmorph/mincmorph.c progs/mincmorph/mincmorph-mincmorph.obj: progs/mincmorph/mincmorph.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -MT progs/mincmorph/mincmorph-mincmorph.obj -MD -MP -MF progs/mincmorph/$(DEPDIR)/mincmorph-mincmorph.Tpo -c -o progs/mincmorph/mincmorph-mincmorph.obj `if test -f 'progs/mincmorph/mincmorph.c'; then $(CYGPATH_W) 'progs/mincmorph/mincmorph.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincmorph/mincmorph.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/mincmorph/$(DEPDIR)/mincmorph-mincmorph.Tpo progs/mincmorph/$(DEPDIR)/mincmorph-mincmorph.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincmorph/mincmorph.c' object='progs/mincmorph/mincmorph-mincmorph.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -c -o progs/mincmorph/mincmorph-mincmorph.obj `if test -f 'progs/mincmorph/mincmorph.c'; then $(CYGPATH_W) 'progs/mincmorph/mincmorph.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincmorph/mincmorph.c'; fi` progs/mincmorph/mincmorph-kernel_io.o: progs/mincmorph/kernel_io.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -MT progs/mincmorph/mincmorph-kernel_io.o -MD -MP -MF progs/mincmorph/$(DEPDIR)/mincmorph-kernel_io.Tpo -c -o progs/mincmorph/mincmorph-kernel_io.o `test -f 'progs/mincmorph/kernel_io.c' || echo '$(srcdir)/'`progs/mincmorph/kernel_io.c @am__fastdepCC_TRUE@ mv -f progs/mincmorph/$(DEPDIR)/mincmorph-kernel_io.Tpo progs/mincmorph/$(DEPDIR)/mincmorph-kernel_io.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincmorph/kernel_io.c' object='progs/mincmorph/mincmorph-kernel_io.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -c -o progs/mincmorph/mincmorph-kernel_io.o `test -f 'progs/mincmorph/kernel_io.c' || echo '$(srcdir)/'`progs/mincmorph/kernel_io.c progs/mincmorph/mincmorph-kernel_io.obj: progs/mincmorph/kernel_io.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -MT progs/mincmorph/mincmorph-kernel_io.obj -MD -MP -MF progs/mincmorph/$(DEPDIR)/mincmorph-kernel_io.Tpo -c -o progs/mincmorph/mincmorph-kernel_io.obj `if test -f 'progs/mincmorph/kernel_io.c'; then $(CYGPATH_W) 'progs/mincmorph/kernel_io.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincmorph/kernel_io.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/mincmorph/$(DEPDIR)/mincmorph-kernel_io.Tpo progs/mincmorph/$(DEPDIR)/mincmorph-kernel_io.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincmorph/kernel_io.c' object='progs/mincmorph/mincmorph-kernel_io.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -c -o progs/mincmorph/mincmorph-kernel_io.obj `if test -f 'progs/mincmorph/kernel_io.c'; then $(CYGPATH_W) 'progs/mincmorph/kernel_io.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincmorph/kernel_io.c'; fi` progs/mincmorph/mincmorph-kernel_ops.o: progs/mincmorph/kernel_ops.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -MT progs/mincmorph/mincmorph-kernel_ops.o -MD -MP -MF progs/mincmorph/$(DEPDIR)/mincmorph-kernel_ops.Tpo -c -o progs/mincmorph/mincmorph-kernel_ops.o `test -f 'progs/mincmorph/kernel_ops.c' || echo '$(srcdir)/'`progs/mincmorph/kernel_ops.c @am__fastdepCC_TRUE@ mv -f progs/mincmorph/$(DEPDIR)/mincmorph-kernel_ops.Tpo progs/mincmorph/$(DEPDIR)/mincmorph-kernel_ops.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincmorph/kernel_ops.c' object='progs/mincmorph/mincmorph-kernel_ops.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -c -o progs/mincmorph/mincmorph-kernel_ops.o `test -f 'progs/mincmorph/kernel_ops.c' || echo '$(srcdir)/'`progs/mincmorph/kernel_ops.c progs/mincmorph/mincmorph-kernel_ops.obj: progs/mincmorph/kernel_ops.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -MT progs/mincmorph/mincmorph-kernel_ops.obj -MD -MP -MF progs/mincmorph/$(DEPDIR)/mincmorph-kernel_ops.Tpo -c -o progs/mincmorph/mincmorph-kernel_ops.obj `if test -f 'progs/mincmorph/kernel_ops.c'; then $(CYGPATH_W) 'progs/mincmorph/kernel_ops.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincmorph/kernel_ops.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/mincmorph/$(DEPDIR)/mincmorph-kernel_ops.Tpo progs/mincmorph/$(DEPDIR)/mincmorph-kernel_ops.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincmorph/kernel_ops.c' object='progs/mincmorph/mincmorph-kernel_ops.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincmorph_CFLAGS) $(CFLAGS) -c -o progs/mincmorph/mincmorph-kernel_ops.obj `if test -f 'progs/mincmorph/kernel_ops.c'; then $(CYGPATH_W) 'progs/mincmorph/kernel_ops.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincmorph/kernel_ops.c'; fi` progs/mincsample/mincsample-mincsample.o: progs/mincsample/mincsample.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -MT progs/mincsample/mincsample-mincsample.o -MD -MP -MF progs/mincsample/$(DEPDIR)/mincsample-mincsample.Tpo -c -o progs/mincsample/mincsample-mincsample.o `test -f 'progs/mincsample/mincsample.c' || echo '$(srcdir)/'`progs/mincsample/mincsample.c @am__fastdepCC_TRUE@ mv -f progs/mincsample/$(DEPDIR)/mincsample-mincsample.Tpo progs/mincsample/$(DEPDIR)/mincsample-mincsample.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincsample/mincsample.c' object='progs/mincsample/mincsample-mincsample.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -c -o progs/mincsample/mincsample-mincsample.o `test -f 'progs/mincsample/mincsample.c' || echo '$(srcdir)/'`progs/mincsample/mincsample.c progs/mincsample/mincsample-mincsample.obj: progs/mincsample/mincsample.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -MT progs/mincsample/mincsample-mincsample.obj -MD -MP -MF progs/mincsample/$(DEPDIR)/mincsample-mincsample.Tpo -c -o progs/mincsample/mincsample-mincsample.obj `if test -f 'progs/mincsample/mincsample.c'; then $(CYGPATH_W) 'progs/mincsample/mincsample.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincsample/mincsample.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/mincsample/$(DEPDIR)/mincsample-mincsample.Tpo progs/mincsample/$(DEPDIR)/mincsample-mincsample.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincsample/mincsample.c' object='progs/mincsample/mincsample-mincsample.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -c -o progs/mincsample/mincsample-mincsample.obj `if test -f 'progs/mincsample/mincsample.c'; then $(CYGPATH_W) 'progs/mincsample/mincsample.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincsample/mincsample.c'; fi` progs/mincsample/mincsample-mt19937ar.o: progs/mincsample/mt19937ar.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -MT progs/mincsample/mincsample-mt19937ar.o -MD -MP -MF progs/mincsample/$(DEPDIR)/mincsample-mt19937ar.Tpo -c -o progs/mincsample/mincsample-mt19937ar.o `test -f 'progs/mincsample/mt19937ar.c' || echo '$(srcdir)/'`progs/mincsample/mt19937ar.c @am__fastdepCC_TRUE@ mv -f progs/mincsample/$(DEPDIR)/mincsample-mt19937ar.Tpo progs/mincsample/$(DEPDIR)/mincsample-mt19937ar.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincsample/mt19937ar.c' object='progs/mincsample/mincsample-mt19937ar.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -c -o progs/mincsample/mincsample-mt19937ar.o `test -f 'progs/mincsample/mt19937ar.c' || echo '$(srcdir)/'`progs/mincsample/mt19937ar.c progs/mincsample/mincsample-mt19937ar.obj: progs/mincsample/mt19937ar.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -MT progs/mincsample/mincsample-mt19937ar.obj -MD -MP -MF progs/mincsample/$(DEPDIR)/mincsample-mt19937ar.Tpo -c -o progs/mincsample/mincsample-mt19937ar.obj `if test -f 'progs/mincsample/mt19937ar.c'; then $(CYGPATH_W) 'progs/mincsample/mt19937ar.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincsample/mt19937ar.c'; fi` @am__fastdepCC_TRUE@ mv -f progs/mincsample/$(DEPDIR)/mincsample-mt19937ar.Tpo progs/mincsample/$(DEPDIR)/mincsample-mt19937ar.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='progs/mincsample/mt19937ar.c' object='progs/mincsample/mincsample-mt19937ar.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mincsample_CFLAGS) $(CFLAGS) -c -o progs/mincsample/mincsample-mt19937ar.obj `if test -f 'progs/mincsample/mt19937ar.c'; then $(CYGPATH_W) 'progs/mincsample/mt19937ar.c'; else $(CYGPATH_W) '$(srcdir)/progs/mincsample/mt19937ar.c'; fi` .l.c: $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) .y.c: $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf conversion/Acr_nema/.libs conversion/Acr_nema/_libs -rm -rf libsrc/.libs libsrc/_libs -rm -rf libsrc2/.libs libsrc2/_libs -rm -rf volume_io/Geometry/.libs volume_io/Geometry/_libs -rm -rf volume_io/MNI_formats/.libs volume_io/MNI_formats/_libs -rm -rf volume_io/Prog_utils/.libs volume_io/Prog_utils/_libs -rm -rf volume_io/Volumes/.libs volume_io/Volumes/_libs distclean-libtool: -rm -f libtool config.lt install-man1: $(man1_MANS) $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)" @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $$i; then file=$$i; \ else file=$(srcdir)/$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 1*) ;; \ *) ext='1' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ done uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 1*) ;; \ *) ext='1' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ done install-man3: $(man3_MANS) $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.3*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $$i; then file=$$i; \ else file=$(srcdir)/$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 3*) ;; \ *) ext='3' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \ done uninstall-man3: @$(NORMAL_UNINSTALL) @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.3*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 3*) ;; \ *) ext='3' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \ rm -f "$(DESTDIR)$(man3dir)/$$inst"; \ done install-includeHEADERS: $(include_HEADERS) @$(NORMAL_INSTALL) test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" @list='$(include_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ done uninstall-includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_HEADERS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ rm -f "$(DESTDIR)$(includedir)/$$f"; \ done install-include_acr_nemaHEADERS: $(include_acr_nema_HEADERS) @$(NORMAL_INSTALL) test -z "$(include_acr_nemadir)" || $(MKDIR_P) "$(DESTDIR)$(include_acr_nemadir)" @list='$(include_acr_nema_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(include_acr_nemaHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(include_acr_nemadir)/$$f'"; \ $(include_acr_nemaHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(include_acr_nemadir)/$$f"; \ done uninstall-include_acr_nemaHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_acr_nema_HEADERS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(include_acr_nemadir)/$$f'"; \ rm -f "$(DESTDIR)$(include_acr_nemadir)/$$f"; \ done install-include_volume_ioHEADERS: $(include_volume_io_HEADERS) @$(NORMAL_INSTALL) test -z "$(include_volume_iodir)" || $(MKDIR_P) "$(DESTDIR)$(include_volume_iodir)" @list='$(include_volume_io_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(include_volume_ioHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(include_volume_iodir)/$$f'"; \ $(include_volume_ioHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(include_volume_iodir)/$$f"; \ done uninstall-include_volume_ioHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_volume_io_HEADERS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(include_volume_iodir)/$$f'"; \ rm -f "$(DESTDIR)$(include_volume_iodir)/$$f"; \ done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @case `sed 15q $(srcdir)/NEWS` in \ *"$(VERSION)"*) : ;; \ *) \ echo "NEWS not updated; not releasing" 1>&2; \ exit 1;; \ esac @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi $(am__remove_distdir) test -d $(distdir) || mkdir $(distdir) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ am__remove_distdir=: \ am__skip_length_check=: \ distdir) \ || exit 1; \ fi; \ done -find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lzma*) \ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(MANS) \ $(HEADERS) config.h install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(include_acr_nemadir)" "$(DESTDIR)$(include_volume_iodir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -rm -f conversion/Acr_nema/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/Acr_nema/$(am__dirstamp) -rm -f conversion/dcm2mnc/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/dcm2mnc/$(am__dirstamp) -rm -f conversion/ecattominc/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/ecattominc/$(am__dirstamp) -rm -f conversion/image_filters/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/image_filters/$(am__dirstamp) -rm -f conversion/micropet/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/micropet/$(am__dirstamp) -rm -f conversion/minctoecat/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/minctoecat/$(am__dirstamp) -rm -f conversion/nifti1/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/nifti1/$(am__dirstamp) -rm -f conversion/vff2mnc/$(DEPDIR)/$(am__dirstamp) -rm -f conversion/vff2mnc/$(am__dirstamp) -rm -f libsrc/$(DEPDIR)/$(am__dirstamp) -rm -f libsrc/$(am__dirstamp) -rm -f libsrc2/$(DEPDIR)/$(am__dirstamp) -rm -f libsrc2/$(am__dirstamp) -rm -f progs/Proglib/$(DEPDIR)/$(am__dirstamp) -rm -f progs/Proglib/$(am__dirstamp) -rm -f progs/coordinates/$(DEPDIR)/$(am__dirstamp) -rm -f progs/coordinates/$(am__dirstamp) -rm -f progs/minc_modify_header/$(DEPDIR)/$(am__dirstamp) -rm -f progs/minc_modify_header/$(am__dirstamp) -rm -f progs/mincaverage/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincaverage/$(am__dirstamp) -rm -f progs/mincblob/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincblob/$(am__dirstamp) -rm -f progs/minccalc/$(DEPDIR)/$(am__dirstamp) -rm -f progs/minccalc/$(am__dirstamp) -rm -f progs/minccmp/$(DEPDIR)/$(am__dirstamp) -rm -f progs/minccmp/$(am__dirstamp) -rm -f progs/mincconcat/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincconcat/$(am__dirstamp) -rm -f progs/mincconvert/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincconvert/$(am__dirstamp) -rm -f progs/minccopy/$(DEPDIR)/$(am__dirstamp) -rm -f progs/minccopy/$(am__dirstamp) -rm -f progs/mincdump/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincdump/$(am__dirstamp) -rm -f progs/mincexample/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincexample/$(am__dirstamp) -rm -f progs/mincexpand/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincexpand/$(am__dirstamp) -rm -f progs/mincextract/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincextract/$(am__dirstamp) -rm -f progs/mincgen/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincgen/$(am__dirstamp) -rm -f progs/mincinfo/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincinfo/$(am__dirstamp) -rm -f progs/minclookup/$(DEPDIR)/$(am__dirstamp) -rm -f progs/minclookup/$(am__dirstamp) -rm -f progs/mincmakescalar/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincmakescalar/$(am__dirstamp) -rm -f progs/mincmakevector/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincmakevector/$(am__dirstamp) -rm -f progs/mincmath/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincmath/$(am__dirstamp) -rm -f progs/mincmorph/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincmorph/$(am__dirstamp) -rm -f progs/mincresample/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincresample/$(am__dirstamp) -rm -f progs/mincreshape/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincreshape/$(am__dirstamp) -rm -f progs/mincsample/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincsample/$(am__dirstamp) -rm -f progs/mincstats/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincstats/$(am__dirstamp) -rm -f progs/minctoraw/$(DEPDIR)/$(am__dirstamp) -rm -f progs/minctoraw/$(am__dirstamp) -rm -f progs/mincview/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincview/$(am__dirstamp) -rm -f progs/mincwindow/$(DEPDIR)/$(am__dirstamp) -rm -f progs/mincwindow/$(am__dirstamp) -rm -f progs/rawtominc/$(DEPDIR)/$(am__dirstamp) -rm -f progs/rawtominc/$(am__dirstamp) -rm -f progs/xfm/$(DEPDIR)/$(am__dirstamp) -rm -f progs/xfm/$(am__dirstamp) -rm -f volume_io/Geometry/$(DEPDIR)/$(am__dirstamp) -rm -f volume_io/Geometry/$(am__dirstamp) -rm -f volume_io/MNI_formats/$(DEPDIR)/$(am__dirstamp) -rm -f volume_io/MNI_formats/$(am__dirstamp) -rm -f volume_io/Prog_utils/$(DEPDIR)/$(am__dirstamp) -rm -f volume_io/Prog_utils/$(am__dirstamp) -rm -f volume_io/Volumes/$(DEPDIR)/$(am__dirstamp) -rm -f volume_io/Volumes/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -rm -f progs/minccalc/gram.c -rm -f progs/minccalc/gram.h -rm -f progs/minccalc/lex.c -rm -f progs/mincgen/ncgentab.c -rm -f progs/mincgen/ncgentab.h -rm -f progs/mincgen/ncgenyy.c clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf conversion/Acr_nema/$(DEPDIR) conversion/dcm2mnc/$(DEPDIR) conversion/ecattominc/$(DEPDIR) conversion/image_filters/$(DEPDIR) conversion/micropet/$(DEPDIR) conversion/minctoecat/$(DEPDIR) conversion/nifti1/$(DEPDIR) conversion/vff2mnc/$(DEPDIR) libsrc/$(DEPDIR) libsrc2/$(DEPDIR) progs/Proglib/$(DEPDIR) progs/coordinates/$(DEPDIR) progs/minc_modify_header/$(DEPDIR) progs/mincaverage/$(DEPDIR) progs/mincblob/$(DEPDIR) progs/minccalc/$(DEPDIR) progs/minccmp/$(DEPDIR) progs/mincconcat/$(DEPDIR) progs/mincconvert/$(DEPDIR) progs/minccopy/$(DEPDIR) progs/mincdump/$(DEPDIR) progs/mincexample/$(DEPDIR) progs/mincexpand/$(DEPDIR) progs/mincextract/$(DEPDIR) progs/mincgen/$(DEPDIR) progs/mincinfo/$(DEPDIR) progs/minclookup/$(DEPDIR) progs/mincmakescalar/$(DEPDIR) progs/mincmakevector/$(DEPDIR) progs/mincmath/$(DEPDIR) progs/mincmorph/$(DEPDIR) progs/mincresample/$(DEPDIR) progs/mincreshape/$(DEPDIR) progs/mincsample/$(DEPDIR) progs/mincstats/$(DEPDIR) progs/minctoraw/$(DEPDIR) progs/mincview/$(DEPDIR) progs/mincwindow/$(DEPDIR) progs/rawtominc/$(DEPDIR) progs/xfm/$(DEPDIR) volume_io/Geometry/$(DEPDIR) volume_io/MNI_formats/$(DEPDIR) volume_io/Prog_utils/$(DEPDIR) volume_io/Volumes/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-includeHEADERS \ install-include_acr_nemaHEADERS \ install-include_volume_ioHEADERS install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-dist_binSCRIPTS install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man1 install-man3 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf conversion/Acr_nema/$(DEPDIR) conversion/dcm2mnc/$(DEPDIR) conversion/ecattominc/$(DEPDIR) conversion/image_filters/$(DEPDIR) conversion/micropet/$(DEPDIR) conversion/minctoecat/$(DEPDIR) conversion/nifti1/$(DEPDIR) conversion/vff2mnc/$(DEPDIR) libsrc/$(DEPDIR) libsrc2/$(DEPDIR) progs/Proglib/$(DEPDIR) progs/coordinates/$(DEPDIR) progs/minc_modify_header/$(DEPDIR) progs/mincaverage/$(DEPDIR) progs/mincblob/$(DEPDIR) progs/minccalc/$(DEPDIR) progs/minccmp/$(DEPDIR) progs/mincconcat/$(DEPDIR) progs/mincconvert/$(DEPDIR) progs/minccopy/$(DEPDIR) progs/mincdump/$(DEPDIR) progs/mincexample/$(DEPDIR) progs/mincexpand/$(DEPDIR) progs/mincextract/$(DEPDIR) progs/mincgen/$(DEPDIR) progs/mincinfo/$(DEPDIR) progs/minclookup/$(DEPDIR) progs/mincmakescalar/$(DEPDIR) progs/mincmakevector/$(DEPDIR) progs/mincmath/$(DEPDIR) progs/mincmorph/$(DEPDIR) progs/mincresample/$(DEPDIR) progs/mincreshape/$(DEPDIR) progs/mincsample/$(DEPDIR) progs/mincstats/$(DEPDIR) progs/minctoraw/$(DEPDIR) progs/mincview/$(DEPDIR) progs/mincwindow/$(DEPDIR) progs/rawtominc/$(DEPDIR) progs/xfm/$(DEPDIR) volume_io/Geometry/$(DEPDIR) volume_io/MNI_formats/$(DEPDIR) volume_io/Prog_utils/$(DEPDIR) volume_io/Volumes/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-dist_binSCRIPTS uninstall-includeHEADERS \ uninstall-include_acr_nemaHEADERS \ uninstall-include_volume_ioHEADERS uninstall-libLTLIBRARIES \ uninstall-man uninstall-man: uninstall-man1 uninstall-man3 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ install-strip .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS ctags \ ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-lzma \ dist-shar dist-tarZ dist-zip distcheck distclean \ distclean-compile distclean-generic distclean-hdr \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-binSCRIPTS \ install-data install-data-am install-dist_binSCRIPTS \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-includeHEADERS \ install-include_acr_nemaHEADERS \ install-include_volume_ioHEADERS install-info install-info-am \ install-libLTLIBRARIES install-man install-man1 install-man3 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-binSCRIPTS uninstall-dist_binSCRIPTS \ uninstall-includeHEADERS uninstall-include_acr_nemaHEADERS \ uninstall-include_volume_ioHEADERS uninstall-libLTLIBRARIES \ uninstall-man uninstall-man1 uninstall-man3 # how to build man pages from POD progs/minccomplete/minccomplete.man1: progs/minccomplete/minccomplete $(POD2MAN) --section=1 $< > $@ progs/minchistory/minchistory.man1: progs/minchistory/minchistory $(POD2MAN) --section=1 $< > $@ progs/mincpik/mincpik.man1: progs/mincpik/mincpik $(POD2MAN) --section=1 $< > $@ ezminc/examples/CMakeLists.txt ezminc/examples/fuzzy_volume_similarity.cpp ezminc/examples/trilinear_resample.cpp ezminc/examples/volume_avg.cpp ezminc/examples/volume_gtc_similarity.cpp ezminc/examples/volume_similarity.cpp ezminc/minc_1_simple_rw.cpp ezminc/minc_1_simple_rw.h ezminc/minc_io_4d_volume.h ezminc/minc_io_fixed_vector.h ezminc/minc_io_simple_volume.h ezminc/tests/minc_rw_test2.cpp ezminc/tests/minc_rw_test_4d.cpp ezminc/tests/minc_rw_test_simple.cpp ezminc/tests/CMakeLists.txt ezminc/tests/ezminc_rw_test.cpp ezminc/tests/ezminc_stats.cpp ezminc/minc_1_simple.h ezminc/CMakeLists.txt ezminc/minc_1_rw.cpp ezminc/minc_1_rw.h ezminc/minc_io_exceptions.h # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: minc-2.2.00/config.h.in0000644000265600003100000001032012030077513011454 00000000000000/* config.h.in. Generated from configure.in by autoheader. */ /* Force the 1.8.x version */ #undef H5Acreate_vers /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_FLOAT_H /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `getpwnam' function. */ #undef HAVE_GETPWNAM /* Define to 1 if the system has the type `int16_t'. */ #undef HAVE_INT16_T /* Define to 1 if the system has the type `int32_t'. */ #undef HAVE_INT32_T /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mkstemp' function. */ #undef HAVE_MKSTEMP /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the `popen' function. */ #undef HAVE_POPEN /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* Define to 1 if you have the `system' function. */ #undef HAVE_SYSTEM /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the `tempnam' function. */ #undef HAVE_TEMPNAM /* Define to 1 if you have the `tmpnam' function. */ #undef HAVE_TMPNAM /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_VALUES_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define if MINC 2.0 is enabled. */ #undef MINC2 /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Version number of package */ #undef VERSION /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER /* Define to `int' if does not define. */ #undef pid_t /* Define as `fork' if `vfork' does not work. */ #undef vfork minc-2.2.00/epm-header.in0000644000265600003100000000033212027132661011774 00000000000000%product minc %copyright 1993-2005 Peter Neelin %vendor McConnell Brain Imaging Centre %packager Andrew Janke %license COPYING %readme README %description Medical Imaging library %version @VERSION@ minc-2.2.00/configure0000755000265600003100000200311212030077515011345 00000000000000#! /bin/sh # From configure.in Revision: 6.45 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.67 for minc 2.2.00. # # Report bugs to . # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software # Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and a.janke@gmail.com $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac ECHO=${lt_ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF $* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='minc' PACKAGE_TARNAME='minc' PACKAGE_VERSION='2.2.00' PACKAGE_STRING='minc 2.2.00' PACKAGE_BUGREPORT='a.janke@gmail.com' PACKAGE_URL='' ac_unique_file="libsrc2/minc2.h" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS ACR_NEMA_TOOLS_FALSE ACR_NEMA_TOOLS_TRUE LIBOBJS MINC2_FALSE MINC2_TRUE BUILD_POD_DOC_FALSE BUILD_POD_DOC_TRUE POD2MAN OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL lt_ECHO RANLIB AR OBJDUMP NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL EGREP GREP CPP YFLAGS YACC LEXLIB LEX_OUTPUT_ROOT LEX ac_ct_F77 FFLAGS F77 am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC LN_S am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld enable_libtool_lock with_build_path enable_disminc2 enable_acr_nema ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS F77 FFLAGS YACC YFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures minc 2.2.00 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/minc] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of minc 2.2.00:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-minc2 disable HDF5 (MINC 2) functionality --enable-acr-nema install ACR/NEMA tools Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-build-path=DIR build using DIR/include and DIR/lib Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags YACC The `Yet Another C Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF minc configure 2.2.00 generated by GNU Autoconf 2.67 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_f77_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_f77_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_f77_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval "test \"\${$3+set}\"" = set; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## -------------------------------- ## ## Report this to a.janke@gmail.com ## ## -------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_type # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_func # ac_fn_f77_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_f77_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_f77_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by minc $as_me 2.2.00, which was generated by GNU Autoconf 2.67. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5 ; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in ac_config_aux "$srcdir"/ac_config_aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in ac_config_aux \"$srcdir\"/ac_config_aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.10' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test "${ac_cv_path_mkdir+set}" = set; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AWK+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='minc' VERSION='2.2.00' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers config.h" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5 ; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5 ; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5 ; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5 ; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5 ; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval "test \"\${ac_cv_prog_cc_${ac_cc}_c_o+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$F77"; then ac_cv_prog_F77="$F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi F77=$ac_cv_prog_F77 if test -n "$F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $F77" >&5 $as_echo "$F77" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$F77" && break done fi if test -z "$F77"; then ac_ct_F77=$F77 for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_F77"; then ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_F77="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_F77=$ac_cv_prog_ac_ct_F77 if test -n "$ac_ct_F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_F77" >&5 $as_echo "$ac_ct_F77" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_F77" && break done if test "x$ac_ct_F77" = x; then F77="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac F77=$ac_ct_F77 fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done rm -f a.out # If we don't use `.F' as extension, the preprocessor is not run on the # input file. (Note that this only needs to work for GNU compilers.) ac_save_ext=$ac_ext ac_ext=F { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Fortran 77 compiler" >&5 $as_echo_n "checking whether we are using the GNU Fortran 77 compiler... " >&6; } if test "${ac_cv_f77_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat > conftest.$ac_ext <<_ACEOF program main #ifndef __GNUC__ choke me #endif end _ACEOF if ac_fn_f77_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_f77_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_compiler_gnu" >&5 $as_echo "$ac_cv_f77_compiler_gnu" >&6; } ac_ext=$ac_save_ext ac_test_FFLAGS=${FFLAGS+set} ac_save_FFLAGS=$FFLAGS FFLAGS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $F77 accepts -g" >&5 $as_echo_n "checking whether $F77 accepts -g... " >&6; } if test "${ac_cv_prog_f77_g+set}" = set; then : $as_echo_n "(cached) " >&6 else FFLAGS=-g cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_compile "$LINENO"; then : ac_cv_prog_f77_g=yes else ac_cv_prog_f77_g=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_f77_g" >&5 $as_echo "$ac_cv_prog_f77_g" >&6; } if test "$ac_test_FFLAGS" = set; then FFLAGS=$ac_save_FFLAGS elif test $ac_cv_prog_f77_g = yes; then if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-g -O2" else FFLAGS="-g" fi else if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-O2" else FFLAGS= fi fi if test $ac_compiler_gnu = yes; then G77=yes else G77= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu for ac_prog in flex lex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_LEX+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_LEX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LEX=$ac_cv_prog_LEX if test -n "$LEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 $as_echo "$LEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LEX" && break done test -n "$LEX" || LEX=":" if test "x$LEX" != "x:"; then cat >conftest.l <<_ACEOF %% a { ECHO; } b { REJECT; } c { yymore (); } d { yyless (1); } e { yyless (input () != 0); } f { unput (yytext[0]); } . { BEGIN INITIAL; } %% #ifdef YYTEXT_POINTER extern char *yytext; #endif int main (void) { return ! yylex () + ! yywrap (); } _ACEOF { { ac_try="$LEX conftest.l" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$LEX conftest.l") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 $as_echo_n "checking lex output file root... " >&6; } if test "${ac_cv_prog_lex_root+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -f lex.yy.c; then ac_cv_prog_lex_root=lex.yy elif test -f lexyy.c; then ac_cv_prog_lex_root=lexyy else as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 $as_echo "$ac_cv_prog_lex_root" >&6; } LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root if test -z "${LEXLIB+set}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 $as_echo_n "checking lex library... " >&6; } if test "${ac_cv_lib_lex+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS=$LIBS ac_cv_lib_lex='none needed' for ac_lib in '' -lfl -ll; do LIBS="$ac_lib $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lex=$ac_lib fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext test "$ac_cv_lib_lex" != 'none needed' && break done LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 $as_echo "$ac_cv_lib_lex" >&6; } test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 $as_echo_n "checking whether yytext is a pointer... " >&6; } if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then : $as_echo_n "(cached) " >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the # default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no ac_save_LIBS=$LIBS LIBS="$LEXLIB $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define YYTEXT_POINTER 1 `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_prog_lex_yytext_pointer=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 $as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } if test $ac_cv_prog_lex_yytext_pointer = yes; then $as_echo "#define YYTEXT_POINTER 1" >>confdefs.h fi rm -f conftest.l $LEX_OUTPUT_ROOT.c fi if test "$LEX" = :; then LEX=${am_missing_run}flex fi for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_YACC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_YACC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if test "${ac_cv_header_time+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval "test \"\${$as_ac_Header+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if test "${ac_cv_search_opendir+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then : break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if test "${ac_cv_search_opendir+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then : break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5 ; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/time.h sys/stat.h sys/wait.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fcntl.h pwd.h float.h values.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" if test "x$ac_cv_type_int32_t" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT32_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" if test "x$ac_cv_type_int16_t" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT16_T 1 _ACEOF fi # dnl Build only static libs by default # AC_DISABLE_SHARED case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.2.6b' macro_revision='1.3017' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if test "${ac_cv_build+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if test "${ac_cv_host+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if test "${ac_cv_path_SED+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if test "${ac_cv_path_FGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if test "${lt_cv_path_LD+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if test "${lt_cv_path_NM+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$ac_tool_prefix"; then for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DUMPBIN+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if test "${lt_cv_nm_interface+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:5712: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:5715: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:5718: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if test "${lt_cv_sys_max_cmd_len+set}" = set; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if test "${lt_cv_ld_reload_flag+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OBJDUMP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if test "${lt_cv_deplibs_check_method+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AR+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 6912 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if test "${lt_cv_cc_needs_belf+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DSYMUTIL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_NMEDIT+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_LIPO+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OTOOL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OTOOL64+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if test "${lt_cv_apple_cc_single_mod+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if test "${lt_cv_ld_exported_symbols_list+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$F77"; then ac_cv_prog_F77="$F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi F77=$ac_cv_prog_F77 if test -n "$F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $F77" >&5 $as_echo "$F77" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$F77" && break done fi if test -z "$F77"; then ac_ct_F77=$F77 for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_F77"; then ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_F77="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_F77=$ac_cv_prog_ac_ct_F77 if test -n "$ac_ct_F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_F77" >&5 $as_echo "$ac_ct_F77" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_F77" && break done if test "x$ac_ct_F77" = x; then F77="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac F77=$ac_ct_F77 fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done rm -f a.out # If we don't use `.F' as extension, the preprocessor is not run on the # input file. (Note that this only needs to work for GNU compilers.) ac_save_ext=$ac_ext ac_ext=F { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Fortran 77 compiler" >&5 $as_echo_n "checking whether we are using the GNU Fortran 77 compiler... " >&6; } if test "${ac_cv_f77_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat > conftest.$ac_ext <<_ACEOF program main #ifndef __GNUC__ choke me #endif end _ACEOF if ac_fn_f77_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_f77_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_compiler_gnu" >&5 $as_echo "$ac_cv_f77_compiler_gnu" >&6; } ac_ext=$ac_save_ext ac_test_FFLAGS=${FFLAGS+set} ac_save_FFLAGS=$FFLAGS FFLAGS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $F77 accepts -g" >&5 $as_echo_n "checking whether $F77 accepts -g... " >&6; } if test "${ac_cv_prog_f77_g+set}" = set; then : $as_echo_n "(cached) " >&6 else FFLAGS=-g cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_compile "$LINENO"; then : ac_cv_prog_f77_g=yes else ac_cv_prog_f77_g=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_f77_g" >&5 $as_echo "$ac_cv_prog_f77_g" >&6; } if test "$ac_test_FFLAGS" = set; then FFLAGS=$ac_save_FFLAGS elif test $ac_cv_prog_f77_g = yes; then if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-g -O2" else FFLAGS="-g" fi else if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-O2" else FFLAGS= fi fi if test $ac_compiler_gnu = yes; then G77=yes else G77= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if test "${lt_cv_objdir+set}" = set; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8393: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:8397: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 $as_echo "$lt_prog_compiler_pic" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if test "${lt_cv_prog_compiler_pic_works+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8732: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:8736: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8837: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:8841: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8892: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:8896: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu) link_all_deplibs=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='' link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo(void) {} _ACEOF if ac_fn_c_try_link "$LINENO"; then : archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 $as_echo "$archive_cmds_need_lc" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = x""yes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = x""yes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = x""yes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 11276 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self_static+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 11372 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu archive_cmds_need_lc_F77=no allow_undefined_flag_F77= always_export_symbols_F77=no archive_expsym_cmds_F77= export_dynamic_flag_spec_F77= hardcode_direct_F77=no hardcode_direct_absolute_F77=no hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_minus_L_F77=no hardcode_automatic_F77=no inherit_rpath_F77=no module_cmds_F77= module_expsym_cmds_F77= link_all_deplibs_F77=unknown old_archive_cmds_F77=$old_archive_cmds no_undefined_flag_F77= whole_archive_flag_spec_F77= enable_shared_with_static_runtimes_F77=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o objext_F77=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${F77-"f77"} compiler=$CC compiler_F77=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` GCC=$G77 if test -n "$compiler"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } GCC_F77="$G77" LD_F77="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... lt_prog_compiler_wl_F77= lt_prog_compiler_pic_F77= lt_prog_compiler_static_F77= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_static_F77='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_F77='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_F77='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_F77=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_F77='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_F77=-Kconform_pic fi ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_F77='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' else lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_F77='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_F77='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_F77='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_F77='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-fPIC' lt_prog_compiler_static_F77='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='--shared' lt_prog_compiler_static_F77='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-fpic' lt_prog_compiler_static_F77='-Bstatic' ;; ccc*) lt_prog_compiler_wl_F77='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-qpic' lt_prog_compiler_static_F77='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' lt_prog_compiler_wl_F77='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' lt_prog_compiler_wl_F77='' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_F77='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_F77='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; rdos*) lt_prog_compiler_static_F77='-non_shared' ;; solaris*) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl_F77='-Qoption ld ';; *) lt_prog_compiler_wl_F77='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl_F77='-Qoption ld ' lt_prog_compiler_pic_F77='-PIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_F77='-Kconform_pic' lt_prog_compiler_static_F77='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; unicos*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_can_build_shared_F77=no ;; uts4*) lt_prog_compiler_pic_F77='-pic' lt_prog_compiler_static_F77='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_F77=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_F77= ;; *) lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_F77" >&5 $as_echo "$lt_prog_compiler_pic_F77" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... " >&6; } if test "${lt_cv_prog_compiler_pic_works_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_F77=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_F77" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:12027: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:12031: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_F77=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_F77" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_F77" >&6; } if test x"$lt_cv_prog_compiler_pic_works_F77" = xyes; then case $lt_prog_compiler_pic_F77 in "" | " "*) ;; *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; esac else lt_prog_compiler_pic_F77= lt_prog_compiler_can_build_shared_F77=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_F77=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_F77=yes fi else lt_cv_prog_compiler_static_works_F77=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_F77" >&5 $as_echo "$lt_cv_prog_compiler_static_works_F77" >&6; } if test x"$lt_cv_prog_compiler_static_works_F77" = xyes; then : else lt_prog_compiler_static_F77= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_F77=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:12126: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:12130: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_F77=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_F77" >&5 $as_echo "$lt_cv_prog_compiler_c_o_F77" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_F77=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:12178: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:12182: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_F77=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_F77" >&5 $as_echo "$lt_cv_prog_compiler_c_o_F77" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag_F77= always_export_symbols_F77=no archive_cmds_F77= archive_expsym_cmds_F77= compiler_needs_object_F77=no enable_shared_with_static_runtimes_F77=no export_dynamic_flag_spec_F77= export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic_F77=no hardcode_direct_F77=no hardcode_direct_absolute_F77=no hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=unsupported inherit_rpath_F77=no link_all_deplibs_F77=unknown module_cmds_F77= module_expsym_cmds_F77= old_archive_from_new_cmds_F77= old_archive_from_expsyms_cmds_F77= thread_safe_flag_spec_F77= whole_archive_flag_spec_F77= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_F77= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_F77='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu) link_all_deplibs_F77=no ;; esac ld_shlibs_F77=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_F77='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_F77= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_F77=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='' ;; m68k) archive_cmds_F77='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_F77=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_F77=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_F77='-L$libdir' allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_F77=no fi ;; interix[3-9]*) hardcode_direct_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec_F77= tmp_sharedflag='--shared' ;; xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object_F77=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds_F77='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec_F77='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' archive_cmds_F77='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds_F77='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs_F77=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs_F77=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs_F77=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac ;; sunos4*) archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac if test "$ld_shlibs_F77" = no; then runpath_var= hardcode_libdir_flag_spec_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_F77=unsupported always_export_symbols_F77=yes archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_F77=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_F77=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_F77='' hardcode_direct_F77=yes hardcode_direct_absolute_F77=yes hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes file_list_spec_F77='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_F77=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_F77=yes hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_libdir_separator_F77= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs_F77=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec_F77='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_F77=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_F77='-berok' # Determine the default libpath from the value encoded in an # empty executable. cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_F77='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_F77="-z nodefs" archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_F77=' ${wl}-bernotok' allow_undefined_flag_F77=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_F77='$convenience' archive_cmds_need_lc_F77=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='' ;; m68k) archive_cmds_F77='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec_F77=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_F77=' ' allow_undefined_flag_F77=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_F77='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; darwin* | rhapsody*) archive_cmds_need_lc_F77=no hardcode_direct_F77=no hardcode_automatic_F77=yes hardcode_shlibpath_var_F77=unsupported whole_archive_flag_spec_F77='' link_all_deplibs_F77=yes allow_undefined_flag_F77="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo archive_cmds_F77="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_F77="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_F77="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds_F77="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs_F77=no fi ;; dgux*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; freebsd1*) ld_shlibs_F77=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_F77='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_F77='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes export_dynamic_flag_spec_F77='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld_F77='+b $libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes hardcode_direct_absolute_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: case $host_cpu in hppa*64*|ia64*) hardcode_direct_F77=no hardcode_shlibpath_var_F77=no ;; *) hardcode_direct_F77=yes hardcode_direct_absolute_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat > conftest.$ac_ext <<_ACEOF int foo(void) {} _ACEOF if ac_fn_f77_try_link "$LINENO"; then : archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" else archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc_F77='no' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: inherit_rpath_F77=yes link_all_deplibs_F77=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; newsos6) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_shlibpath_var_F77=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no hardcode_direct_absolute_F77=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-R$libdir' ;; *) archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs_F77=no fi ;; os2*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes allow_undefined_flag_F77=unsupported archive_cmds_F77='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc_F77='no' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_F77='-rpath $libdir' fi archive_cmds_need_lc_F77='no' hardcode_libdir_separator_F77=: ;; solaris*) no_undefined_flag_F77=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds_F77='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds_F77='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_shlibpath_var_F77=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs_F77=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; sysv4) case $host_vendor in sni) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_F77='$CC -r -o $output$reload_objs' hardcode_direct_F77=no ;; motorola) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv4.3*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_F77=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_F77='${wl}-z,text' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_F77='${wl}-z,text' allow_undefined_flag_F77='${wl}-z,nodefs' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='${wl}-R,$libdir' hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes export_dynamic_flag_spec_F77='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; *) ld_shlibs_F77=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec_F77='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_F77" >&5 $as_echo "$ld_shlibs_F77" >&6; } test "$ld_shlibs_F77" = no && can_build_shared=no with_gnu_ld_F77=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_F77" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_F77=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_F77 in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_F77 pic_flag=$lt_prog_compiler_pic_F77 compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_F77 allow_undefined_flag_F77= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_F77 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_F77 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc_F77=no else archive_cmds_need_lc_F77=yes fi allow_undefined_flag_F77=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_F77" >&5 $as_echo "$archive_cmds_need_lc_F77" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_F77\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_F77\"" cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_F77= if test -n "$hardcode_libdir_flag_spec_F77" || test -n "$runpath_var_F77" || test "X$hardcode_automatic_F77" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct_F77" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, F77)" != no && test "$hardcode_minus_L_F77" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_F77=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_F77=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_F77=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_F77" >&5 $as_echo "$hardcode_action_F77" >&6; } if test "$hardcode_action_F77" = relink || test "$inherit_rpath_F77" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_F77" != yes ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: for ac_prog in pod2man do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_POD2MAN+set}" = set; then : $as_echo_n "(cached) " >&6 else case $POD2MAN in [\\/]* | ?:[\\/]*) ac_cv_path_POD2MAN="$POD2MAN" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_POD2MAN="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi POD2MAN=$ac_cv_path_POD2MAN if test -n "$POD2MAN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $POD2MAN" >&5 $as_echo "$POD2MAN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$POD2MAN" && break done if test "x$POD2MAN" != "x" ; then BUILD_POD_DOC_TRUE= BUILD_POD_DOC_FALSE='#' else BUILD_POD_DOC_TRUE='#' BUILD_POD_DOC_FALSE= fi if test "x$POD2MAN" = "x"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pod2man not installed, unable to build all manual pages" >&5 $as_echo "$as_me: WARNING: pod2man not installed, unable to build all manual pages" >&2;} fi # Check whether --with-build-path was given. if test "${with_build_path+set}" = set; then : withval=$with_build_path; for d in `echo $withval | tr : ' '`; do test -d $d || as_fn_error $? "build path $d not found." "$LINENO" 5 test -d $d/include && CPPFLAGS="$CPPFLAGS -I$d/include" test -d $d/lib && LDFLAGS="$LDFLAGS -L$d/lib" done fi # Check for required C libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library m" >&5 $as_echo_n "checking for library m... " >&6; } LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { double x = sqrt(3.); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : mni_result=yes else mni_result=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mni_result" >&5 $as_echo "$mni_result" >&6; } if test "$mni_result" = "no"; then as_fn_error $? "cannot find required library m" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library netcdf" >&5 $as_echo_n "checking for library netcdf... " >&6; } LIBS="-lnetcdf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int i = ncopen("",0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : mni_result=yes else mni_result=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mni_result" >&5 $as_echo "$mni_result" >&6; } if test "$mni_result" = "no"; then as_fn_error $? "cannot find required library netcdf" "$LINENO" 5 fi # Check whether --enable-disminc2 was given. if test "${enable_disminc2+set}" = set; then : enableval=$enable_disminc2; case "${disableval}" in yes) disminc2=true ;; no) disminc2=false ;; *) as_fn_error $? "bad value ${disableval} for --disable-minc2" "$LINENO" 5 ;; esac else disminc2=false fi if test x$disminc2 = xfalse; then MINC2_TRUE= MINC2_FALSE='#' else MINC2_TRUE='#' MINC2_FALSE= fi # force certain HDF5 function calls to the 1.8.x versions cat >>confdefs.h <<_ACEOF #define H5Acreate_vers 2 _ACEOF if test x$disminc2 = xfalse; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library z" >&5 $as_echo_n "checking for library z... " >&6; } LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { compress2; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : mni_result=yes else mni_result=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mni_result" >&5 $as_echo "$mni_result" >&6; } if test "$mni_result" = "no"; then as_fn_error $? "cannot find required library z" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library hdf5" >&5 $as_echo_n "checking for library hdf5... " >&6; } LIBS="-lhdf5 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int f = H5Fopen("",0,H5P_DEFAULT); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : mni_result=yes else mni_result=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mni_result" >&5 $as_echo "$mni_result" >&6; } if test "$mni_result" = "no"; then as_fn_error $? "cannot find required library hdf5" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define MINC2 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define MINC2 0 _ACEOF fi ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" if test "x$ac_cv_func_strdup" = x""yes; then : $as_echo "#define HAVE_STRDUP 1" >>confdefs.h else case " $LIBOBJS " in *" strdup.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strdup.$ac_objext" ;; esac fi for ac_func in mkstemp tempnam tmpnam do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getpwnam select strerror sysconf do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # Functions required for execute_decompress_command(). ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if test "${ac_cv_func_fork_works+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if test "${ac_cv_func_vfork_works+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi for ac_func in system popen do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # Code to enable conditional build of ACR/NEMA tools # Check whether --enable-acr-nema was given. if test "${enable_acr_nema+set}" = set; then : enableval=$enable_acr_nema; case "${enableval}" in yes) acr_nema=true ;; no) acr_nema=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-acr-nema" "$LINENO" 5 ;; esac else acr_nema=false fi if test x$acr_nema = xtrue; then ACR_NEMA_TOOLS_TRUE= ACR_NEMA_TOOLS_FALSE='#' else ACR_NEMA_TOOLS_TRUE='#' ACR_NEMA_TOOLS_FALSE= fi ac_config_files="$ac_config_files Makefile epm-header doc/Makefile testdir/Makefile libsrc2/test/Makefile volume_io/Makefile volume_io/Documentation/Makefile volume_io/Testing/Makefile" ac_config_files="$ac_config_files progs/xfm/xfmflip progs/minccomplete/minccomplete progs/minchistory/minchistory progs/mincpik/mincpik" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_POD_DOC_TRUE}" && test -z "${BUILD_POD_DOC_FALSE}"; then as_fn_error $? "conditional \"BUILD_POD_DOC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MINC2_TRUE}" && test -z "${MINC2_FALSE}"; then as_fn_error $? "conditional \"MINC2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ACR_NEMA_TOOLS_TRUE}" && test -z "${ACR_NEMA_TOOLS_FALSE}"; then as_fn_error $? "conditional \"ACR_NEMA_TOOLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by minc $as_me 2.2.00, which was generated by GNU Autoconf 2.67. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ minc config.status 2.2.00 configured by $0, generated by GNU Autoconf 2.67, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' LD_F77='`$ECHO "X$LD_F77" | $Xsed -e "$delay_single_quote_subst"`' old_archive_cmds_F77='`$ECHO "X$old_archive_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' compiler_F77='`$ECHO "X$compiler_F77" | $Xsed -e "$delay_single_quote_subst"`' GCC_F77='`$ECHO "X$GCC_F77" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_F77='`$ECHO "X$lt_prog_compiler_no_builtin_flag_F77" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_wl_F77='`$ECHO "X$lt_prog_compiler_wl_F77" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_pic_F77='`$ECHO "X$lt_prog_compiler_pic_F77" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_static_F77='`$ECHO "X$lt_prog_compiler_static_F77" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_F77='`$ECHO "X$lt_cv_prog_compiler_c_o_F77" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds_need_lc_F77='`$ECHO "X$archive_cmds_need_lc_F77" | $Xsed -e "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_F77='`$ECHO "X$enable_shared_with_static_runtimes_F77" | $Xsed -e "$delay_single_quote_subst"`' export_dynamic_flag_spec_F77='`$ECHO "X$export_dynamic_flag_spec_F77" | $Xsed -e "$delay_single_quote_subst"`' whole_archive_flag_spec_F77='`$ECHO "X$whole_archive_flag_spec_F77" | $Xsed -e "$delay_single_quote_subst"`' compiler_needs_object_F77='`$ECHO "X$compiler_needs_object_F77" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_new_cmds_F77='`$ECHO "X$old_archive_from_new_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_F77='`$ECHO "X$old_archive_from_expsyms_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds_F77='`$ECHO "X$archive_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' archive_expsym_cmds_F77='`$ECHO "X$archive_expsym_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' module_cmds_F77='`$ECHO "X$module_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' module_expsym_cmds_F77='`$ECHO "X$module_expsym_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' with_gnu_ld_F77='`$ECHO "X$with_gnu_ld_F77" | $Xsed -e "$delay_single_quote_subst"`' allow_undefined_flag_F77='`$ECHO "X$allow_undefined_flag_F77" | $Xsed -e "$delay_single_quote_subst"`' no_undefined_flag_F77='`$ECHO "X$no_undefined_flag_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_F77='`$ECHO "X$hardcode_libdir_flag_spec_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld_F77='`$ECHO "X$hardcode_libdir_flag_spec_ld_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_separator_F77='`$ECHO "X$hardcode_libdir_separator_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct_F77='`$ECHO "X$hardcode_direct_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct_absolute_F77='`$ECHO "X$hardcode_direct_absolute_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_minus_L_F77='`$ECHO "X$hardcode_minus_L_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_shlibpath_var_F77='`$ECHO "X$hardcode_shlibpath_var_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_automatic_F77='`$ECHO "X$hardcode_automatic_F77" | $Xsed -e "$delay_single_quote_subst"`' inherit_rpath_F77='`$ECHO "X$inherit_rpath_F77" | $Xsed -e "$delay_single_quote_subst"`' link_all_deplibs_F77='`$ECHO "X$link_all_deplibs_F77" | $Xsed -e "$delay_single_quote_subst"`' fix_srcfile_path_F77='`$ECHO "X$fix_srcfile_path_F77" | $Xsed -e "$delay_single_quote_subst"`' always_export_symbols_F77='`$ECHO "X$always_export_symbols_F77" | $Xsed -e "$delay_single_quote_subst"`' export_symbols_cmds_F77='`$ECHO "X$export_symbols_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' exclude_expsyms_F77='`$ECHO "X$exclude_expsyms_F77" | $Xsed -e "$delay_single_quote_subst"`' include_expsyms_F77='`$ECHO "X$include_expsyms_F77" | $Xsed -e "$delay_single_quote_subst"`' prelink_cmds_F77='`$ECHO "X$prelink_cmds_F77" | $Xsed -e "$delay_single_quote_subst"`' file_list_spec_F77='`$ECHO "X$file_list_spec_F77" | $Xsed -e "$delay_single_quote_subst"`' hardcode_action_F77='`$ECHO "X$hardcode_action_F77" | $Xsed -e "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ AR \ AR_FLAGS \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ SHELL \ ECHO \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ fix_srcfile_path \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ finish_eval \ old_striplib \ striplib \ LD_F77 \ compiler_F77 \ lt_prog_compiler_no_builtin_flag_F77 \ lt_prog_compiler_wl_F77 \ lt_prog_compiler_pic_F77 \ lt_prog_compiler_static_F77 \ lt_cv_prog_compiler_c_o_F77 \ export_dynamic_flag_spec_F77 \ whole_archive_flag_spec_F77 \ compiler_needs_object_F77 \ with_gnu_ld_F77 \ allow_undefined_flag_F77 \ no_undefined_flag_F77 \ hardcode_libdir_flag_spec_F77 \ hardcode_libdir_flag_spec_ld_F77 \ hardcode_libdir_separator_F77 \ fix_srcfile_path_F77 \ exclude_expsyms_F77 \ include_expsyms_F77 \ file_list_spec_F77; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec \ old_archive_cmds_F77 \ old_archive_from_new_cmds_F77 \ old_archive_from_expsyms_cmds_F77 \ archive_cmds_F77 \ archive_expsym_cmds_F77 \ module_cmds_F77 \ module_expsym_cmds_F77 \ export_symbols_cmds_F77 \ prelink_cmds_F77; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` ;; esac ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "epm-header") CONFIG_FILES="$CONFIG_FILES epm-header" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "testdir/Makefile") CONFIG_FILES="$CONFIG_FILES testdir/Makefile" ;; "libsrc2/test/Makefile") CONFIG_FILES="$CONFIG_FILES libsrc2/test/Makefile" ;; "volume_io/Makefile") CONFIG_FILES="$CONFIG_FILES volume_io/Makefile" ;; "volume_io/Documentation/Makefile") CONFIG_FILES="$CONFIG_FILES volume_io/Documentation/Makefile" ;; "volume_io/Testing/Makefile") CONFIG_FILES="$CONFIG_FILES volume_io/Testing/Makefile" ;; "progs/xfm/xfmflip") CONFIG_FILES="$CONFIG_FILES progs/xfm/xfmflip" ;; "progs/minccomplete/minccomplete") CONFIG_FILES="$CONFIG_FILES progs/minccomplete/minccomplete" ;; "progs/minchistory/minchistory") CONFIG_FILES="$CONFIG_FILES progs/minchistory/minchistory" ;; "progs/mincpik/mincpik") CONFIG_FILES="$CONFIG_FILES progs/mincpik/mincpik" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_t=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_t"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="F77 " # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == "file_magic". file_magic_cmd=$lt_file_magic_cmd # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name of the directory that contains temporary libtool files. objdir=$objdir # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that does not interpret backslashes. ECHO=$lt_ECHO # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $* )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[^=]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$@"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1+=\$2" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1=\$$1\$2" } _LT_EOF ;; esac sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: F77 # The linker used to build libraries. LD=$lt_LD_F77 # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_F77 # A language specific compiler. CC=$lt_compiler_F77 # Is the compiler the GNU compiler? with_gcc=$GCC_F77 # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_F77 # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_F77 # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_F77 # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_F77 # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_F77 # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_F77 archive_expsym_cmds=$lt_archive_expsym_cmds_F77 # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_F77 module_expsym_cmds=$lt_module_expsym_cmds_F77 # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_F77 # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_F77 # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_F77 # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_F77 # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_F77 # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_F77 # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_F77 # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_F77 # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_F77 # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path_F77 # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_F77 # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_F77 # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_F77 # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_F77 # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_F77 # Specify filename containing input files. file_list_spec=$lt_file_list_spec_F77 # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_F77 # ### END LIBTOOL TAG CONFIG: F77 _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi minc-2.2.00/AUTHORS0000644000265600003100000000077612027132657010526 00000000000000Peter Neelin designed, coded, and maintained MINC (1992-2002). David MacDonald designed, coded, and maintained VolumeIO (1991-1998). Current maintenance is done on the minc-development mailing list. http://www.bic.mni.mcgill.ca/mailman/listinfo/minc-development MINC Contributors (in alphabetical order) Leila Baghdadi Vladimir Fonov Colin Holmes Andrew Janke David Leonard (original minccalc parser) Claude Lepage Ilana Leppert (dcm2mnc DTI additions) Jason Lerch Steven Robbins John Sled Robert Vincent minc-2.2.00/COPYING0000644000265600003100000000075212030075003010464 00000000000000Copyright the MINC developers, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. minc-2.2.00/ChangeLog0000644000265600003100000011274112030101211011174 00000000000000 -- Release of minc 2.2.00 -- 2012-09-24 Andrew L Janke * added make_mincmorph_kernel.pl * merged changed from develop branch * added -size arguments to mincresample 2012-08-03 Andrew L Janke * progs/mincheader/mincheader: fixed to handle files with spaces 2012-06-21 Andrew L Janke * added mincblob.man1 and updated configure.ac and Makefile.am 2012-05-16 Andrew L Janke * added patches from Jordi Gutiérrez Hermoso * libsrc/hdf_convenience.c: added default switch case * libsrc/ParseArgv.c: added intptr_t casts * conversion/dcm2mnc/dicom_to_minc.c: added initialisation of tmp_offset 2012-04-10 Andrew L Janke * libsrc2/grpattr.c: added a history patch from Leila 2012-03-14 Andrew L Janke * added progs/mincsample 2012-03-14 Andrew L Janke * added progs/mincmorph -- Release of minc 2.1.10 -- 2012-02-22 Andrew L Janke * added a patch from Steve Robbins that factors references to PATH_MAX out to fix a build problem on hurd 2011-12-20 Andrew L Janke * libsrc/netcdf_convenience.c: changed execute_decompress_command() to always decompress the whole file as the approach used for netCDF files for header_only does not work with HDF5 MINC2 files * merged Vlad's ezminc branch 2011-06-29 Andrew L Janke * configure.in: changed typo from enable to disable minc2 2011-05-30 Andrew L Janke * progs/minccalc: added imax() and imin() operators 2011-04-29 Andrew L Janke * libsrc2/volume.c: added minc_version global * libsrc/netcdf_convenience.c: added minc_version global 2011-02-17 Andrew L Janke * libsrc2/test/datatype-test.c: fixed a HDF5 bug in error output 2011-02-14 Andrew L Janke * progs/mincview/mincview: converted from csh to bash and changed from xv to display 2011-02-09 Andrew L Janke * libsrc/minc_compat.h: Added cplusplus extern to header 2011-01-19 Jim Nikelski * Fixed x86_64 ecattominc bug which resulted in a segmentation fault on 64-bit platforms. Change primarily required changing the type of the "dirblock" IO buffer from long to int32_t, reflecting the actual storage type in the ecat file. 2010-11-23 Claude Lepage * Fixed bug in dicom_to_minc.c for segmentation fault on undefined sequence (initialization of gi_ptr->cur_size) * Free some memory after usage 2010-11-23 Ilana Leppert * Added b-matrix field for Siemens diffusion scans (version >= VB only). * Made changes to ordering of slices: e.g. a descending acquisition now has negative slice step. This was an issue with MOSAIC, in which the ordering of the slices in the MOSAIC image is ascending, even though the acquisition is descending (version >= VA25 and >= VB11). -- Release of minc 2.1.00 -- 2010-07-27 Andrew L Janke * conversion/micropet/upet2mnc.c: error bug squashed (John Cupitt) 2010-07-06 Claude Lepage * Improved convergence and accuracy for application of non-linear transformation (especially for 2-d slices) 2010-06-28 Andrew L Janke * Added progs/xfm/xfm2def.c and progs/xfm/xfm2def.man1 2010-05-23 Andrew L Janke * changed all calls to H5Acreate2 to the H5Acreate macro 2010-05-18 Steve M. Robbins * libsrc/hdf_convenience.c: specify version 2 of H5Gopen, H5Acreate. * minc.h: ensure hdf5.h included before netcdf.h to avoid build error with netcdf 4.1.1 and openmpi 1.4.1. 2010-03-22 Andrew L Janke * added pod2man for manpage generation from scripts * shifted minchistory man to POD * conversion/vff2mnc/vff2mnc.c: added error checking for fgets * set default volume_io caching to none * added checks for outfiles in minccalc * removed outdated GETTING_STARTED file 2010-03-02 Andrew L Janke * Added minccmp (minccmp.c and minccmp.man1) * libsrc/hdf_convenience.c: removed spurious debug output * libsrc/minc.h: replaced MAX_NC_OPEN with 32 * libsrc/voxel_loop.c: replaced MAX_NC_OPEN with MI_MAX_NUM_ICV 2010-02-03 Andrew L Janke * progs/mincpik/mincik: added -text_size option (Thanks Mishkin) * removed all non-quoted string barewords (hash refs) * added range calculation for anot bar if not defined 2009-11-13 Andrew L Janke * progs/mincpik/mincpik: added -sagittal_offset_perc option 2009-11-06 Claude Lepage * volume_io/Volumes/output_mnc.c: fix output buffers for a slice as only first buffer would be written out 2009-08-11 Andrew L Janke * progs/mincpik/mincpik: Added taking first time point for 4D files 2009-07-08 Andrew L Janke * Added minimum cmake version to CMakeLists.txt * Added libtoolize/glibtoolize logic in autogen.sh (thanks Sean) 2009-06-03 Claude Lepage * Fixed bug in multidim_array_is_alloced for correct check of memory allocation of image data. Return volume=NULL when memory allocation fails. -- Release of minc 2.0.18 -- 2009-04-29 Claude Lepage * Smarter utilization of buffer in input_mnc.c and output_mnc.c 2009-04-29 Andrew L Janke * progs/mincinfo/mincinfo.c: fixed a stack smash 2009-04-21 Claude Lepage * Fixed bug with chunking for internal file compression using hdf5 (now makes the code faster for large files) -- Release of minc 2.0.17 -- 2009-01-20 Andrew L Janke * Updated version in CMakeLists.txt * Note that with the bugfix in ParseArgv all other MINC programs that link against this will have to be rebuilt. * CMakeLists.txt: updated version Warning cleanups below * conversion/dcm2mnc/minc_file.c: fixed printf type * conversion/dcm2mnc/siemens_to_dicom.c: fixed printf type * conversion/ecattominc/machine_indep.c: added string.h and fixed 2 fprintf missing format args * conversion/micropet/upet2mnc.c: fixed two fprintf format args * conversion/minctoecat/ecat_write.c: added string.h * conversion/minctoecat/minctoecat.c: added missing argument to fprintf * conversion/nifti1/mnc2nii.c: fixed incorrect printf type * progs/mincview/invert_raw_image.c: added fwrite checking 2009-01-03 Steve M. Robbins * testdir/run_test_progs.sh: New. Test that programs like mincheader and mincdiff work properly. * configure.in: Bump to version 2.0.17. * libsrc/ParseArgv.c (ParseArgv): Change ARGV_CONSTANT to treat src and dst and pointer to integer, as documented. Reverts change 6.9 of this file. * testdir/test_arg_parse.c: New. Test program for argument parsing (ParseArgv.[ch]). * testdir/run_test_arg_parse.sh: New. Test driver for above. * testdir/Makefile.am (TESTS): Add run_test_arg_parse.sh. * libsrc2/Makefile.am: Remove; the only content was SUBDIRS = test. * Makefile.am: Change SUBDIRS from libsrc2 to libsrc2/test. * configure.in: Remove libsrc2/Makefile output. * testdir/xfmconcat_01.sh: * testdir/xfmconcat_02.sh: Add -clobber to output-generating commands. * libsrc2/test/testminctools.sh: Add "set -e" to exit on any error. * configure.in: Remove AC_PROG_RANLIB, obsoleted by use of AC_PROG_LIBTOOL. 2008-10-12 Steve M. Robbins * conversion/dcm2mnc/dcm2mnc.man1: * conversion/ecattominc/ecattominc.man1: * conversion/micropet/upet2mnc.man1: * conversion/minctoecat/minctoecat.man1: * conversion/nifti1/mnc2nii.man1: * conversion/nifti1/nii2mnc.man1: * conversion/vff2mnc/vff2mnc.man1: * progs/mincgen/mincgen.man1: Fix errors, mainly removing trailing TAB characters. -- Release of minc 2.0.16 -- 2008-09-04 Andrew L Janke * progs/xfm/xfmconcat.c: Added -verbose and -clobber options * progs/xfm/xfmconcat.man1: added -verbose and -clobber * progs/xfm/xfminvert.man1: added -verbose and -clobber 2008-08-13 Andrew L Janke * progs/rawtominc/rawtominc.c: changed to an enum for modalities to get around an esoteric bug with use of ParseArgv and strings passed by reference on 64 bit architectures 2008-08-11 Andrew L Janke * conversion/Acr_Nema: Many changes from Claude * conversion/dcm2mnc: Many changes for 64 bit and "new" DICOM types 2008-04-07 Andrew L Janke * conversion/ecattominc/ecattominc.c: added config.h * Makefile.am: removed minc_globdef.h * libsrc/minc_basic.h: rewrote error code to avoid global vars (Claude) * libsrc/minc_error.h: changes for error code (Claude) * libsrc/minc_error.c: changes for error code (Claude) 2008-03-08 Andrew L Janke * progs/mincpik/mincpik: fixed a bug with bar width from Mike Ferreira 2008-03-07 Andrew L Janke * progs/mincpik/mincpik: fixed two bugs with lookup triplanars 2008-02-28 Andrew L Janke * progs/mincpik/mincpik: added the -anot_bar option -- Release of minc 2.0.15 -- 2008-02-15 Andrew L Janke * Removed all fortran code (the subdirectory anyhow) * removed get_image_offset.c as it will not work with MINC2 * updated configure.in and Makefile.am to suit * changed --enable-minc2 to --disable-minc2 2008-01-24 Andrew L Janke * AUTHORS: added Claude Lepage * progs/xfm/xfmconcat.c: Added a history patch from Mishkin Derakhshan * conversion/nifti1/nii2mnc.c: Added a patch from Claude for patient names 2008-01-17 Andrew L Janke * libsrc/hdf_convenience.c (hdf_path_from_name): added NC_NAT to switch 2008-01-17 Steve M. Robbins * testdir/test_speed.c (nctypename): Return "unknown" if no switch case used. * libsrc2/test/vector_dimension-test.c (create_test_file): * libsrc2/test/hyper-test-2.c (create_test_file): * conversion/dcm2mnc/dicom_to_minc.c (copy_element_properties): Change return type from int to void; no callers require a return value. * testdir/icv_fillvalue.c (main): * conversion/micropet/upet2mnc.c (main): Return 0 at end of function. 2008-01-17 Andrew L Janke * removed all rcsid's as they are not used * removed a bunch of ^L's that crept in somehow * removed old and out of date BUGS file 2008-01-13 Steve M. Robbins * progs/mincreshape/mincreshape.h: * progs/mincreshape/mincreshape.c: * progs/mincreshape/copy_data.c: Move static function declarations from header file to .c files that define the function. Avoids compiler warnings. * progs/mincresample/mincresample.h: * progs/mincresample/mincresample.c: * progs/mincresample/resample_volumes.c: Move static function declarations from header file to .c files that define the function. Avoids compiler warnings. * progs/minccalc/minccalc.c (constant,constant2): Remove unushed variables. * libsrc/voxel_loop.c (get_output_filename): Remove unused function. * conversion/nifti1/nifti1_local.h: * conversion/nifti1/mnc2nii.c: Move definition of dimnames to .c file where it is used. Avoids compiler warning. * conversion/dcm2mnc/dicom_read.c: Don't declare or define convert_numa3_coordinate(), since the caller is #if 0'd out. 2008-01-12 Steve M. Robbins * libsrc2/hyper.c (mirw_hyperslab_raw): * libsrc/hdf_convenience.c (hdf_varget): Use hsize_t rather than hssize_t for 3rd argument to H5Sselect_hyperslab(). * libsrc/voxel_loop.c: * progs/mincinfo/mincinfo.c: * progs/mincmath/mincmath.c: * progs/rawtominc/rawtominc.c: * testdir/icv.c: * testdir/icv_dim.c: * testdir/icv_dim1.c: * testdir/icv_fillvalue.c: * testdir/icv_range.c: * testdir/minc_types.c: Add braces around static initializers. 2008-01-11 Andrew L Janke * removed outdated TODO file * merged WHATSNEW-2.0 into NEWS/README 2008-01-09 Andrew L Janke * replaced mincedit with a complete rewrite in sh 2008-01-04 Andrew L Janke * mincheader: updated scripting style and replaced tmpdir code 2008-01-02 Steve M. Robbins * testdir/run_tests.sh: * testdir/run_test2.sh: Quote the value assigned to variable tests, so that the scripts run. 2007-12-18 Jonathan Harlap * dcm2mnc: Restored dicom fields in minc headers. (conversion/dcm2mnc/minc_file.c) * dcm2mnc: Restored old name of acquisition comments attribute. (conversion/dcm2mnc/minc_file.c) 2007-12-06 Claude Lepage * Freed more memory in miicv_free (libsrc/image_conversion.c) * Added cubic interpolation in mincresample for x-y slices * Fixed seg fault bug with null history string (libsrc/minc_convenience.c) * Changed hard-coded strings for MIxspace (y,z) (libsrc2/volume.c and libsrc2/dimension.c) * Made global variables static in minccompress to avoid conflict with libz 2007-12-03 Andrew L Janke * changed all global variables to static in progs directory to avoid possible linker errors in the future. 2007-10-23 Andrew L Janke * Added most things needed for a CMake build * nii2mnc mnc2nii: Fixed a linking bug -- Release of minc 2.0.14 -- 2007-09-13 Andrew L Janke * Added a few more free's for memory thanks to Claude 2007-08-24 Andrew L Janke * added xfmflip and man page * fixed a bug in the build of minccalc * updated nifti library for nii2mnc 2007-08-08 Claude Lepage * Increased size of MI_MAX_VAR_BUFFER_SIZE and fix chunking for internal file compression using hdf5 * Modified mincconvert to use default chunking 2007-05-18 Andrew L Janke * Fixed up small problems with build process * replaced csh scripts with sh. (checks fail if no tcsh) * added libsrc2 to the INCLUDES. why this was not in before beats me 2006-09-01 Jonathan Harlap * conversion/Acr_nema - Fixed a bug causing dump_acr_nema to skip all elements with element number 0x0010 2006-05-31 Jonathan Harlap * Makefile.am - modified to build and install image_filters/extract and image_filters/byte_swap if the ACR NEMA tools are intstalled, as they are required by dicom_to_minc.pl 2006-05-18 Bert Vincent * progs/various... added config.h to source files that need it for proper operation with MINC 2.0 2006-04-19 Claude Lepage * fix duplicate instances of solve_linear_system and scaled_maximal_pivoting_gaussian_elimination in volume_io/Geometry/gaussian.c and libsrc.2. Make static. This is to avoid linker problems with minc2. 2006-04-09 Bert Vincent * conversion/dcm2mnc, conversion/Acr_nema - added general support for Siemens DTI sequences, inserting attributes according to Jennifer Campbell's conventions. 2006-03-27 Bert Vincent * conversion/nifti1/mnc2nii.c - Set time and vector dimensions "properly" for some versions of Analyze and NIfTI libraries. Also set the intent_code field to NIFTI_INTENT_VECTOR if the vector_dimension is set. Also fixed an issue with file names. 2006-03-10 Bert Vincent * conversion/Acr_nema/element.c - Modify acr_dump_element_list() to use helper function maybe_print_as_string() to print data with unknown VR as either ASCII or a string of hex bytes. 2006-02-28 Bert Vincent * libsrc/hdf_convenience.c - Modify the hdf_vardef() function to avoid errors in HDF5 1.6.5 2006-02-19 Steve M. Robbins * testdir/create_grid_xfm.c (main): Initialize variable mio before using. 2006-02-09 Bert Vincent * conversion/dcm2mnc/dicom_to_minc.c, conversion/dcm2mnc/siemens_to_dicom.c - Deal more correctly with some odd cases in .IMA files. 2006-02-08 Bert Vincent * progs/rawtominc/rawtominc.c, conversion/nifti1/nii2mnc.c, conversion/micropet/upet2mnc.c: Change fopen() parameter to "rb" to force correct operation on DOS/Windows. * libsrc2/volume.c: Allow signed as well as unsigned base types for labels. 2005-12-15 Bert Vincent * libsrc2/volume.c - set units field unconditionally in _miget_file_dimension() 2005-12-13 Bert Vincent * conversion/dcm2mnc/dicom_to_minc.c: Ignore DICOM protocol errors. This change was necessitated by images from a Philips Intera scanner version 'NT 10.4.1\\PIIM V2.1.4.1 MIMIT MCS' that appears to set the DICOM length field incorrectly. 2005-12-03 Bert Vincent * conversion/micropet/upet2mnc.c - fix handling of single-frame data * progs/mincgen/main.c - make "-o" option imply "-b" 2005-11-22 Bert Vincent * progs/mincgen/genlib.c - fix free() issue * progs/mincgen/load.c - #include config.h 2005-11-11 Bert Vincent * conversion/dcm2mnc/dcm2mnc.h - fix definition of IMA_MAGIC_SIZE * conversion/dcm2mnc/dcm2mnc.c - fix test for is_ima_file() 2005-11-04 Bert Vincent * conversion/dcm2mnc/dicom_to_minc.h - further relaxation of COORDINATE_EPSILON, now set to 0.005 * conversion/dcm2mnc/minc_file.c - combine cloned regular/irregular dimension checking code into new function, check_regular() * conversion/dcm2mnc/dcm2mnc.c - update version to 2.0.07 2005-10-26 Bert Vincent * conversion/dcm2mnc/dicom_to_minc.h - set COORDINATE_EPSILON to a fixed value of 0.0001 rather than 100*FLT_EPSILON to allow for more slop in coordinates. * conversion/nifti1/mnc2nii.c - handle missing value for spacetype. 2005-09-16 Bert Vincent * libsrc2/conversion/dcm2mnc/dicom_read.c - again change the handling of the slice thickness / slice spacing issue to accomodate Andrew Janke's Philips data. If both slice thickness and slice spacing are set, we select the maximum. For some reason I had been choosing the minimum, but logically the opposite seems more reasonable (and is certainly correct in Andrew's case). 2005-09-14 Bert Vincent * libsrc2/slice.c - in function mirw_slice_minmax(), properly reorient access for slice minimum and maximum if dimension order has been altered. * libsrc2/hyper.c - normalize data correctly in miget_real_value_hyperslab(). * progs/mincinfo/mincinfo.c - include config.h 2005-08-26 Bert Vincent * Implemented --enable-hdf5 option in ./configure script so that we can selectively enable or disable MINC2 support. This required changing the way we treat the MINC2 symbol, and being careful to include config.h in all files that call netCDF functions. * libsrc2/grpattr.c - Fixed issue in micreate_group() function - it would not function properly when a group already existed in the file. * conversion/dcm2mnc - Ported changes from MINC 1 branch. 2005-07-29 Bert Vincent * progs/mincstats/mincstats.c: Add warning when mask file specified with no mask range option. 2005-07-28 Bert Vincent * conversion/nifti1/mnc2nii.c: Implement fix suggested by Hyun-Pil Kim to set unused dimension lengths to 1 rather than zero. 2005-07-25 Bert Vincent * progs/mincstats/mincstats.c: Fix calculation of percent threshold to correctly account for non-zero histogram floor. 2005-07-15 Andrew Janke * added -auto_range option to mincpik (thanks to Jon Harlap) 2005-07-15 Bert Vincent * libsrc/hdf_convenience.c: Two minor fixes. First, when emulating 'signtype' attributes in MINC 2 files, comparisons with MI_SIGNED and MI_UNSIGNED should NOT depend on a properly- null-terminated attribute value. Second, suppress HDF5 errors in hdf_attdel() * progs/mincresample/mincresample.c * progs/mincresample/mincresample.h * progs/mincresample/mincresample.man1 * progs/mincresample/resample_volumes.c Support windowed sinc interpolation, as ported from 1.X branch. * progs/mincconcat/mincconcat.c: * progs/mincconcat/mincconcat.man1: Add support for -filestarts option, as ported from 1.X branch. 2005-07-04 Steve M. Robbins * Makefile.am: * progs/minchistory/minchistory.man1: New manual page for minchistory. 2005-07-03 Steve M. Robbins * configure.in: Check for sysconf(). * volume_io/Prog_utils/time.c (get_clock_ticks_per_second): Use POSIX sysconf() function, if available. 2005-06-22 Bert Vincent * Minor fix to ncgenyy.l to avoid compiler complaint on ia64. 2005-05-20 Bert Vincent * Update Makefile.msvc-win32 to build converters. * Declare restructure_array() in hyper.c to be MNCAPI so that nii2mnc can link to it. * Get rid of warnings in mincgen build. Affected files are progs/mincgen/ncgenyy.l and progs/mincgen/ncgentab.y * Replace direct usage of H5Fis_hdf5() function to avoid annoying error messages for nonexistant files. Instead there is now a function named hdf_access() that returns a boolean value TRUE if the file can be accessed and is in HDF5 format. This change affected the files libsrc/hdf_convenience.h, libsrc/hdf_convenience.c, and libsrc/netcdf_convenience.c * Remove and/or conditionalize some test code for memory-mapped files that should not have been checked in. Affected files are libsrc/netcdf_convenience.c, libsrc/hdf_convenience.c, and progs/mincstats/mincstats.c 2005-05-19 Bert Vincent * Fix volume.c and m2util.c to be compatible with HDF5 1.6.3 and later. * Port nifti converter changes from MINC 1.X branch * Port dcm2mnc converter changes from MINC 1.X branch * Port build changes for dcm2mnc and ACR/NEMA library from MINC 1.X branch 2005-04-18 Bert Vincent * Move volume_io headers into Include/volume_io subdirectory. 2005-03-17 Andrew Janke * removed ':' from temporary filenames for windows compatibility 2005-03-11 Bert Vincent * Improve nii2mnc's support for functional (time-varying) data, and support qform as well as sform transforms in the header. 2005-01-28 Bert Vincent * Incorporate NIfTI-1 converters, nii2mnc and mnc2nii * Incorporate upet2mnc, converter for Concorde microPET data. * Copied fix for mincmakescalar to warn user if the vector_dimension is not the last dimension in the file. * Modify Leila's vector_dimension-test code to create its own data file, to avoid having to carry around a multi-megabyte test file as part of the distrbution. 2005-01-19 Bert Vincent * Incorporate Anthonin Reilhac's changes to ecattominc * Add ecattominc, mnc2nii, and nii2mnc to the automake files * Modify mincdump to print long attributes of type NC_BYTE as strings if all of the characters are printable. 2005-01-04 Bert Vincent * Adapt minc_simple.c to use Leila's revision of the restructure_array() parameters. This seems to work properly again. 2004-12-14 Bert Vincent * Got rid of lots of C99-related warnings * Added new biModalT algorithms to mincstats 2004-12-15 Andrew Janke * added epm-header.in, removed mni_minc.epm.header 2004-12-07 Andrew Janke * Squashed yet another bug with the BiModalT code aaargh! This should now replicate volume_stats even closer! 2004-10-18 Andrew Janke * Fixed bug in mincstats -BimodalT code to exactly replicate (within reason) volume_stats * Changed default # of int histogram bins from 10000 to 65536 2004-08-11 Bert Vincent * Fix minc.h for netCDF 3.5.1 2004-08-03 Bert Vincent * Added new test cases to dimension-test.c * Fix bug(s) in volume.c * Correctly implement some of the conversion functions 2004-06-21 Bert Vincent * Updated mincgen man page * "Improve" Doxygen documentation 2004-06-16 Bert Vincent * Fixes and improvements for mincgen/mincdump * Emulate a vector_dimension for MINC 2.0 files with a compound datatype. * Move libsrc2 (MINC 2.0 API) files under the MINC hierarchy in CVS * Fix ordering of world coordinate values in miconvert_world_to_voxel and miconvert_voxel_to_world 2004-06-11 Bert Vincent * Fix issue with minc_modify_header's new -sappend and -dappend options. * Add "mincgen" based upon "ncgen" for "mincedit" * Fix nasty minccalc bug. Minccalc would fail to work properly on any file with a vector_dimension of length greater than 1. 2004-06-09 Bert Vincent * Add netcdf and HDF5 versions to the -version list. 2004-06-08 Bert Vincent * Avoid printing HDF5 errors on excessively long attributes. Still have to decide how best to deal with this situations - truncate, drop, or somehow convert the attribute into a dataset? Right now we will drop excessively large attributes from HDF5 files, which is probably bad. * Fix bug (mentioned in previous entries) which caused mincdump (as derived from ncdump) to print zero-length attributes as an erroneous string of length one instead of as an empty string. * Eliminate bogus "not implemented yet" message from volume_io 2004-06-07 Bert Vincent * Fix setting of length in hdf_vardef/hdf_dimdef * Handle zero-length character strings properly. There is actually a minor bug in "ncdump" which makes zero-length strings appear to have length one (the bogus character will appear to match the first character in the preceding string). 2004-06-04 Bert Vincent * Changed volume_io/Volumes/volume_cache.c to increase both the cache size and the default cached volume size (i.e. the size which turns on caching). 2004-06-01 Bert Vincent * Fixed endian-ness issues in MINC 2.0 format. 2004-05-25 Bert Vincent * Added -dappend, -sappend to minc_modify_header 2004-05-20 Bert Vincent * Revised man pages * Added -2 option to minclookup 2004-04-30 Bert Vincent * Further reduce compiler issues for IRIX MIPSpro compiler. * Tagged version 2.0.06 2004-04-29 Bert Vincent * Fix compiler compatibility problem against IRIX MIPSpro compiler in netcdf_convenience.c 2004-04-22 Bert Vincent * Expanded test cases 2004-04-15 Bert Vincent * Add -DMINC2, #ifdef MINC2 to make most MINC2 additions and changes optional. * Expand minc2_uguide.tex 2004-04-08 Bert Vincent * Add mincdump command * Minor changes to increase portability, esp. to Windows. 2004-03-25 Bert Vincent * Add support for -compress and -chunk options to mincconvert * Some small library fixes * Fix handling of irregular dimension variables in emulation library. 2004-02-27 Bert Vincent * Fix dimorder handling 2004-02-18 Bert Vincent * Fixed handling of "rootvariable" emulation in hdf_convenience.c and netcdf_convenience.c * Fixed behavior of some of the netCDF emulation attribute functions in hdf_convenience.c and minc_compat.c 2004-02-17 Bert Vincent * Fixed mincconvert - added ncendef() * Actually implemented MINC_COMPRESS MINC 1: 2004-03-24 Bert Vincent * Minor fix to miappend_history() in libsrc/minc_convenience.c 2004-03-23 Bert Vincent * Modify configure.in, libsrc/netcdf_convenience.c, volume_io/Prog_utils/files.c, and volume_io/Prog_utils/time.c to make MINC more portable, especially to Windows compilers. 2003-02-02 Bert Vincent * Added -version flag for all executables (or at least all "C" language executables). Implemented in ParseArgv() to make it universal, and applications can override their version number by adding a "ARGV_VERINFO" record to their argTable[]. * Created miget_version() and miappend_history() functions. 2003-12-05 Andrew L. Janke * Changes to mincpik: added -depth option (as per a diff supplied by Jonathan HARLAP); while at it, did a bit of clean-up including replacing home-grown tempdir cleanup with File::Temp; Added -clobber option so that mincpik more closely matches the other minc tools. 2003-11-23 Steve M. Robbins * configure.in: Set version to 1.3. Check for headers sys/stat.h, sys/wait.h, unistd.h; and for functions fork, system, and popen. * libsrc/netcdf_convenience.c: Use above checks for conditional inclusion of headers. (execute_decompress_command): Use fork or system to decompress file, if facility available. 2003-11-21 Steve ROBBINS * volume_io/Include/basic.h: Include for M_PI definition. Build problem reported by Maxime Descoteaux . 2003-11-14 Steve M. Robbins * Makefile.am (libvolume_io_la_LDFLAGS): (libminc_la_LDFLAGS): Update version-info. * progs/rawtominc/rawtominc.c: Include for declaration of swab(). Cast void pointer "image" to unsigned char before adding integer size; otherwise IRIX CC fails. * progs/mincview/invert_raw_image.c (main): * progs/minc_modify_header/minc_modify_header.c (main): Specify return type. * libsrc/voxel_loop.c: * libsrc/value_conversion.c: * libsrc/dim_conversion.c: Include for declaration of fabs(). 2003-11-13 Steve M. Robbins * progs/minchistory: * progs/mincpik: New. Perl scripts moved here from Andrew Janke's "minc_dev" tool set. * Makefile.am (dist_bin_SCRIPTS): Install minchistory and mincpik. * README: Mention minchistory, mincpik. Correct distribution URL. * mni_minc.epm.header: Update license, version. * Makefile.am (EXTRA_DIST): Distribute README.binary_packaging. * configure.in: Run autoupdate; change AM_CONFIG_HEADER to AC_CONFIG_HEADERS. * testdir/Makefile.am (INCLUDES): Add volume_io/Include. 2003-10-31 Bert Vincent * progs/rawtominc/rawtominc.c: Add options -dimorder and -swap_bytes. 2003-06-01 Steve M. Robbins * testdir/Makefile.am (script_tests): * Makefile.am (SUBDIRS): Process volume_io before testdir, because tests may link against volume_io. * volume_io/MNI_formats/gen_xf_io.c (output_one_transform): Update *volume_count after writing a grid transform (thanks, Peter Neelin). * testdir/create_grid_xfm.c: New. Utility to create grid transformation. * testdir/test_xfm.c: Copied from volume_io/Testing/test-xfm.c. * testdir/xfmconcat_01.sh: * testdir/xfmconcat_02.sh: New. Test concatenation of grid transformations. 2003-03-17 Bert Vincent * configure.in: added check for mkstemp(), tempnam(), and tmpnam() * libsrc/netcdf_convenience.c: added definition of micreate_tempfile() * libsrc/minc.h: added declaration of micreate_tempfile() * volume_io/Prog_utils/files.c: replaced uses of tmpnam() with micreate_tempfile(). * volume_io/Volumes/volume_cache.c: replaced use of tmpnam() with micreate_tempfile() 2003-02-14 Jason Lerch * configure.in: Set version to 1.1.1 * mni_minc.epm.header: added. * README.binary_packaging: added. 2003-01-17 Steve M. Robbins * configure.in: Set version to 1.2. 2003-01-17 Steve M. Robbins * MINC-1-1 tagged. * README.release: * INSTALL.minc: new. * AUTHORS: * GETTING_STARTED: * INSTALL: * README: Tune up for release. 2003-01-10 Steve M. Robbins * testdir/Makefile.am (INCLUDES): * volume_io/Testing/Makefile.am (INCLUDES): Set includes for test files. * Makefile.am (EXTRA_DIST, dist-hook): Distribute fortran subdirectory, sans the CVS files. * progs/mincstats/mincstats.man1: Document change of -max_bins to -int_max_bins. 2003-01-09 Steve M. Robbins * progs/rawtominc/rawtominc.man1: Document -skip option. * volume_io/Makefile.am: New. * volume_io/Documentation/Makefile.am: New. * volume_io/Testing/check_xfm.sh: * volume_io/Testing/test-xfm.c: * volume_io/Testing/t1.xfm: * volume_io/Testing/t2.xfm: * volume_io/Testing/t3.xfm: * volume_io/Testing/t3_grid_0.mnc: * volume_io/Testing/Makefile.am: New. * volume_io/Testing/test-xfm.c: Allow tolerance specified on command line. Exit with nonzero status if point out of tolerance. * Makefile.am (dist_man3_MANS): Distribute and install ParseArgv(3). (EXTRA_DIST): Distribute get_image_offset.c (not built). (noinst_HEADERS): Remove vax_conversions.h (not used). * doc/Makefile: Removed. * doc/Makefile.am: New. * testdir/run_tests.csh: Use -e flag to stop on error. Look for expected output files in $srcdir. * testdir/Makefile: Removed. * testdir/Makefile.am: New. * configure.in: * Makefile.am: Adjust for testdir/Makefile. 2003-01-07 Steve M. Robbins * autogen.sh: New. * Makefile.am: New. * configure.in: Updated to use automake, libtool. * AUTHORS: New. * LICENCE: Renamed to ... * COPYING: ... this. Makes automake happier. * progs/coordinates/voxeltoworld.man1: * progs/minccopy/minccopy.man1: * progs/mincdiff/mincdiff.man1: * progs/mincedit/mincedit.man1: * progs/mincextract/mincextract.man1: * progs/minctoraw/minctoraw.man1: * progs/mincview/invert_raw_image.man1: * progs/mincview/mincview.man1: * progs/mincwindow/mincwindow.man1: * progs/xfm/transformtags.man1: * progs/xfm/xfmconcat.man1: * progs/xfm/xfminvert.man1: New. 2002-12-11 Steve M. Robbins * progs/minccalc/gram.y: Insert missing semicolon at end of "exprlist" production. 2002-12-05 Steve Robbins * volume_io/Include/vol_io_prototypes.h: Add prototype for get_volume_translation(). 2002-11-05 Jason Lerch * progs/mincresample/mincresample.{c,h}: changed the setting of the interpolation type to go through an enum rather than directly to a function pointer, as that is the behaviour that ParseArgv expects and also makes mincresample 64 bit safe. 2002-10-30 Jason Lerch * libsrc/ParseArgv: added the ARGV_LONG argument type. * progs/mincresample/mincresample.c: changed the parsing of the nelements arguments to be ARGV_LONG. 2002-09-05 Andrew Janke * progs/mincstats/mincstats.c: Change command line option "-max_bins" to "-int_max_bins", to avoid clash with option "-max". 2002-09-03 Steve M. Robbins * CHANGES: Renamed ... * NEWS: ... to this. NEWS is the place to document important user-visible changes. The ChangeLog is the place for more detailed notes. See http://www.gnu.org/prep/standards.html. * volume_io/MNI_formats/gen_xfs.c (transform_or_invert_point): Do not flip inverse_flag when transform inverted. * volume_io/Testing/test-xfm.c: New. Regression tests for General_transforms. 2002-08-22 Steve M. Robbins * volume_io/Documentation/volume_io.tex (section{Volume Input}): Clarify notion of vector volume and vector-to-scalar conversion. * progs/minccalc/eval.c: * progs/minccalc/gram.y: * progs/minccalc/lex.l: * progs/minccalc/minccalc.man1: * progs/minccalc/node.c: * progs/minccalc/node.h: Add support for tan, asin, acos, and atan, courtesy of Andrew Janke. 2002-08-04 Peter Neelin * progs/rawtominc/rawtominc.c: Add slightly modified code from Colin Holmes to support -skip option. 2002-04-08 John Sled * progs/mincstats/mincstats.c: Do not call fclose() on NULL file pointer. 2002-02-22 Steve M. Robbins * libsrc/ParseArgv.h: Declare code with "C" linkage when included by C++ compiler. minc-2.2.00/INSTALL0000644000265600003100000003633212030077514010476 00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. minc-2.2.00/NEWS0000644000265600003100000007456112030101334010136 00000000000000New in Release 2.2.00 --------------------- * added mincmorph, mincblob and mincsample * many bugfixes for minc 2.0 code * last release before split of libminc from minc-tools New in Release 2.1.10 --------------------- * added imin() and imax() operators to minccalc * added a minc_version global to files created with minc * Fixed a few HDF5 error output bugs * mincview is now coded in sh, not csh also shifted from xv to display * Fixed bug in dicom_to_minc.c for segmentation fault on undefined sequence (initialization of gi_ptr->cur_size) * Fixed some memory leaks (thanks Jim Nikelski) * Added b-matrix field for Siemens diffusion scans (version >= VB only). (thanks to Ilana Leppert) * Made changes to ordering of slices: e.g. a descending acquisition now has negative slice step. This was an issue with MOSAIC, in which the ordering of the slices in the MOSAIC image is ascending, even though the acquisition is descending (version >= VA25 and >= VB11). (thanks to Ilana Leppert) New in Release 2.1.00 --------------------- * Improved convergence and accuracy for application of non-linear transformation (especially for 2-d slices) - Claude * Set default volume_io caching to none * Added pod2man for man page generation of help for perl scripts * Added minccmp and xfm2def man man pages * Added checks for outfiles to minccalc * Added taking first time point for 4D files, -test_size and -sagittal_offset_perc to mincpik * ported some HDF calls to 1.8.x (must now use 1.8.X; 1.6.X no longer supported from now on) * Added libtoolize/glibtoolize logic in autogen.sh (thanks Sean) * Fixed bug in multidim_array_is_alloced for correct check of memory allocation of image data. Return volume=NULL when memory allocation fails. * Fixed a bug in upet2mnc on 64 bit platforms (thanks John Cupitt) New in Release 2.0.18 --------------------- * Fixed bug with chunking for internal file compression using hdf5 (now makes the code faster for large files) * Smarter utilization of buffer in input_mnc.c and output_mnc.c New in Release 2.0.17 --------------------- * Fix for argument handling on 64 bit systems, previously the order of arguments could cause some arguments to be missed. * New tests for argument parsing, mincheader and mincdiff * Cosmetic fixes for a lot of manpages * Fixed a bunch of warnings for cleaner Debian and Ubuntu builds New in Release 2.0.16 --------------------- * new option for mincpik (-anot_bar) and two bugs fixed for lookup triplanars * updates to dcm2mnc for 64bit machines thanks to Claude * 64bit bug fixes for rawtominc * added -clobber and -verbose options to xfmconcat New in Release 2.0.15 --------------------- * MINC2 is now built by default (or disabled with --disable-minc2). * Began to aggregate and update all docs for a clean(er) 2.1 release * Added cubic interpoation in mincresample for x-y slices * Fixed a seg-fault with null history strings * Changed all global variables to static to avoid linking problems with other libraries (eg: libz) * new version of mincedit/mincheader in sh instead of csh * Many fixes to remove compile warnings * removed all rcsid's in files given that we have a -version argument * Added preservation of "patient name" in nii2mnc (where patient name is the descriptor field in a nifti/analyze file) * xfmconcat now records history in the output file * removed all fortran build bits. This code was both out of date and not ever built * removed get_image_offset as with a MINC2 file this would not work as it was it wouldn't work that well with MINC1 let along MINC2 * changed --enable-minc2 to --disable-minc2 in configure.ac (come what may....) New in Release 2.0.14 --------------------- * Added files needed for a CMake build of MINC * Fixed a linking problem with nii2mnc mnc2nii New in Release 2.0.13 --------------------- * Fixed a few small build errors for make check * Changes to ensure there is a clean ITK minc build * added xfmflip * Fixed buffering and chunking for fast internal file compression * updated nii2mnc and mnc2nii with the latest version of niftilib New in Release 2.0.12 --------------------- * Fixed a bug causing dump_acr_nema to skip all elements with element number 0x0010. New in Release 2.0.11 --------------------- * Many small fixes * fix to mincresample * Small fix to mincconvert * -like flag added to rawtominc * Added additional tests for minc2 files. New in Release 2.0.10 --------------------- * Many small fixes to dcm2mnc * Fix mincgen HDF5 support * Fix upet2mnc handling of single-frame files * Fix mincgen -o option to imply -b * Fix duplicate symbols of solve_linear_system and scaled_maximal_pivoting_gaussian_elimination in volume_io/Geometry/gaussian.c and libsrc.2. New in Release 2.0.09 --------------------- This release is primarily a bug fix release for the core MINC libraries, as well as an opportunity to port library changes from the 1.X series. One of the most important changes involves support for HDF5 versions subsequent to version 1.6.2. Previous releases of MINC 2 would not work properly with HDF5 1.6.3 or later, but these issues should now be fixed. Additional major changes include: New converters added in this release: * minctoecat, as contributed by Anthonin Reilhac. * dcm2mnc mincresample now supports "windowed sinc" interpolation. See the man page for more details. mincconcat now has a "-filestarts" option for greater flexibility in combining files. This is especially useful for concatenating functional runs. * mincresample now supports the sinc interpolant * mincconcat has new -filestarts option * Many updates and fixes to upet2mnc (Concorde microPET conversion) * Fixes to the MINC 2.0 library (libminc2) courtesy of Leila Baghdadi * Some progress on documentation * Improved nii2mnc, Analyze and NIfTI-1 conversion utility * Fix MINC 2 code to work with HDF5 1.6.4 as well as 1.6.2. There is a problem with the "make check" self-test code when using HDF5 1.6.3, but this problem should not affect normal operation of the code. New in Release 2.0.08 --------------------- Several major changes are incorporated into this release. First, the "simplified" MINC interface is now included in the release. This interface, which is still under development, is intended to provide easier access for software that does not need to use MINC's more advanced features. Second, we are beginning to include conversion programs with MINC. For this release, we are including converters for the new NIfTI-1 format, created as a successor to Analyze. FSL 3.2 and other popular fMRI packages now support this format. For PET users we are also including the ECAT to MINC format converter, with updates from Anthonin Reilhac Third, some new tool features have been added and bugs have been fixed. * The mincstats bimodal threshold calculation has been fixed and improved. Mincstats now supports multiple algorithms for calculating the bimodal threshold. The default is still the "Otsu '97" algorithm, where the code for this has been corrected to give more reasonable results. In addition we have implemented the "Kittler & Illingworth '86", the "Kapur et al. '85", and a simple "mean of means" algorithms as options. * mincmakescalar now warns the user if an attempt is made to convert a file that has a vector_dimension that is NOT the fastest-varying dimension in the image. Previously the program would simply copy the input file to the output unmodified, without warning the user. In addition to these changes, many bugs and issues with the MINC 2.0 format and interface have been fixed. * Added conversion subdirectory with PRELIMINARY converters for ECAT, Concorde microPET, and NIfTI-1 data files. * Simplified MINC programming interface. * Many bug fixes * See WHATSNEW-2.0 for additional details New in Release 2.0.07 --------------------- * Added automatic creation of "ident" attribute in all MINC files. * Added -sappend and -dappend arguments to minc_modify_header * Most man pages updated * Fixed endian-ness issues which could affect interoperability in MINC 2.0 format * Changed volume_io caching defaults New in Release 2.0.06 --------------------- * No functional changes - this release is intended only to address compilation issues found with the SGI IRIX MIPSpro compiler. New in Release 2.0.05 --------------------- This version represents several weeks of effort cleaning up the existing code and trying to put things into better shape for a release. In particular, the existing test suites ("make check") now run for both MINC 1.0 and MINC 2.0 format files. One functional change is that the MINC 2.0 tools should now create MINC 2.0 format files by default if all of the input files are themselves in MINC 2.0 format. In other words, you only have to specify the "-2" option to force a MINC 2.0 file if one or more of your input files are MINC 1.0 format. The environment variable "MINC_FORCE_V2" should force all output to MINC 2.0 even if MINC 1.0 files are present at the input. There is additional documentation on the new "2.0" MINC programming interface. This is still very much a work in progress so your feedback is very much appreciated, both as to the form and content of these documents: libsrc2/doc/minc_20.tex - Interface reference libsrc2/doc/minc2_uguide.tex - Programmer's guide This distribution will build its libraries as "libminc2.a" and "libvolume_io2.a", rather than the previous "libminc.a" and "libvolume_io.a". This decission was intended to make it easier to keep both MINC1 and MINC2 libraries installed simultaneously, but this may prove to be unwieldy or unnecessary. We welcome suggestions from beta testers. * More bugs fixed * "make check" expanded to test MINC 2.0 format. * "mincdump" added to the distribution. * Almost all MINC 2.0 specific changes are now surrounded by "#ifdef MINC2" New in Release 2.0.04 --------------------- * More bugs fixed * mincconvert now takes a -compress and -chunk option to force the output file to take on a desired structure. * User's guide to MINC 2.0 library is now in doc/minc2_uguide.tex. It's a work in progress but it should contain some useful information. New in Release 2.0.03 --------------------- * Actually implemented MINC_COMPRESS * Many bugs fixed New in Release 2.0.02 --------------------- * Several bug fixes * Even newer error handling New in Release 2.0.01 --------------------- * Support for HDF5 "MINC 2.0" format files. * Revised error message handling. Some new, unwanted messages are probably present. * Tentative .mincrc and environment variable support. * New programming interface. New in Release 1.3 ------------------ * Build fixes. New in Release 1.2 ------------------ * New tools: mincpik, minchistory. * Rawtominc has new options -dimorder and -swap_bytes. * Ability to easily create binary packages; see README.binary_packaging. New in Release 1.1 ------------------ * All MINC programs now ship with a man page. * Rawtominc has new "-skip" option, to allow skipping header information. * Mincstats option "-max_bins" renamed to "-int_max_bins", to avoid clash with "-max". * Minccalc has new functions: tan, asin, acos, and atan. ************************************************************************ Wed Jan 16 08:43:28 EST 2002 *** RELEASE OF MINC 1.0 Tue Jan 15 12:55:21 EST 2002 - Modified libsrc/Makefile to install ParseArgv man pages. Tue Jan 15 10:40:49 EST 2002 - Updated README to include minccalc and mincstats. Mon Jan 14 16:26:53 - Moved nd_loop, voxel_loop, ParseArgv and time_stamp to the libsrc directory for inclusion in the minc library. The header files will continue to be separate from minc.h Mon Jan 14 15:02:39 EST 2002 - Modified voxel_loop so that input buffers have a minimum size (1K voxels). This prevents large output images from forcing buffers to contain only one voxel when the requested memory is not large enough. Wed Jan 9 08:58:27 EST 2002 - Modified mincstats to only print a blank line after the histogram info if -quiet is not specified. Fri Dec 14 12:12:42 EST 2001 - Removed rcsid variables from volume_io .h files. Mon Dec 10 09:11:58 EST 2001 - Sped up mincstats by only doing centre-of-mass summing when it is needed (thanks to Andrew Janke for the suggestion). Thu Dec 6 16:55:50 EST 2001 - extensive modifications to mincstats to get it working properly and to add support for multiple volume and mask ranges. Thu Dec 6 09:14:22 EST 2001 - Corrected return from mivar_exists in minc library to use MI_RETURN so that ncopts is properly restored. Tue Dec 4 12:24:29 EST 2001 - No code changes, but checked in lex.c and gram.c in progs/minccalc. This fixes an interaction problem between make and CVS. When exporting the minc tree the file dates are set to the commit time. If the generated .c files were previously committed at the same time as the generating files (.l and .y), then later makes on the exported files might try to rebuild the .c files. Since these file dates tend to end up in the distribution, the distribution will not build cleanly without bison and flex being installed. Wed Nov 28 10:36:13 EST 2001 - Removed limit on number of icv's that can exist at one time. The definition of MI_MAX_NUM_ICV remains, but it is no longer enforced. - Added function set_minc_input_user_real_range to allow users to set the scaling for input to integers. This forces the Volume real range to a particular pair of values, rather than using the full range of the file. - Added get_info_voxel_index to voxel_loop to allow users to get the full multi-dimensional file index of the current voxel. - Allow arg_string in voxel_loop to be NULL. Tue Nov 13 16:04:36 EST 2001 - Modified icv normalization handling in minc library. When the icv type is floating point, normalization is always done (scaling to real values), regardless of the normalization setting. When the file type is floating point, rescaling of internal integers are done using the slice real range (image-max/min). Thus image-max/min are only completely ignored for integer to integer conversion. This fixes some problems that appeared when converting from int to float or float to int with mincrehape. Tue Nov 13 09:17:17 EST 2001 - Added functions miget_image_range and mivar_exists to minc_convenience.c. - In mincreshape, set output valid range correctly for conversion from int to float types. Wed Oct 31 14:40:30 EST 2001 - Fixed mincinfo printing of sign for default output. Change to miget_datatype had messed this up. - Changed names of macros _R and _P in volume_io/Include/geometry.h to avoid clashes with macro in ctype.h. Wed Oct 17 14:33:00 EDT 2001 - Modified miset_valid_range to write out valid_range as double in all cases except float. Unfortunately, writing out values in a type that matched the type of the image variable caused problems with programs linked against old minc libraries. Tue Sep 18 11:47:13 EDT 2001 - In library function miset_valid_range, changed output type of valid_range from byte to short when image type is byte. Tue Sep 18 11:34:16 EDT 2001 - Always create image variable last in order to allow images > 2GB on 64-bit machines (offset to variable must be < 2GB, but size can be greater). This also fixes a compatibility problem between NetCDF 3.x and 2.3, in which 3.x can create files that cause 2.3-linked programs to crash (when NC_NOFILL is set). Putting the image variable at the end ensures that data is always written to the end of the file, assuming that the image data will always be completely written. Mon Aug 20 09:20:04 EDT 2001 - more fixes to valid_range handling functions - added function miattget_with_sign Thu Aug 16 12:47:32 EDT 2001 - added library functions to handle reading and writing of valid_range and reading of type and sign, as well as setting of default range values for a given type. These routines properly handle type differences between valid_range and the image variable. For the case of a float image and a double valid_range attribute, valid data can go out of range and appear invalid through rounding in the conversion from double to float and back. Writing of the valid_range attribute now follows the NetCDF convention of having the same type for variables and valid_range. Modified volume_io, voxel_loop and programs to use these functions. - modified minctoraw so that user must specify either -normalize or -nonormalize Mon Aug 13 09:44:13 EDT 2001 - Changed use of floorf to floor in macro SCALAR_ROUND of node.h in minccalc. - Added invocation of ranlib when installing minc and volume_io libraries. ************************************************************************ Fri Aug 10 08:49:54 EDT 2001 *** RELEASE OF MINC 0.8 Fri Aug 10 08:49:34 EDT 2001 - Fixed Makefiles in doc directories so that they build properly Tue Apr 24 14:18:07 EDT 2001 - Added minccalc from Andrew Janke to progs directory. Tue Apr 24 12:21:42 EDT 2001 - Fixed bug in execute_decompress_command in libsrc/netcdf_convenience.c that caused multiple stdio buffer flushing when opening compressed files (particularly with mincinfo). - Moved volume_io documentation build from doc directory to volume_io/Documentation, and added install-docs target to top-level Makefile. Tue Apr 24 09:43:38 EDT 2001 - Replaced NC_NAT by MI_ORIGINAL_TYPE since NC_NAT is not defined for NetCDF 3.1-3.4. Because NC_NAT and NC_UNSPECIFIED are defined through enums, they cannot be detected by the preprocessor. So we just define MI_ORIGINAL_TYPE to the same value ((nc_type) 0). Mon Apr 23 09:20:36 EDT 2001 - Fixed volume_io/Volumes/output_mnc.c to pass cdfid to mivarput* instead of minc_icv id (patch from Steve Robbins). Problems showed up when used NetCDF 3.x Tue Apr 17 15:00:48 EDT 2001 - Modified to build with NetCDF 3.x. Changed NC_LONG to NC_INT, as well as corresponding longs to ints. Replaced NC_UNSPECIFIED with NC_NAT (not-a-type). Changed volume_io to use UNSIGNED_INT instead of UNSIGNED_LONG. Added appropriate definitions to support both of these with both NetCDF 2.x and 3.x. Changed error handling to be independent of NetCDF library apart from use of ncopts and ncerr. Uses old style NetCDF2 error handling still, but no longer makes use of NetCDF internals. Removed all prototype wrappers to only support ANSI C. Changed fortran build - no longer generate .c from .src with m4 since fortran support mechanism under NetCDF has changed. Keeping irix5 .c file for backwards compatibility. Only build when BUILD_FORTRAN is set to "yes". Mon Apr 2 11:35:29 EDT 2001 - Added -keep_real_range option to mincresample for resampling labels. Fri Nov 3 11:44:38 EST 2000 - Modified -dinsert option to minc_modify_header to allow multiple values. Tue Sep 19 11:37:41 EDT 2000 - Added option for user-defined allocation function to voxel_loop code - Added LICENSE file to top-level directory Wed Sep 13 11:38:49 EDT 2000 - added bzip support (patches from Steve Robbins) - modified TMPDIR to look in /var/tmp, /usr/tmp, /tmp in scripts mincdiff, mincheader, mincview and mincedit (Steve Robbins) - converted mincheader and mincdiff to Bourne shell (Steve Robbins) Fri Jul 7 09:34:17 EDT 2000 - added -filelist option to mincaverage, mincmath, mincconcat to read input file names from a file. This gets around command-line length limits. Wed Apr 26 15:36:04 EDT 2000 - modified mincinfo to handle multiple files (patch from Steve Robbins) Wed Apr 5 09:02:55 EDT 2000 - fixed bug in mincresample to properly handle valid fillvalues in slices containing no original data. ************************************************************************ Tue Mar 21 10:03:15 EST 2000 *** RELEASE OF MINC 0.7 Wed Feb 2 13:43:43 EST 2000 - modified miexpand_file in library so that fclose is not called with a NULL fp when the file does not exist. This would cause a seg fault with newer versions of glibc. Thu Jan 20 15:36:04 EST 2000 - Re-arranged headers in volume_io so that only volume_io.h needs to be on the search path. Other header files are installed in the volume_io subdirectory and found by volume_io.h. (Patch from Steve Robbins.) Tue Oct 19 14:45:27 1999 - Completed conversion from RCS to CVS Fri Oct 15 15:25:56 EST 1999 - Moved the Acr_nema libraries and conversion programs out of the minc package. Fri Nov 13 11:02:51 EST 1998 - Modified acrnema library to support asynchronous transfers in the client routines (allow sending of next message before receiving reply to previous one). Wed Nov 11 11:28:34 EST 1998 - Modifications to acrnema library: Added functions acr_find_group and acr_group_steal_element. Increased default buffer size to 64KB. Thu Feb 19 09:06:38 EDT 1998 - Fixes to internals of mincreshape that had not yet shown symptoms, but appeared with insure++. Thu Aug 13 15:35:15 EDT 1998 - Modified mincconcat so that the coordinate variable corresponding to the concatenation dimension is always created, subscripted with by the dimension (like an irregularly-spaced dimension). This is required by some programs that want all of the time points (in particular) to be stored even for a regularly-spaced dimension. Mon Jun 22 10:06:29 EDT 1998 - Fixed bug in rawtominc in handling of default types and signs. This bug showed up when options -short and -scan_range were used with data containing negative values. Wed Apr 22 16:23:06 EDT 1998 - Fixed a bug in fortran test program minc_ftest.f in which an insufficient number of arguments were being passed to miclos. Mon Mar 23 15:17:49 EST 1998 - Moved some functions in the acr-nema library from one file to another. Tue Mar 17 12:05:43 EST 1998 - Modified acrnema library so that default maximum length for client connections is 1MB to fix problems with servers that do not handle maximum length 0 (unlimited). Tue Mar 10 12:07:28 EST 1998 - Fixed more bugs in acrnema library to prevent core dumps under Linux when a protocol error occurs while reading a message. Also fixed handling of last fragment bit for DICOM command PDV's. Re-organized code to use watchpoints more consistently in dicom_network.c Fri Feb 20 12:29:18 EST 1998 - Fixed bug in acrnema library (dicom_client_routines) that sometimes caused write errors under irix 5.3. Thu Feb 19 10:05:34 EST 1998 - Minor bug fixes. Wed Feb 18 15:29:28 EST 1998 - Minor bug fixes in libacrnema. Mon Sep 29 08:24:20 EDT 1997 - Modified rawtominc so that its argument error messages are more explicit. Wed Sep 17 09:24:32 EDT 1997 - Modified gcomserver to do conversions to dicom and retransmit data to a dicom server. ************************************************************************ Fri Sep 12 13:24:48 EDT 1997 *** RELEASE OF MINC 0.6 Thu Sep 11 10:54:41 EDT 1997 - Copied in new version of volume_io. The version released with minc 0.5 was missing function set_volume_translation. It has been re-instated. Thu Sep 11 09:46:51 EDT 1997 - Modified gcomserver to have project file syntax that allows different things to be done to the data. The old syntax is still supported. Wed Sep 10 15:31:27 EDT 1997 - Small modification to dicomserver (siemens_dicom_read.c) to set default direction cosines properly if they are absent from the dicom data. Mon Sep 08 17:52:21 EDT 1997 - Added dicom client routines to acr_nema library. - Added new status for connection timeout to acr_nema library. Tue Sep 02 18:52:12 EDT 1997 - Fixed acr_nema library (element.c) padding of UI-type elements (pad with NUL instead of blank). ************************************************************************ Thu Aug 21 09:22:18 EDT 1997 *** RELEASE OF MINC 0.5 Wed Aug 13 19:30:00 EDT 1997 - Changes to acr-nema library: Fixed bug that was causing the loss of PDU items on read in dicom_network.c. Added function acr_group_remove_element to group.c. Wed Aug 13 12:09:37 EDT 1997 - Copied in new release of volume_io Wed Aug 13 11:44:38 EDT 1997 - Fixed initialization bug in mincresample that caused it to always crash under Linux Tue Aug 12 11:44:38 EDT 1997 - Added new program mincmakevector for assembling a list of scalar files into one vector file. Thu Aug 7 11:44:38 EDT 1997 - Added new program mincmakescalar for converting vector volumes to scalar by various schemes. Fri Jun 20 09:59:47 EDT 1997 - Fixed bug in voxel_loop that affected mincconcat when concatenating 4D (or greater) files. Basically, when there are no output files and accumulation is used, then an outer loop over files is done (process each file in order). With 4D or greater input files, the first volume of each file would be handled correctly, but subsequent volumes would only have the last slice read in. Tue Jun 3 10:59:29 EDT 1997 - Really corrected dimension width suffix added by mincconcat. Changed to _width to -width (fix of Aug 27, 1996 was not complete) ************************************************************************ Wed May 7 16:05:05 EDT 1997 *** RELEASE OF MINC 0.4 Wed May 7 15:09:58 EDT 1997 - Changed distribution script to use gzip instead of compress. Thu Apr 24 13:48:51 EDT 1997 - Added mincmath options: -maximum, -minimum, -abs, -illegal_value and -count_valid. Wed Apr 23 10:58:02 EDT 1997 - Added code to volume_io/Prog_utils/files.c to handle missing strerror (on SunOS). Modified configure.in and Make_machine_specific.in to define constant in this case (through GLOBAL_CDEFINES). - Fixed progs install so that directories with more than one binary will get them all installed under linux (bash seems to have a problem with my Bourne shell code). - Added dependencies for install targets. They were removed at one point, but it seems safer to have them in. They'll probably disappear at a later point, and perhaps I'll make a note of the reason...! - Added options -maximum, -minimum, -abs, -illegal_value and -count_valid to mincmath. Fixed handling of invalid or uninitialized data for cumulative operations. Mon Apr 21 13:33:55 EDT 1997 - Fixed icv calculation of scale so that values are never re-scaled from their internal "real" value to an external floating-point type (or the other way around). Previously, this re-scaling could occur if normalization was turned off and a valid range was set in the file. Thu Apr 17 14:45:18 EDT 1997 - Added option of setting BUILD_FORTRAN to "no" for configure. - Moved building of volume_io documentations to docs directory. - Added explicit path to run_tests script Thu Apr 10 15:23:32 EDT 1997 - Fixed icv handling of invalid data when the scale factor is zero. When this happens fillvalue checking is turned on (for both input and output) regardless of the user setting. This fixes problems when mincmath is writing out a uniform image that contains invalid data as well. - Removed redefinition of NULL from library header file and added casts to pointer types in places where it matters. Mon Mar 10 15:23:32 EDT 1997 - Updated ACR-NEMA library to handle dicom messages. Wed Jan 15 11:26:28 EST 1997 - Fixed small bug in test program minc_types.c so that handling of FLT_MAX is done properly and output agrees with original output and Tue Jan 14 14:47:40 EST 1997 - Added Fortran wrappers miopn, micre and miclos Tue Jan 7 14:47:40 EST 1997 - Added -origin option to rawtominc. Tue Dec 10 09:30:21 EST 1996 - Modified top-level Makefile - added targets libs, programs, test and docs - default make no longer does make in docs directory Tue Aug 27 13:08:18 EDT 1996 - Corrected dimension width suffix added by mincconcat. Changed to _width to -width. Wed Jul 10 13:08:18 EDT 1996 - Modified minclookup: - added output type options - added -lut_string - added handling of duplicate first or last lookup table entries - added man page Wed Jun 19 14:26:33 EDT 1996 - Catch errors in opening file specified with -input for rawtominc Tue Jan 16 08:30:08 EST 1996 - Added -invert option to mincmath Wed Dec 13 08:47:26 EST 1995 - Added -check_dimensions and -nocheck_dimensions options to mincmath. - Improved tmp dir cleanup in mincview when an error occurs. - Small changes to minc_modify_header man page. Tue Dec 12 14:19:07 EST 1995 - Added convert_origin_to_start routines to Proglib to handle conversion of a point to a start value given 3 direction cosines - Modified mincresample: - modified argument parsing so that only one pass is done - changed default to transform input sampling when -transformation is specified and added options -tfm_input_sampling (to get above behaviour) and -use_input_sampling (to get old behaviour). - added -origin option to specify a coordinate instead of dimension start values. - added -standard_sampling option. - added -invert_transformation option. - added -spacetype, -talairach and -units options. Mon Nov 20 14:24:47 EST 1995 - Added -weights option to mincaverage. Thu Nov 16 13:11:16 EST 1995 - Include math.h in rawtominc, mincwindow, mincinfo, mincconcat and Acr_nema library to get declaration of strtod under SunOs. Wed Oct 4 19:05:25 EDT 1995 - Fixed default minimum for signed long. Fri Sep 29 12:59:06 EDT 1995 - Modified micopy_all_atts in library to handle MI_ERROR being passed as a variable id. - Fixed handling of image-min/max in mincconcat when the variables are not present in the input files. Wed Aug 2 13:41:36 - Added -prefix option to gyrotominc. Fri Jun 16 08:28:39 EDT 1995 - Modified mincview so that file name appears in xv window frame. Tue Jun 13 16:44:28 EDT 1995 - Improved test for ANSI compiler in configure script. Check that (signed char *) is handled properly (since the Solaris compiler doesn't handle it from what I've been told). - Improved configuration for fortran compilation. Set FORTRAN_SUBDIR and FORTRAN_OBJ from configure only if f77 is found and the system is irix. Mon Jun 12 13:32:53 EDT 1995 - Added MI_LABEL modality to minc.h - Modified miexpand_file and miopen to try adding compression extensions to filenames if the first open fails. minc-2.2.00/Makefile.msvc-win320000644000265600003100000002734412027132657013025 00000000000000# # Makefile for MINC using Microsoft Visual C/C++ (on Windows, natch). # # Written for Microsoft's NMAKE utility, but appears to work # more-or-less correctly with GNU Make for Windows (as in Cygwin). # # Builds all of the MINC command-line utilities, along with the # MINC libraries MINC2.DLL and VOLUME_IO2.DLL # # Assumes that the environment variable NETCDF_ROOT points to # the location of netcdf.lib and netcdf.h. This could be made # more flexible to allow the library and header to reside in # different directories. # # $Header: /private-cvsroot/minc/Makefile.msvc-win32,v 6.6 2008-04-11 05:19:26 rotor Exp $ # PROGS = worldtovoxel.exe \ voxeltoworld.exe \ minc_modify_header.exe \ mincaverage.exe \ minccalc.exe \ mincconcat.exe \ mincconvert.exe \ minccopy.exe \ mincdump.exe \ mincexpand.exe \ mincextract.exe \ mincgen.exe \ mincinfo.exe \ minclookup.exe \ mincmakescalar.exe \ mincmakevector.exe \ mincmath.exe \ mincresample.exe \ mincreshape.exe \ mincstats.exe \ minctoraw.exe \ invert_raw_image.exe \ mincwindow.exe \ rawtominc.exe \ xfmconcat.exe \ xfminvert.exe \ ecattominc.exe \ minctoecat.exe \ mnc2nii.exe \ nii2mnc.exe \ upet2mnc.exe \ dcm2mnc.exe MINC_HDRS = \ libsrc\minc.h \ libsrc\minc_basic.h \ libsrc\minc_private.h \ libsrc\minc_routines.h \ libsrc\minc_structures.h \ libsrc\minc_useful.h \ libsrc\minc_varlists.h \ libsrc\nd_loop.h \ libsrc\ParseArgv.h \ libsrc\time_stamp.h \ libsrc\type_limits.h \ libsrc\voxel_loop.h \ libsrc\minc_error.h \ libsrc\minc_config.h \ libsrc\minc_compat.h MINC_OBJS = \ libsrc\ParseArgv.obj \ libsrc\dim_conversion.obj \ libsrc\image_conversion.obj \ libsrc\minc_convenience.obj \ libsrc\minc_error.obj \ libsrc\nd_loop.obj \ libsrc\netcdf_convenience.obj \ libsrc\time_stamp.obj \ libsrc\value_conversion.obj \ libsrc\voxel_loop.obj \ libsrc\hdf_convenience.obj \ libsrc\minc_compat.obj MINC2_OBJS = \ libsrc2\convert.obj \ libsrc2\datatype.obj \ libsrc2\dimension.obj \ libsrc2\free.obj \ libsrc2\grpattr.obj \ libsrc2\hyper.obj \ libsrc2\label.obj \ libsrc2\m2util.obj \ libsrc2\record.obj \ libsrc2\slice.obj \ libsrc2\valid.obj \ libsrc2\volprops.obj \ libsrc2\volume.obj VOLIO_OBJS = \ volume_io/Geometry/colour.obj \ volume_io/Geometry/colour_def.obj \ volume_io/Geometry/gaussian.obj \ volume_io/Geometry/inverse.obj \ volume_io/Geometry/newton.obj \ volume_io/Geometry/points.obj \ volume_io/Geometry/splines.obj \ volume_io/Geometry/tensors.obj \ volume_io/Geometry/transforms.obj \ volume_io/MNI_formats/gen_xf_io.obj \ volume_io/MNI_formats/gen_xfs.obj \ volume_io/MNI_formats/grid_transforms.obj \ volume_io/MNI_formats/mni_io.obj \ volume_io/MNI_formats/tag_points.obj \ volume_io/MNI_formats/thin_plate_spline.obj \ volume_io/Prog_utils/alloc.obj \ volume_io/Prog_utils/alloc_check.obj \ volume_io/Prog_utils/arrays.obj \ volume_io/Prog_utils/files.obj \ volume_io/Prog_utils/print.obj \ volume_io/Prog_utils/progress.obj \ volume_io/Prog_utils/string.obj \ volume_io/Prog_utils/time.obj \ volume_io/Volumes/evaluate.obj \ volume_io/Volumes/get_hyperslab.obj \ volume_io/Volumes/input_free.obj \ volume_io/Volumes/input_mnc.obj \ volume_io/Volumes/input_volume.obj \ volume_io/Volumes/multidim_arrays.obj \ volume_io/Volumes/output_mnc.obj \ volume_io/Volumes/output_volume.obj \ volume_io/Volumes/set_hyperslab.obj \ volume_io/Volumes/volume_cache.obj \ volume_io/Volumes/volumes.obj # Unfortunately the CVS tree does not reflect the desired file organization # of the software, so we have to fix that up here: VOLIO_HDRS = \ volume_io\Include\volume_io\alloc.h \ volume_io\Include\volume_io\arrays.h \ volume_io\Include\volume_io\basic.h \ volume_io\Include\volume_io\def_math.h \ volume_io\Include\volume_io\files.h \ volume_io\Include\volume_io\geometry.h \ volume_io\Include\volume_io\geom_structs.h \ volume_io\Include\volume_io\multidim.h \ volume_io\Include\volume_io\progress.h \ volume_io\Include\volume_io\string_funcs.h \ volume_io\Include\volume_io\system_dependent.h \ volume_io\Include\volume_io\transforms.h \ volume_io\Include\volume_io\vol_io_prototypes.h \ volume_io\Include\volume_io\volume_cache.h \ volume_io\Include\volume_io\volume.h ACR_NEMA_OBJS = \ conversion\Acr_nema\acr_io.obj \ conversion\Acr_nema\element.obj \ conversion\Acr_nema\file_io.obj \ conversion\Acr_nema\group.obj \ conversion\Acr_nema\message.obj \ conversion\Acr_nema\value_repr.obj ACR_NEMA_HDRS = \ conversion\Acr_nema\acr_nema.h \ conversion\Acr_nema\acr_nema\acr_io.h \ conversion\Acr_nema\acr_nema\element.h \ conversion\Acr_nema\acr_nema\file_io.h \ conversion\Acr_nema\acr_nema\group.h \ conversion\Acr_nema\acr_nema\message.h \ conversion\Acr_nema\acr_nema\value_repr.h INCLUDES = -I$(NETCDF_ROOT) -I$(HDF5_ROOT)/include -Ilibsrc \ -Iprogs/Proglib -Ivolume_io/Include -Iconversion/Acr_nema DEFINES = -DDLL_NETCDF -D_POSIX_ -DMINC2 -DWIN32 -D_HDF5USEDLL_ \ -DHAVE_CONFIG_H -D_USE_MATH_DEFINES NETCDF_LIB = $(NETCDF_ROOT)/netcdf.lib HDF5_LIB = $(HDF5_ROOT)/dll/hdf5dll.lib LIBS = minc2.lib volume_io2.lib $(NETCDF_LIB) $(HDF5_LIB) CFLAGS = $(INCLUDES) $(DEFINES) .SUFFIXES: .obj .c.obj: cl /nologo $(CFLAGS) -c -Fo$*.obj $< all: $(PROGS) minc2.dll volume_io2.dll clean: -del /s *.obj -del *.exp -del *.lib -del *.dll -del *.exe -del *.map LINK = link $(PROGS): minc2.dll volume_io2.dll $(MINC_OBJS): libsrc\config.h $(MINC_HDRS) $(MINC2_OBJS): libsrc2\minc2.h libsrc2\minc2_private.h minc2.dll: $(MINC_OBJS) $(MINC2_OBJS) link /dll /nologo /map:minc2.map /out:minc2.dll $(MINC_OBJS) $(MINC2_OBJS) $(NETCDF_LIB) $(HDF5_LIB) ws2_32.lib volume_io2.dll: $(VOLIO_OBJS) minc2.dll link /dll /nologo /map:volume_io2.map /out:volume_io2.dll $(VOLIO_OBJS) minc2.lib $(NETCDF_LIB) $(HDF5_LIB) $(VOLIO_OBJS): $(VOLIO_HDRS) libsrc\config.h: libsrc\config.h.msvc-win32 copy libsrc\config.h.msvc-win32 libsrc\config.h WORLDTOVOXEL_OBJS = progs/coordinates/worldtovoxel.obj worldtovoxel.exe: $(WORLDTOVOXEL_OBJS) $(LINK) $(WORLDTOVOXEL_OBJS) $(LIBS) VOXELTOWORLD_OBJS = progs/coordinates/voxeltoworld.obj voxeltoworld.exe: $(VOXELTOWORLD_OBJS) $(LINK) $(VOXELTOWORLD_OBJS) $(LIBS) MINC_MODIFY_HEADER_OBJS = progs/minc_modify_header/minc_modify_header.obj minc_modify_header.exe: $(MINC_MODIFY_HEADER_OBJS) $(LINK) $(MINC_MODIFY_HEADER_OBJS) $(LIBS) MINCAVERAGE_OBJS = progs/mincaverage/mincaverage.obj mincaverage.exe: $(MINCAVERAGE_OBJS) $(LINK) $(MINCAVERAGE_OBJS) $(LIBS) MINCCALC_OBJS = \ progs/minccalc/minccalc.obj \ progs/minccalc/gram.obj \ progs/minccalc/lex.obj \ progs/minccalc/eval.obj \ progs/minccalc/ident.obj \ progs/minccalc/node.obj \ progs/minccalc/optim.obj \ progs/minccalc/scalar.obj \ progs/minccalc/sym.obj \ progs/minccalc/vector.obj minccalc.exe: $(MINCCALC_OBJS) $(LINK) $(MINCCALC_OBJS) $(LIBS) MINCCONCAT_OBJS = progs/mincconcat/mincconcat.obj mincconcat.exe: $(MINCCONCAT_OBJS) $(LINK) $(MINCCONCAT_OBJS) $(LIBS) MINCCONVERT_OBJS = progs/mincconvert/mincconvert.obj mincconvert.exe: $(MINCCONVERT_OBJS) $(LINK) $(MINCCONVERT_OBJS) $(LIBS) MINCCOPY_OBJS = progs/minccopy/minccopy.obj minccopy.exe: $(MINCCOPY_OBJS) $(LINK) $(MINCCOPY_OBJS) $(LIBS) MINCDUMP_OBJS = \ progs/mincdump/mincdump.obj \ progs/mincdump/vardata.obj \ progs/mincdump/dumplib.obj mincdump.exe: $(MINCDUMP_OBJS) $(LINK) $(MINCDUMP_OBJS) $(LIBS) MINCEXPAND_OBJS = progs/mincexpand/mincexpand.obj mincexpand.exe: $(MINCEXPAND_OBJS) $(LINK) $(MINCEXPAND_OBJS) $(LIBS) MINCEXTRACT_OBJS = progs/mincextract/mincextract.obj mincextract.exe: $(MINCEXTRACT_OBJS) $(LINK) $(MINCEXTRACT_OBJS) $(LIBS) MINCGEN_OBJS = \ progs/mincgen/escapes.obj \ progs/mincgen/genlib.obj \ progs/mincgen/getfill.obj \ progs/mincgen/init.obj \ progs/mincgen/load.obj \ progs/mincgen/main.obj \ progs/mincgen/ncgentab.obj \ progs/mincgen/ncgenyy.obj mincgen.exe: $(MINCGEN_OBJS) $(LINK) $(MINCGEN_OBJS) $(LIBS) MINCINFO_OBJS = progs/mincinfo/mincinfo.obj mincinfo.exe: $(MINCINFO_OBJS) $(LINK) $(MINCINFO_OBJS) $(LIBS) MINCLOOKUP_OBJS = progs/minclookup/minclookup.obj minclookup.exe: $(MINCLOOKUP_OBJS) $(LINK) $(MINCLOOKUP_OBJS) $(LIBS) MINCMAKESCALAR_OBJS = progs/mincmakescalar/mincmakescalar.obj mincmakescalar.exe: $(MINCMAKESCALAR_OBJS) $(LINK) $(MINCMAKESCALAR_OBJS) $(LIBS) MINCMAKEVECTOR_OBJS = progs/mincmakevector/mincmakevector.obj mincmakevector.exe: $(MINCMAKEVECTOR_OBJS) $(LINK) $(MINCMAKEVECTOR_OBJS) $(LIBS) MINCMATH_OBJS = progs/mincmath/mincmath.obj mincmath.exe: $(MINCMATH_OBJS) $(LINK) $(MINCMATH_OBJS) $(LIBS) MINCRESAMPLE_OBJS = \ progs/mincresample/mincresample.obj \ progs/mincresample/resample_volumes.obj \ progs/Proglib/convert_origin_to_start.obj mincresample.exe: $(MINCRESAMPLE_OBJS) $(LINK) $(MINCRESAMPLE_OBJS) $(LIBS) MINCRESHAPE_OBJS = \ progs/mincreshape/mincreshape.obj \ progs/mincreshape/copy_data.obj mincreshape.exe: $(MINCRESHAPE_OBJS) $(LINK) $(MINCRESHAPE_OBJS) $(LIBS) MINCSTATS_OBJS = progs/mincstats/mincstats.obj mincstats.exe: $(MINCSTATS_OBJS) $(LINK) $(MINCSTATS_OBJS) $(LIBS) MINCTORAW_OBJS = progs/minctoraw/minctoraw.obj minctoraw.exe: $(MINCTORAW_OBJS) $(LINK) $(MINCTORAW_OBJS) $(LIBS) INVERT_RAW_IMAGE_OBJS = progs/mincview/invert_raw_image.obj invert_raw_image.exe: $(INVERT_RAW_IMAGE_OBJS) $(LINK) $(INVERT_RAW_IMAGE_OBJS) $(LIBS) MINCWINDOW_OBJS = progs/mincwindow/mincwindow.obj mincwindow.exe: $(MINCWINDOW_OBJS) $(LINK) $(MINCWINDOW_OBJS) $(LIBS) RAWTOMINC_OBJS = \ progs/rawtominc/rawtominc.obj \ progs/Proglib/convert_origin_to_start.obj rawtominc.exe: $(RAWTOMINC_OBJS) $(LINK) $(RAWTOMINC_OBJS) $(LIBS) XFMCONCAT_OBJS = progs/xfm/xfmconcat.obj xfmconcat.exe: $(XFMCONCAT_OBJS) $(LINK) $(XFMCONCAT_OBJS) $(LIBS) XFMINVERT_OBJS = progs/xfm/xfminvert.obj xfminvert.exe: $(XFMINVERT_OBJS) $(LINK) $(XFMINVERT_OBJS) $(LIBS) ECATTOMINC_OBJS = \ conversion/ecattominc/ecat_file.obj \ conversion/ecattominc/ecattominc.obj \ conversion/ecattominc/insertblood.obj \ conversion/ecattominc/machine_indep.obj $(ECATTOMINC_OBJS): conversion/ecattominc/ecat_file.h \ conversion/ecattominc/machine_indep.h \ conversion/ecattominc/ecat_header_definition.h ecattominc.exe: $(ECATTOMINC_OBJS) $(LINK) $(ECATTOMINC_OBJS) $(LIBS) WS2_32.LIB MINCTOECAT_OBJS = \ conversion/minctoecat/ecat_write.obj \ conversion/minctoecat/minctoecat.obj \ conversion/minctoecat/machine_indep.obj $(MINCTOECAT_OBJS): conversion/minctoecat/ecat_write.h \ conversion/minctoecat/machine_indep.h minctoecat.exe: $(MINCTOECAT_OBJS) $(LINK) $(MINCTOECAT_OBJS) $(LIBS) NII2MNC_OBJS = \ conversion/nifti1/nii2mnc.obj \ conversion/nifti1/nifti1_io.obj NII2MNC_OBJS: conversion/nifti1/nifti1.h \ conversion/nifti1/nifti1_io.h nii2mnc.exe: $(NII2MNC_OBJS) $(LINK) $(NII2MNC_OBJS) $(LIBS) MNC2NII_OBJS = \ conversion/nifti1/mnc2nii.obj \ conversion/nifti1/nifti1_io.obj MNC2NII_OBJS: conversion/nifti1/nifti1.h \ conversion/nifti1/nifti1_io.h mnc2nii.exe: $(MNC2NII_OBJS) $(LINK) $(MNC2NII_OBJS) $(LIBS) UPET2MNC_OBJS = \ conversion/micropet/upet2mnc.obj upet2mnc.exe: $(UPET2MNC_OBJS) $(LINK) $(UPET2MNC_OBJS) $(LIBS) $(ACR_NEMA_OBJS): $(ACR_NEMA_HDRS) DCM2MNC_OBJS = \ conversion/dcm2mnc/dcm2mnc.obj \ conversion/dcm2mnc/dicom_to_minc.obj \ conversion/dcm2mnc/dicom_read.obj \ conversion/dcm2mnc/minc_file.obj \ conversion/dcm2mnc/progress.obj \ conversion/dcm2mnc/siemens_to_dicom.obj \ conversion/dcm2mnc/string_to_filename.obj \ $(ACR_NEMA_OBJS) dcm2mnc.exe: $(DCM2MNC_OBJS) $(LINK) $(DCM2MNC_OBJS) $(LIBS) minc-2.2.00/INSTALL.minc0000644000265600003100000000243512027132657011426 00000000000000See INSTALL for generic installation instructions. Shared or Static libraries? --------------------------- By default, only a static version (i.e. libminc.a) will be produced. A shared version of the library may be enabled using the configure flag "--enabled-shared". See also "--disable-static". Finding NetCDF/HDF5 ------------------- The NetCDF and HDF libraries must be built and installed before you can build MINC. Teaching MINC to find the NetCDF library depends on where the latter is installed. There are two possibilities here: 1. NetCDF and HDF5 may be installed in a location where the compiler can find it. If so, you have nothing to do. 2. Third-party libraries are commonly installed with headers in /usr/local/include and libraries in /usr/local/include. If this is the case, you should pass the argument "--with-build-path=/usr/local" to configure as such: ./configure --with-build-path=/usr/local 3. Use NetCDF 4.X and HDF5 1.8.X for minc-2.1.X. Compiling --------- Now that things are configured all you need to do is run: make and then make install Building against the MINC2 library ---------------------------------- From here on in if you wish to build against the MINC2 library with other packages you will have to use the --with-minc2 configure flag minc-2.2.00/CMakeLists.txt0000644000265600003100000003140412030114015012164 00000000000000# CMakeFiles.txt for the MINC2 library # # Andrew Janke - a.janke@gmail.com # Vladimir S. FONOV - vladimir.fonov@gmail.com PROJECT(minc2) SET(MINC2_PACKAGE_VERSION_MAJOR 2) SET(MINC2_PACKAGE_VERSION_MINOR 2) SET(MINC2_PACKAGE_VERSION_PATCH 00) SET(PACKAGE "minc2") SET(PACKAGE_BUGREPORT "a.janke@gmail.com") SET(PACKAGE_NAME "minc2") SET(PACKAGE_VERSION "${MINC2_PACKAGE_VERSION_MAJOR}.${MINC2_PACKAGE_VERSION_MINOR}.${MINC2_PACKAGE_VERSION_PATCH}") SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") ENABLE_TESTING() INCLUDE(CTest) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) IF(MINC_TOOLKIT_BUILD) SET(MINC2_EXTERNALLY_CONFIGURED ON) ENDIF(MINC_TOOLKIT_BUILD) IF(NOT MINC2_EXTERNALLY_CONFIGURED) SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules") SET(CPACK_GENERATOR TGZ) SET(CPACK_PACKAGE_VERSION_MAJOR ${MINC2_PACKAGE_VERSION_MAJOR}) SET(CPACK_PACKAGE_VERSION_MINOR ${MINC2_PACKAGE_VERSION_MINOR}) SET(CPACK_PACKAGE_VERSION_PATCH ${MINC2_PACKAGE_VERSION_PATCH}) OPTION(MINC2_BUILD_SHARED_LIBS "Build minc2 with shared libraries." OFF) INCLUDE(CPack) OPTION(MINC2_BUILD_V2 "Support minc2 file format" ON) OPTION(MINC2_BUILD_TOOLS "Build minc tools (mincreshape,mincresample, etc)" ON) OPTION(MINC2_BUILD_CONVERTERS "Build minc conversion programs (mnc2nii, nii2mnc , dcm2mnc...)" ON) OPTION(MINC2_BUILD_EZMINC "Build C++ interface library EZminc" ON) OPTION(MINC2_BUILD_EZMINC_EXAMPLES "Build EZminc examples" ON) ENDIF(NOT MINC2_EXTERNALLY_CONFIGURED) IF(MINC2_BUILD_V2 AND NOT MINC2_EXTERNALLY_CONFIGURED) IF(ITK_FOUND AND ITK_VERSION_MAJOR VERSION_EQUAL 4) # check if using ITK HDF5 library IF(ITKHDF5_LOADED) SET(USE_ITK_HDF5 ON) ELSE(ITKHDF5_LOADED) SET(USE_ITK_HDF5 OFF) ENDIF(ITKHDF5_LOADED) ELSE(ITK_FOUND AND ITK_VERSION_MAJOR VERSION_EQUAL 4) # check if using ITK HDF5 library SET(USE_ITK_HDF5 OFF) ENDIF(ITK_FOUND AND ITK_VERSION_MAJOR VERSION_EQUAL 4) # check if using ITK HDF5 library ENDIF(MINC2_BUILD_V2 AND NOT MINC2_EXTERNALLY_CONFIGURED) IF(MINC2_BUILD_SHARED_LIBS) SET(LIBRARY_TYPE SHARED) SET(LIBRARY_INSTALL LIBRARY) ELSE(MINC2_BUILD_SHARED_LIBS) SET(LIBRARY_TYPE STATIC) SET(LIBRARY_INSTALL ARCHIVE) ENDIF(MINC2_BUILD_SHARED_LIBS) # external packages IF(NOT MINC2_EXTERNALLY_CONFIGURED) FIND_PACKAGE(NETCDF REQUIRED) ENDIF(NOT MINC2_EXTERNALLY_CONFIGURED) IF(MINC2_BUILD_V2 AND NOT MINC2_EXTERNALLY_CONFIGURED) IF(USE_ITK_HDF5) SET(HDF5_INCLUDE_DIR "${ITKHDF5_INCLUDE_DIRS}/itkhdf5") # a hack? SET(HDF5_LIBRARY ${ITKHDF5_LIBRARIES}) SET(ZLIB_LIBRARY ${ITKZLIB_LIBRARIES}) ELSE(USE_ITK_HDF5) FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(HDF5 REQUIRED) ENDIF(USE_ITK_HDF5) IF(ZLIB_FOUND) SET(HAVE_ZLIB 1) ELSE(ZLIB_FOUND) FIND_PACKAGE(ZLIB) IF(ZLIB_FOUND) SET(HAVE_ZLIB 1) ENDIF(ZLIB_FOUND) ENDIF(ZLIB_FOUND) ENDIF(MINC2_BUILD_V2 AND NOT MINC2_EXTERNALLY_CONFIGURED) # add for building relocatable library IF(UNIX) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") ENDIF(UNIX) # check for prereqs INCLUDE(CheckFunctionExists) CHECK_FUNCTION_EXISTS(mkstemp HAVE_MKSTEMP) CHECK_FUNCTION_EXISTS(tmpnam HAVE_TMPNAM) CHECK_FUNCTION_EXISTS(tempnam HAVE_TEMPNAM) CHECK_FUNCTION_EXISTS(strerror HAVE_STRERROR) CHECK_FUNCTION_EXISTS(popen HAVE_POPEN) CHECK_FUNCTION_EXISTS(fork HAVE_WORKING_FORK) CHECK_FUNCTION_EXISTS(vfork HAVE_WORKING_VFORK) CHECK_FUNCTION_EXISTS(fdopen HAVE_FDOPEN) CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP) CHECK_FUNCTION_EXISTS(getpwnam HAVE_GETPWNAM) CHECK_FUNCTION_EXISTS(select HAVE_SELECT) CHECK_FUNCTION_EXISTS(strerror HAVE_STRERROR) CHECK_FUNCTION_EXISTS(sysconf HAVE_SYSCONF) CHECK_FUNCTION_EXISTS(system HAVE_SYSTEM) INCLUDE(CheckIncludeFiles) CHECK_INCLUDE_FILES(float.h HAVE_FLOAT_H) CHECK_INCLUDE_FILES(sys/dir.h HAVE_SYS_DIR_H) CHECK_INCLUDE_FILES(sys/ndir.h HAVE_SYS_NDIR_H) CHECK_INCLUDE_FILES(sys/stat.h HAVE_SYS_STAT_H) CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H) CHECK_INCLUDE_FILES(sys/wait.h HAVE_SYS_WAIT_H) CHECK_INCLUDE_FILES(values.h HAVE_VALUES_H) CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES(dirent.h HAVE_DIRENT_H) CHECK_INCLUDE_FILES(memory.h HAVE_MEMORY_H) CHECK_INCLUDE_FILES(stdlib.h HAVE_STDLIB_H) CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H) CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN_H) CHECK_INCLUDE_FILES(vfork.h HAVE_VFORK_H) CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H) CHECK_INCLUDE_FILES(string.h HAVE_STRING_H) CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H) CHECK_INCLUDE_FILES(pwd.h HAVE_PWD_H) ADD_DEFINITIONS(-DHAVE_CONFIG_H) # aliases SET(VERSION "${PACKAGE_VERSION}") IF(MINC2_BUILD_EZMINC) set(MINC2_INCLUDE_DIRS_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/ezminc ) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/ezminc ) ENDIF(MINC2_BUILD_EZMINC) # netcdf and HDF5 IF(MINC2_BUILD_V2) FIND_PACKAGE(ZLIB REQUIRED) SET(MINC2 "1") ELSE(BUILD_MINC2) SET(MINC2 "0") ENDIF(MINC2_BUILD_V2) # config files for build CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY) # others CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/epm-header.in ${CMAKE_CURRENT_BINARY_DIR}/epm-header) # set the master INCLUDE directories INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libsrc ${CMAKE_CURRENT_SOURCE_DIR}/volume_io/Include ) INCLUDE_DIRECTORIES( ${NETCDF_INCLUDE_DIR} ) IF(MINC2_BUILD_V2) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libsrc2 ) ENDIF(MINC2_BUILD_V2) # some variables SET(minc1_LIB_SRCS libsrc/ParseArgv.c libsrc/dim_conversion.c libsrc/image_conversion.c libsrc/minc_convenience.c libsrc/minc_error.c libsrc/nd_loop.c libsrc/netcdf_convenience.c libsrc/time_stamp.c libsrc/value_conversion.c libsrc/voxel_loop.c libsrc/hdf_convenience.c libsrc/minc_compat.c libsrc/minc_simple.c libsrc/read_file_names.c ) SET(minc1_HEADERS libsrc/minc.h libsrc/ParseArgv.h libsrc/voxel_loop.h libsrc/nd_loop.h libsrc/time_stamp.h libsrc/minc_compat.h volume_io/Include/volume_io.h libsrc/minc_simple.h ) SET(minc2_LIB_SRCS libsrc2/convert.c libsrc2/datatype.c libsrc2/dimension.c libsrc2/free.c libsrc2/grpattr.c libsrc2/hyper.c libsrc2/label.c libsrc2/m2util.c libsrc2/record.c libsrc2/slice.c libsrc2/valid.c libsrc2/volprops.c libsrc2/volume.c ) SET(minc2_HEADERS libsrc2/minc2.h ) # volume_io2 SET(volume_io_LIB_SRCS volume_io/Geometry/colour.c volume_io/Geometry/colour_def.c volume_io/Geometry/gaussian.c volume_io/Geometry/inverse.c volume_io/Geometry/newton.c volume_io/Geometry/points.c volume_io/Geometry/splines.c volume_io/Geometry/tensors.c volume_io/Geometry/transforms.c volume_io/MNI_formats/gen_xf_io.c volume_io/MNI_formats/gen_xfs.c volume_io/MNI_formats/grid_transforms.c volume_io/MNI_formats/mni_io.c volume_io/MNI_formats/tag_points.c volume_io/MNI_formats/thin_plate_spline.c volume_io/Prog_utils/alloc.c volume_io/Prog_utils/alloc_check.c volume_io/Prog_utils/arrays.c volume_io/Prog_utils/files.c volume_io/Prog_utils/print.c volume_io/Prog_utils/progress.c volume_io/Prog_utils/string.c volume_io/Prog_utils/time.c volume_io/Volumes/evaluate.c volume_io/Volumes/get_hyperslab.c volume_io/Volumes/input_free.c volume_io/Volumes/input_mnc.c volume_io/Volumes/input_volume.c volume_io/Volumes/multidim_arrays.c volume_io/Volumes/output_mnc.c volume_io/Volumes/output_volume.c volume_io/Volumes/set_hyperslab.c volume_io/Volumes/volume_cache.c volume_io/Volumes/volumes.c ) SET(volume_io_HEADERS volume_io/Include/volume_io/alloc.h volume_io/Include/volume_io/arrays.h volume_io/Include/volume_io/basic.h volume_io/Include/volume_io/def_math.h volume_io/Include/volume_io/files.h volume_io/Include/volume_io/geom_structs.h volume_io/Include/volume_io/geometry.h volume_io/Include/internal_volume_io.h volume_io/Include/volume_io/multidim.h volume_io/Include/volume_io/progress.h volume_io/Include/volume_io/string_funcs.h volume_io/Include/volume_io/system_dependent.h volume_io/Include/volume_io/transforms.h volume_io/Include/volume_io/vol_io_prototypes.h volume_io/Include/volume_io/volume.h volume_io/Include/volume_io/volume_cache.h ) SET(MINC2_LIBRARY minc) SET(VOLUME_IO_LIBRARY volume_io) SET(MINC2_LIBRARIES ${MINC2_LIBRARY} ${NETCDF_LIBRARY}) #SET(MINC2_DEPENDENCIES "") IF(MINC2_BUILD_V2) INCLUDE_DIRECTORIES( ${HDF5_INCLUDE_DIR} ) SET(minc_LIB_SRCS ${minc1_LIB_SRCS} ${minc2_LIB_SRCS}) SET(minc_HEADERS ${minc1_HEADERS} ${minc2_HEADERS}) SET(MINC2_LIBRARY minc2) SET(MINC2_LIBRARIES ${MINC2_LIBRARY} ${HDF5_LIBRARY} ${NETCDF_LIBRARY} ${ZLIB_LIBRARY} m ) SET(VOLUME_IO_LIBRARY volume_io2) ELSE(MINC2_BUILD_V2) SET(minc_LIB_SRCS ${minc1_LIB_SRCS} ) SET(minc_HEADERS ${minc1_HEADERS} ${minc2_HEADERS}) ENDIF(MINC2_BUILD_V2) ADD_LIBRARY(${MINC2_LIBRARY} ${LIBRARY_TYPE} ${minc_LIB_SRCS} ) TARGET_LINK_LIBRARIES(${MINC2_LIBRARY} ${NETCDF_LIBRARY} ${HDF5_LIBRARY} ${ZLIB_LIBRARY} m ) ADD_LIBRARY(${VOLUME_IO_LIBRARY} ${LIBRARY_TYPE} ${volume_io_LIB_SRCS}) TARGET_LINK_LIBRARIES(${VOLUME_IO_LIBRARY} ${MINC2_LIBRARY}) SET_TARGET_PROPERTIES(${MINC2_LIBRARY} PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${MINC2_PACKAGE_VERSION_MAJOR}) SET_TARGET_PROPERTIES(${VOLUME_IO_LIBRARY} PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${MINC2_PACKAGE_VERSION_MAJOR}) ADD_DEPENDENCIES(${VOLUME_IO_LIBRARY} ${MINC2_LIBRARY}) INSTALL(TARGETS ${MINC2_LIBRARY} ${LIBRARY_INSTALL} DESTINATION lib) INSTALL(TARGETS ${VOLUME_IO_LIBRARY} ${LIBRARY_INSTALL} DESTINATION lib) INSTALL(FILES ${minc_HEADERS} DESTINATION include ) INSTALL(FILES ${volume_io_HEADERS} DESTINATION include/volume_io) IF(MINC2_BUILD_TOOLS) ADD_SUBDIRECTORY( progs ) ENDIF(MINC2_BUILD_TOOLS) IF(MINC2_BUILD_CONVERTERS) ADD_SUBDIRECTORY( conversion ) ENDIF(MINC2_BUILD_CONVERTERS) IF(MINC2_BUILD_EZMINC) ADD_SUBDIRECTORY( ezminc ) ENDIF(MINC2_BUILD_EZMINC) # config for the build directory set(MINC2_USE_FILE_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/UseMINC2.cmake) set(MINC2_INCLUDE_DIRS_CONFIG ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libsrc ${CMAKE_CURRENT_SOURCE_DIR}/volume_io/Include ) IF(MINC2_BUILD_EZMINC) set(MINC2_INCLUDE_DIRS_CONFIG ${MINC2_INCLUDE_DIRS_CONFIG} ${CMAKE_CURRENT_SOURCE_DIR}/ezminc) ENDIF(MINC2_BUILD_EZMINC) IF(MINC2_BUILD_V2) set(MINC2_INCLUDE_DIRS_CONFIG ${MINC2_INCLUDE_DIRS_CONFIG} ${CMAKE_CURRENT_SOURCE_DIR}/libsrc2 ) ENDIF(MINC2_BUILD_V2) IF(MINC2_BUILD_EZMINC) SET(EZMINC_LIBRARIES minc_io ${MINC2_LIBRARIES}) ENDIF(MINC2_BUILD_EZMINC) set(MINC2_LIBRARY_DIRS_CONFIG ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/ezminc) set(MINC2_LIBRARIES_CONFIG ${MINC2_LIBRARIES}) configure_file(MINC2Config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/MINC2Config.cmake @ONLY ) configure_file(UseMINC2.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/UseMINC2.cmake @ONLY) # config for install dir set(MINC2_USE_FILE_CONFIG "${CMAKE_INSTALL_PREFIX}/lib/UseMINC2.cmake") set(MINC2_INCLUDE_DIRS_CONFIG ${CMAKE_INSTALL_PREFIX}/include ) set(MINC2_LIBRARY_DIRS_CONFIG ${CMAKE_INSTALL_PREFIX}/lib) #fix for superbuild install IF(SUPERBUILD_STAGING_PREFIX) STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" MINC2_INCLUDE_DIRS_CONFIG "${MINC2_INCLUDE_DIRS_CONFIG}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" MINC2_LIBRARY_DIRS_CONFIG "${MINC2_LIBRARY_DIRS_CONFIG}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" MINC2_LIBRARIES_CONFIG "${MINC2_LIBRARIES_CONFIG}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" EZMINC_LIBRARIES "${EZMINC_LIBRARIES}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" NETCDF_INCLUDE_DIR "${NETCDF_INCLUDE_DIR}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIR}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" NETCDF_LIBRARY "${NETCDF_LIBRARY}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" HDF5_LIBRARY "${HDF5_LIBRARY}") STRING(REPLACE "${SUPERBUILD_STAGING_PREFIX}/" "" ZLIB_LIBRARIES "${ZLIB_LIBRARIES}") ENDIF(SUPERBUILD_STAGING_PREFIX) configure_file(MINC2Config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/MINC2Config.cmake @ONLY ) configure_file(UseMINC2.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/UseMINC2.cmake @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/UseMINC2.cmake ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/MINC2Config.cmake DESTINATION lib COMPONENT Development) # testing IF(BUILD_TESTING) ADD_SUBDIRECTORY(testdir) ENDIF(BUILD_TESTING) minc-2.2.00/config.h.cmake0000644000265600003100000000266512030075003012133 00000000000000/* various defines */ #define MINC2 @MINC2@ #define PACKAGE_NAME "@PACKAGE_NAME@" #define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" #define PACKAGE_VERSION "@PACKAGE_VERSION@" #define PACKAGE_STRING "@PACKAGE_STRING@" #define VERSION PACKAGE_VERSION #define H5Acreate_vers 2 #cmakedefine HAVE_MKSTEMP 1 #cmakedefine HAVE_STRERROR 1 #cmakedefine HAVE_FLOAT_H 1 #cmakedefine HAVE_DIRENT_H 1 #cmakedefine HAVE_DLFCN_H 1 #cmakedefine HAVE_FCNTL_H 1 #cmakedefine HAVE_FORK 1 #cmakedefine HAVE_GETPWNAM 1 #cmakedefine HAVE_INT16_T 1 #cmakedefine HAVE_INT32_T 1 #cmakedefine HAVE_INTTYPES_H 1 #cmakedefine HAVE_MEMORY_H 1 #cmakedefine HAVE_MKSTEMP 1 #cmakedefine HAVE_NDIR_H 1 #cmakedefine HAVE_POPEN 1 #cmakedefine HAVE_PWD_H 1 #cmakedefine HAVE_SELECT 1 #cmakedefine HAVE_STDINT_H 1 #cmakedefine HAVE_STDLIB_H 1 #cmakedefine HAVE_STRDUP 1 #cmakedefine HAVE_SYSCONF 1 #cmakedefine HAVE_SYSTEM 1 #cmakedefine HAVE_SYS_DIR_H 1 #cmakedefine HAVE_SYS_NDIR_H 1 #cmakedefine HAVE_SYS_STAT_H 1 #cmakedefine HAVE_SYS_TIME_H 1 #cmakedefine HAVE_SYS_TYPES_H 1 #cmakedefine HAVE_SYS_WAIT_H 1 #cmakedefine HAVE_TEMPNAM 1 #cmakedefine HAVE_TMPNAM 1 #cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_VALUES_H 1 #cmakedefine HAVE_VFORK 1 #cmakedefine HAVE_VFORK_H 1 #cmakedefine HAVE_WORKING_FORK 1 #cmakedefine HAVE_WORKING_VFORK 1 #cmakedefine HAVE_ZLIB 1 #cmakedefine HAVE_STRINGS_H 1 #cmakedefine HAVE_STRING_H 1 #define H5Acreate_vers 2 minc-2.2.00/UseMINC2.cmake.in0000644000265600003100000000064712030075003012330 00000000000000INCLUDE_DIRECTORIES(${MINC2_INCLUDE_DIRS}) LINK_DIRECTORIES(${MINC2_LIBRARY_DIRS}) INCLUDE_DIRECTORIES(${NETCDF_INCLUDE_DIR} ) IF(HAVE_MINC2) SET(MINC2 "1") ADD_DEFINITIONS( -DMINC2=1 ) INCLUDE_DIRECTORIES(${MINC2_INCLUDE_DIRS}) LINK_DIRECTORIES(${MINC2_LIBRARY_DIRS}) INCLUDE_DIRECTORIES( ${HDF5_INCLUDE_DIR} ) ENDIF(HAVE_MINC2) IF(USE_ITK_HDF5) LINK_DIRECTORIES(${ITK_LIBRARY_DIRS}) ENDIF(USE_ITK_HDF5) minc-2.2.00/MINC2Config.cmake.in0000644000265600003100000000117212030075003012773 00000000000000set(HAVE_MINC2 @MINC2_BUILD_V2@) set(HAVE_EZMINC @MINC2_BUILD_EZMINC@) set(USE_ITK_HDF5 @USE_ITK_HDF5@) set(NETCDF_INCLUDE_DIR "@NETCDF_INCLUDE_DIR@") set(HDF5_INCLUDE_DIR "@HDF5_INCLUDE_DIR@") set(NETCDF_LIBRARY "@NETCDF_LIBRARY@") set(HDF5_LIBRARY "@HDF5_LIBRARY@") set(ZLIB_LIBRARIES "@ZLIB_LIBRARIES@") set(MINC2_INCLUDE_DIRS "@MINC2_INCLUDE_DIRS_CONFIG@") set(MINC2_LIBRARY_DIRS "@MINC2_LIBRARY_DIRS_CONFIG@") set(MINC2_USE_FILE "@MINC2_USE_FILE_CONFIG@") set(MINC2_LIBRARIES "@MINC2_LIBRARIES_CONFIG@") set(EZMINC_LIBRARIES "@EZMINC_LIBRARIES@") set(VOLUME_IO_LIBRARIES "@VOLUME_IO_LIBRARY@") minc-2.2.00/testdir/0000755000265600003100000000000012030114724011167 500000000000000minc-2.2.00/testdir/Makefile.am0000644000265600003100000000250412027132663013154 00000000000000INCLUDES = -I$(top_srcdir)/libsrc \ -I$(top_srcdir)/volume_io/Include \ -I$(top_builddir)/volume_io/Include script_tests = \ run_test_arg_parse.sh \ run_tests.sh \ run_test2.sh \ xfmconcat_01.sh \ xfmconcat_02.sh \ run_test_progs.sh all-local: cd $(srcdir) && chmod +x $(script_tests) LDADD = ../libvolume_io2.la ../libminc2.la TESTS = run_test_arg_parse.sh \ run_tests.sh \ run_test2.sh \ xfmconcat_01.sh \ xfmconcat_02.sh \ mincapi \ run_test_progs.sh check_PROGRAMS = minc test_mconv minc_types icv icv_range \ icv_dim test_speed icv_dim1 icv_fillvalue \ test_xfm create_grid_xfm mincapi test_speed test_arg_parse EXTRA_DIST = $(script_tests) $(expect_files) t1.xfm icv.mnc CLEANFILES = test.mnc _* # The test script "run_tests.sh" uses a series of "expected output" # files, comparing each with the output generated by the file under # test. We need to distribute these files (so they are in # EXTRA_DIST). # expect_files = icv.out icv_dim.out icv_dim1.out icv_fillvalue.out \ icv_range.out minc_types.out # Unfortunately, GNU make has implicit rules for files with the suffix # ".out". The following lines disable implicit rules. In future, we # should probably use a different naming scheme for these files ... # icv.out: ; icv_dim.out: ; icv_dim1.out: ; icv_fillvalue.out: ; icv_range.out: ; minc_types.out: ; minc-2.2.00/testdir/Makefile.in0000644000265600003100000005414012030077514013165 00000000000000# Makefile.in generated by automake 1.10.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ TESTS = run_test_arg_parse.sh run_tests.sh run_test2.sh \ xfmconcat_01.sh xfmconcat_02.sh mincapi$(EXEEXT) \ run_test_progs.sh check_PROGRAMS = minc$(EXEEXT) test_mconv$(EXEEXT) minc_types$(EXEEXT) \ icv$(EXEEXT) icv_range$(EXEEXT) icv_dim$(EXEEXT) \ test_speed$(EXEEXT) icv_dim1$(EXEEXT) icv_fillvalue$(EXEEXT) \ test_xfm$(EXEEXT) create_grid_xfm$(EXEEXT) mincapi$(EXEEXT) \ test_speed$(EXEEXT) test_arg_parse$(EXEEXT) subdir = testdir DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mni_REQUIRE_LIB.m4 \ $(top_srcdir)/m4/smr_WITH_BUILD_PATH.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = create_grid_xfm_SOURCES = create_grid_xfm.c create_grid_xfm_OBJECTS = create_grid_xfm.$(OBJEXT) create_grid_xfm_LDADD = $(LDADD) create_grid_xfm_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la icv_SOURCES = icv.c icv_OBJECTS = icv.$(OBJEXT) icv_LDADD = $(LDADD) icv_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la icv_dim_SOURCES = icv_dim.c icv_dim_OBJECTS = icv_dim.$(OBJEXT) icv_dim_LDADD = $(LDADD) icv_dim_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la icv_dim1_SOURCES = icv_dim1.c icv_dim1_OBJECTS = icv_dim1.$(OBJEXT) icv_dim1_LDADD = $(LDADD) icv_dim1_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la icv_fillvalue_SOURCES = icv_fillvalue.c icv_fillvalue_OBJECTS = icv_fillvalue.$(OBJEXT) icv_fillvalue_LDADD = $(LDADD) icv_fillvalue_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la icv_range_SOURCES = icv_range.c icv_range_OBJECTS = icv_range.$(OBJEXT) icv_range_LDADD = $(LDADD) icv_range_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la minc_SOURCES = minc.c minc_OBJECTS = minc.$(OBJEXT) minc_LDADD = $(LDADD) minc_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la minc_types_SOURCES = minc_types.c minc_types_OBJECTS = minc_types.$(OBJEXT) minc_types_LDADD = $(LDADD) minc_types_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la mincapi_SOURCES = mincapi.c mincapi_OBJECTS = mincapi.$(OBJEXT) mincapi_LDADD = $(LDADD) mincapi_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la test_arg_parse_SOURCES = test_arg_parse.c test_arg_parse_OBJECTS = test_arg_parse.$(OBJEXT) test_arg_parse_LDADD = $(LDADD) test_arg_parse_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la test_mconv_SOURCES = test_mconv.c test_mconv_OBJECTS = test_mconv.$(OBJEXT) test_mconv_LDADD = $(LDADD) test_mconv_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la test_speed_SOURCES = test_speed.c test_speed_OBJECTS = test_speed.$(OBJEXT) test_speed_LDADD = $(LDADD) test_speed_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la test_xfm_SOURCES = test_xfm.c test_xfm_OBJECTS = test_xfm.$(OBJEXT) test_xfm_LDADD = $(LDADD) test_xfm_DEPENDENCIES = ../libvolume_io2.la ../libminc2.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/ac_config_aux/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = create_grid_xfm.c icv.c icv_dim.c icv_dim1.c icv_fillvalue.c \ icv_range.c minc.c minc_types.c mincapi.c test_arg_parse.c \ test_mconv.c test_speed.c test_xfm.c DIST_SOURCES = create_grid_xfm.c icv.c icv_dim.c icv_dim1.c \ icv_fillvalue.c icv_range.c minc.c minc_types.c mincapi.c \ test_arg_parse.c test_mconv.c test_speed.c test_xfm.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POD2MAN = @POD2MAN@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_F77 = @ac_ct_F77@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir)/libsrc \ -I$(top_srcdir)/volume_io/Include \ -I$(top_builddir)/volume_io/Include script_tests = \ run_test_arg_parse.sh \ run_tests.sh \ run_test2.sh \ xfmconcat_01.sh \ xfmconcat_02.sh \ run_test_progs.sh LDADD = ../libvolume_io2.la ../libminc2.la EXTRA_DIST = $(script_tests) $(expect_files) t1.xfm icv.mnc CLEANFILES = test.mnc _* # The test script "run_tests.sh" uses a series of "expected output" # files, comparing each with the output generated by the file under # test. We need to distribute these files (so they are in # EXTRA_DIST). # expect_files = icv.out icv_dim.out icv_dim1.out icv_fillvalue.out \ icv_range.out minc_types.out all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testdir/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu testdir/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done create_grid_xfm$(EXEEXT): $(create_grid_xfm_OBJECTS) $(create_grid_xfm_DEPENDENCIES) @rm -f create_grid_xfm$(EXEEXT) $(LINK) $(create_grid_xfm_OBJECTS) $(create_grid_xfm_LDADD) $(LIBS) icv$(EXEEXT): $(icv_OBJECTS) $(icv_DEPENDENCIES) @rm -f icv$(EXEEXT) $(LINK) $(icv_OBJECTS) $(icv_LDADD) $(LIBS) icv_dim$(EXEEXT): $(icv_dim_OBJECTS) $(icv_dim_DEPENDENCIES) @rm -f icv_dim$(EXEEXT) $(LINK) $(icv_dim_OBJECTS) $(icv_dim_LDADD) $(LIBS) icv_dim1$(EXEEXT): $(icv_dim1_OBJECTS) $(icv_dim1_DEPENDENCIES) @rm -f icv_dim1$(EXEEXT) $(LINK) $(icv_dim1_OBJECTS) $(icv_dim1_LDADD) $(LIBS) icv_fillvalue$(EXEEXT): $(icv_fillvalue_OBJECTS) $(icv_fillvalue_DEPENDENCIES) @rm -f icv_fillvalue$(EXEEXT) $(LINK) $(icv_fillvalue_OBJECTS) $(icv_fillvalue_LDADD) $(LIBS) icv_range$(EXEEXT): $(icv_range_OBJECTS) $(icv_range_DEPENDENCIES) @rm -f icv_range$(EXEEXT) $(LINK) $(icv_range_OBJECTS) $(icv_range_LDADD) $(LIBS) minc$(EXEEXT): $(minc_OBJECTS) $(minc_DEPENDENCIES) @rm -f minc$(EXEEXT) $(LINK) $(minc_OBJECTS) $(minc_LDADD) $(LIBS) minc_types$(EXEEXT): $(minc_types_OBJECTS) $(minc_types_DEPENDENCIES) @rm -f minc_types$(EXEEXT) $(LINK) $(minc_types_OBJECTS) $(minc_types_LDADD) $(LIBS) mincapi$(EXEEXT): $(mincapi_OBJECTS) $(mincapi_DEPENDENCIES) @rm -f mincapi$(EXEEXT) $(LINK) $(mincapi_OBJECTS) $(mincapi_LDADD) $(LIBS) test_arg_parse$(EXEEXT): $(test_arg_parse_OBJECTS) $(test_arg_parse_DEPENDENCIES) @rm -f test_arg_parse$(EXEEXT) $(LINK) $(test_arg_parse_OBJECTS) $(test_arg_parse_LDADD) $(LIBS) test_mconv$(EXEEXT): $(test_mconv_OBJECTS) $(test_mconv_DEPENDENCIES) @rm -f test_mconv$(EXEEXT) $(LINK) $(test_mconv_OBJECTS) $(test_mconv_LDADD) $(LIBS) test_speed$(EXEEXT): $(test_speed_OBJECTS) $(test_speed_DEPENDENCIES) @rm -f test_speed$(EXEEXT) $(LINK) $(test_speed_OBJECTS) $(test_speed_LDADD) $(LIBS) test_xfm$(EXEEXT): $(test_xfm_OBJECTS) $(test_xfm_DEPENDENCIES) @rm -f test_xfm$(EXEEXT) $(LINK) $(test_xfm_OBJECTS) $(test_xfm_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/create_grid_xfm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icv_dim.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icv_dim1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icv_fillvalue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icv_range.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minc_types.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mincapi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arg_parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mconv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_speed.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_xfm.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am all-local check check-TESTS check-am \ clean clean-checkPROGRAMS clean-generic clean-libtool ctags \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am all-local: cd $(srcdir) && chmod +x $(script_tests) # Unfortunately, GNU make has implicit rules for files with the suffix # ".out". The following lines disable implicit rules. In future, we # should probably use a different naming scheme for these files ... # icv.out: ; icv_dim.out: ; icv_dim1.out: ; icv_fillvalue.out: ; icv_range.out: ; minc_types.out: ; # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: minc-2.2.00/testdir/create_grid_xfm.c0000644000265600003100000000200612027132663014403 00000000000000/* Create a grid transform from an existing MINC volume. */ #include #include #include "time_stamp.h" int main( int ac, char* av[] ) { Volume v; minc_input_options mio; General_transform t; Status st; if ( ac != 3 ) { fprintf( stderr, "usage: %s in_grid.mnc out.xfm\n", av[0] ); return 1; } /* The displacement volume must retain the vector dimension, * so we turn off "vector -> scalar" conversion. */ set_default_minc_input_options( &mio ); set_minc_input_vector_to_scalar_flag( &mio, 0 ); st = input_volume( av[1], 0, NULL, MI_ORIGINAL_TYPE, FALSE, 0.0, 0.0, TRUE, &v, &mio ); if ( st != OK ) { fprintf( stderr, "failed to read grid volume \"%s\"\n", av[1] ); return 1; } create_grid_transform( &t, v ); st = output_transform_file( av[2], time_stamp(ac,av), &t ); if ( st != OK ) { fprintf( stderr, "error writing to xfm file \"%s\"\n", av[2] ); return 1; } return 0; } minc-2.2.00/testdir/icv.c0000644000265600003100000000466512027132663012057 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #include #define TRUE 1 #define FALSE 0 int main(int argc, char **argv) { int icv, cdfid, img, max, min, dimvar; static int dim[MAX_VAR_DIMS]; static struct { long len; char *name;} diminfo[] = { { 3, MIzspace }, { 4, MIyspace }, { 5, MIxspace } }; static int numdims=sizeof(diminfo)/sizeof(diminfo[0]); static long coord[]={0,0,0}; static long count[]={3,4,5}; double dvalue; short int ivalue[]={ 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349 }; int i, j, k; int cflag = 0; #if MINC2 if (argc == 2 && !strcmp(argv[1], "-2")) { cflag = MI2_CREATE_V2; } #endif /* MINC2 */ icv=miicv_create(); miicv_setint(icv, MI_ICV_DO_NORM, TRUE); cdfid=micreate("test.mnc", NC_CLOBBER | cflag); for (i=0; i #include #define TRUE 1 #define FALSE 0 main(int argc, char **argv) { int icv, cdfid, img, max, min, dimvar; static int dim[MAX_VAR_DIMS]; static struct { long len; char *name;} diminfo[] = { { 3, MIzspace }, { 9, MIyspace }, { 2, MIxspace } }; /* static struct { long len; char *name;} diminfo[]= {3, MIzspace, 4, MIyspace, 5, MIxspace}; */ static int numdims=sizeof(diminfo)/sizeof(diminfo[0]); static long coord[]={0,0,0}; static long count[]={3,4,5}; double dvalue; short int ivalue[]={ 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349 }; int i, j, k; int cflag = 0; #if MINC2 if (argc == 2 && !strcmp(argv[1], "-2")) { cflag = MI2_CREATE_V2; } #endif /* MINC2 */ icv=miicv_create(); miicv_setint(icv, MI_ICV_XDIM_DIR, MI_ICV_NEGATIVE); miicv_setint(icv, MI_ICV_YDIM_DIR, MI_ICV_NEGATIVE); miicv_setint(icv, MI_ICV_ZDIM_DIR, MI_ICV_NEGATIVE); miicv_setint(icv, MI_ICV_ADIM_SIZE, 5); miicv_setint(icv, MI_ICV_BDIM_SIZE, 4); miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE); miicv_setint(icv, MI_ICV_KEEP_ASPECT, FALSE); miicv_setint(icv, MI_ICV_DO_NORM, TRUE); cdfid=micreate("test.mnc", NC_CLOBBER | cflag); for (i=0; i #include #define TRUE 1 #define FALSE 0 int main(int argc, char **argv) { int icv, cdfid, img, max, min, dimvar; static int dim[MAX_VAR_DIMS]; static struct { long len; char *name;} diminfo[] = { { 7, MIzspace }, { 9, MIyspace }, { 2, MIxspace } }; /* static struct { long len; char *name;} diminfo[]= {3, MIzspace, 4, MIyspace, 5, MIxspace}; */ static int numdims=sizeof(diminfo)/sizeof(diminfo[0]); static long coord[]={0,0,0}; static long count[]={3,4,5}; double dvalue; short int ivalue[]={ 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349 }; int i, j, k; int cflag = 0; #if MINC2 if (argc == 2 && !strcmp(argv[1], "-2")) { cflag = MI2_CREATE_V2; } #endif /* MINC2 */ icv=miicv_create(); miicv_setint(icv, MI_ICV_XDIM_DIR, MI_ICV_NEGATIVE); miicv_setint(icv, MI_ICV_YDIM_DIR, MI_ICV_NEGATIVE); miicv_setint(icv, MI_ICV_ZDIM_DIR, MI_ICV_NEGATIVE); miicv_setint(icv, MI_ICV_NUM_IMGDIMS, 3); miicv_setint(icv, MI_ICV_DIM_SIZE+0, 5); miicv_setint(icv, MI_ICV_DIM_SIZE+1, 4); miicv_setint(icv, MI_ICV_DIM_SIZE+2, 3); miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE); miicv_setint(icv, MI_ICV_KEEP_ASPECT, FALSE); miicv_setint(icv, MI_ICV_DO_NORM, TRUE); cdfid=micreate("test.mnc", NC_CLOBBER | cflag); for (i=0; i #include #include #include #include #define TRUE 1 #define FALSE 0 int main(int argc, char **argv) { int icv, mincid, img, i; static int dim[MAX_VAR_DIMS]; static struct { long len; char *name;} diminfo[] = { { 4, MIyspace }, { 5, MIxspace} }; static int numdims=sizeof(diminfo)/sizeof(diminfo[0]); static long coord[]={0,0}; static long count[]={4,5}; static short int ivalue[]={ 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, -5 }; static int ivallen = sizeof(ivalue)/sizeof(ivalue[0]); int cflag = 0; #if MINC2 if (argc == 2 && !strcmp(argv[1], "-2")) { cflag = MI2_CREATE_V2; } #endif /* MINC2 */ icv = miicv_create(); (void) miicv_setint(icv, MI_ICV_VALID_MAX, 200); (void) miicv_setint(icv, MI_ICV_VALID_MIN, 0); (void) miicv_setint(icv, MI_ICV_DO_FILLVALUE, TRUE); mincid=micreate("test.mnc", NC_CLOBBER | cflag); for (i=0; i<2; i++) { dim[i]=ncdimdef(mincid, diminfo[i].name, diminfo[i].len); } img=micreate_std_variable(mincid, MIimage, NC_SHORT, numdims, dim); (void) miattputint(mincid, img, MIvalid_max, 200); (void) miattputint(mincid, img, MIvalid_min, 0); (void) ncendef(mincid); (void) miicv_attach(icv, mincid, img); (void) miicv_put(icv, coord, count, ivalue); for (i=0; i #include #define TRUE 1 #define FALSE 0 #define MAX_IN_TYPES 2 #define MAX_NORM 2 #define MAX_OUT_TYPES 2 #define MAX_MAX 2 #define MAX_VAL 2 int main(int argc, char **argv) { int icv, cdfid, img, max, min; static char *typenm[]={"short", "double"}; static char *boolnm[] = {"true", "false"}; static nc_type intypes[] = {NC_SHORT, NC_DOUBLE}; static int norms[] = {TRUE, FALSE}; static nc_type outtypes[] = {NC_SHORT, NC_DOUBLE}; static int maxpresent[] = {TRUE, FALSE}; static int valpresent[] = {TRUE, FALSE}; static int dim[MAX_VAR_DIMS]; static struct { long len; char *name;} diminfo[] = { { 3, MIzspace }, { 1, MIyspace }, { 1, MIxspace } }; static int numdims=sizeof(diminfo)/sizeof(diminfo[0]); static long coord[]={0,0,0}; static long count[]={1,1,1}; static double max_values[] = {0.4, 0.6, 0.8}; double dvalue; short int ivalue; int i, intype, inorm, outtype, imax, ival; int cflag = 0; #if MINC2 if (argc == 2 && !strcmp(argv[1], "-2")) { cflag = MI2_CREATE_V2; } #endif /* MINC2 */ for (intype=0; intype #include #include int main() { int cdf, cdf2; int img; int dim[MAX_VAR_DIMS]; int dim2[MAX_VAR_DIMS]; long start[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS]; double image[256*256]; int i, j, k, ioff; ncopts=NC_VERBOSE|NC_FATAL; cdf=micreate("test.mnc",NC_CLOBBER); count[2]=5; count[1]=3; count[0]=7; dim[2]=ncdimdef(cdf, MIzspace, count[2]); dim[1]=ncdimdef(cdf, MIxspace, count[1]); dim[0]=ncdimdef(cdf, MIyspace, count[0]); dim2[0]=ncdimdef(cdf, MItime, NC_UNLIMITED); dim2[1]=dim[0]; dim2[2]=dim[1]; img=ncvardef(cdf, MIimage, NC_SHORT, 3, dim); (void) ncvardef(cdf, "testvar", NC_FLOAT, 2, dim2); (void) miattputstr(cdf, img, MIsigntype, MI_SIGNED); for (j=0; j #include #include #include #include struct { nc_type type; char *sign; char *ctype; } types[]= { { NC_BYTE, MI_UNSIGNED, "byte" }, { NC_BYTE, MI_SIGNED, "byte" }, { NC_SHORT, MI_UNSIGNED, "short" }, { NC_SHORT, MI_SIGNED, "short" }, { NC_INT, MI_UNSIGNED, "int" }, { NC_INT, MI_SIGNED, "int" }, { NC_FLOAT, MI_SIGNED, "float" }, { NC_DOUBLE, MI_SIGNED, "double" } }; int ntypes = sizeof(types)/sizeof(types[0]); int main(int argc, char **argv) { int cdf; int img, img2; int dim[MAX_VAR_DIMS]; long start[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS]; double image[256*256]; int i, itype, jtype; int cflag = 0; #if MINC2 if (argc == 2 && !strcmp(argv[1], "-2")) { cflag = MI2_CREATE_V2; } #endif /* MINC2 */ ncopts=NC_VERBOSE|NC_FATAL; for (itype=0; itype #include #include #include #include #if HAVE_UNISTD_H #include #endif #define FUNC_ERROR(x) (fprintf(stderr, "On line %d, function %s failed unexpectedly\n", __LINE__, x), ++errors) #define TST_X 0 #define TST_Y 1 #define TST_Z 2 long errors = 0; extern void icv_tests(void); #define XSIZE 20 #define YSIZE 30 #define ZSIZE 40 #define YBOOST 10 #define ZBOOST 20 static struct dimdef { char * name; int length; } dimtab1[3] = { { MIxspace, XSIZE }, { MIyspace, YSIZE }, { MIzspace, ZSIZE } }; struct testinfo { char *name; int fd; int maxid; int minid; int imgid; int dim[3]; }; /* Test case 1 - file creation & definition. */ int test1(struct testinfo *ip, struct dimdef *dims, int ndims) { int fd2; int varid; int stat; int i; /* Test case #1 - file creation */ ip->name = micreate_tempfile(); if (ip->name == NULL) { FUNC_ERROR("micreate_tempfile\n"); } ip->fd = micreate(ip->name, NC_CLOBBER); if (ip->fd < 0) { FUNC_ERROR("micreate"); } /* Try to create another file of the same name - should fail. */ fd2 = micreate(ip->name, NC_NOCLOBBER); if (fd2 >= 0) { FUNC_ERROR("micreate"); } /* Try to open the file for write - should fail. */ /* VF: it doesn't fail! fd2 = miopen(ip->name, NC_WRITE); if (fd2 >= 0) { FUNC_ERROR("miopen"); } */ /* Have to use ncdimdef() here since there is no MINC equivalent. Sigh. */ for (i = 0; i < ndims; i++) { /* Define the dimension */ ip->dim[i] = ncdimdef(ip->fd, dims[i].name, dims[i].length); if (ip->dim[i] < 0) { FUNC_ERROR("ncdimdef"); } /* Create the dimension variable. */ varid = micreate_std_variable(ip->fd, dims[i].name, NC_DOUBLE, 0, &ip->dim[i]); if (varid < 0) { FUNC_ERROR("micreate_std_variable"); } stat = miattputdbl(ip->fd, varid, MIstep, 0.8); if (stat < 0) { FUNC_ERROR("miattputdbl"); } stat = miattputdbl(ip->fd, varid, MIstart, 22.0); if (stat < 0) { FUNC_ERROR("miattputdbl"); } } /* Try to create a bogus variable. This should trigger an error. */ varid = micreate_std_variable(ip->fd, "xyzzy", NC_DOUBLE, 0, NULL); if (varid >= 0) { FUNC_ERROR("micreate_std_variable"); } /* Create the image-max variable. */ ip->maxid = micreate_std_variable(ip->fd, MIimagemax, NC_FLOAT, 0, NULL); if (ip->maxid < 0) { FUNC_ERROR("micreate_std_variable"); } /* Create the image-min variable. */ ip->minid = micreate_std_variable(ip->fd, MIimagemin, NC_FLOAT, 0, NULL); if (ip->minid < 0) { FUNC_ERROR("micreate_std_variable"); } ip->imgid = micreate_std_variable(ip->fd, MIimage, NC_INT, ndims, ip->dim); if (ip->imgid < 0) { FUNC_ERROR("micreate_std_variable"); } return (0); } int test2(struct testinfo *ip, struct dimdef *dims, int ndims) { int i, j, k; int stat; long coords[3]; float flt; stat = miattputdbl(ip->fd, ip->imgid, MIvalid_max, (XSIZE * 10000.0)); if (stat < 0) { FUNC_ERROR("miattputdbl"); } stat = miattputdbl(ip->fd, ip->imgid, MIvalid_min, -(XSIZE * 10000.0)); if (stat < 0) { FUNC_ERROR("miattputdbl"); } ncendef(ip->fd); /* End definition mode. */ coords[0] = 0; flt = -(XSIZE * 100000.0); stat = mivarput1(ip->fd, ip->minid, coords, NC_FLOAT, MI_SIGNED, &flt); if (stat < 0) { FUNC_ERROR("mivarput1"); } flt = XSIZE * 100000.0; stat = mivarput1(ip->fd, ip->maxid, coords, NC_FLOAT, MI_SIGNED, &flt); if (stat < 0) { FUNC_ERROR("mivarput1"); } for (i = 0; i < dims[TST_X].length; i++) { for (j = 0; j < dims[TST_Y].length; j++) { for (k = 0; k < dims[TST_Z].length; k++) { int tmp = (i * 10000) + (j * 100) + k; coords[TST_X] = i; coords[TST_Y] = j; coords[TST_Z] = k; stat = mivarput1(ip->fd, ip->imgid, coords, NC_INT, MI_SIGNED, &tmp); if (stat < 0) { fprintf(stderr, "At (%d,%d,%d), status %d: ", i,j,k,stat); FUNC_ERROR("mivarput1"); } } } } return (0); } int test3(struct testinfo *ip, struct dimdef *dims, int ndims) { /* Try to read the data back. */ size_t total; long coords[3]; long lengths[3]; void *buf_ptr; int *int_ptr; int i, j, k; int stat; total = 1; for (i = 0; i < ndims; i++) { total *= dims[i].length; } buf_ptr = malloc(total * sizeof (int)); if (buf_ptr == NULL) { fprintf(stderr, "Oops, malloc failed\n"); return (-1); } coords[TST_X] = 0; coords[TST_Y] = 0; coords[TST_Z] = 0; lengths[TST_X] = dims[TST_X].length; lengths[TST_Y] = dims[TST_Y].length; lengths[TST_Z] = dims[TST_Z].length; stat = mivarget(ip->fd, ip->imgid, coords, lengths, NC_INT, MI_SIGNED, buf_ptr); if (stat < 0) { FUNC_ERROR("mivarget"); } int_ptr = (int *) buf_ptr; for (i = 0; i < dims[TST_X].length; i++) { for (j = 0; j < dims[TST_Y].length; j++) { for (k = 0; k < dims[TST_Z].length; k++) { int tmp = (i * 10000) + (j * 100) + k; if (*int_ptr != tmp) { fprintf(stderr, "1. Data error at (%d,%d,%d)\n", i,j,k); errors++; } int_ptr++; } } } free(buf_ptr); return (0); } int test4(struct testinfo *ip, struct dimdef *dims, int ndims) { /* Get the same variable again, but this time use an ICV to scale it. */ size_t total; long coords[3]; long lengths[3]; double range[2]; void *buf_ptr; float *flt_ptr; int i, j, k; int stat; int icv; double dbl; total = 1; for (i = 0; i < ndims; i++) { total *= dims[i].length; } buf_ptr = malloc(total * sizeof (float)); if (buf_ptr == NULL) { fprintf(stderr, "Oops, malloc failed\n"); return (-1); } coords[TST_X] = 0; coords[TST_Y] = 0; coords[TST_Z] = 0; lengths[TST_X] = dims[TST_X].length; lengths[TST_Y] = dims[TST_Y].length; lengths[TST_Z] = dims[TST_Z].length; icv = miicv_create(); if (icv < 0) { FUNC_ERROR("miicv_create"); } stat = miicv_setint(icv, MI_ICV_TYPE, NC_FLOAT); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_DO_NORM, 1); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_attach(icv, ip->fd, ip->imgid); if (stat < 0) { FUNC_ERROR("miicv_attach"); } /* This next call _should_ fail, since the ICV has been attached. */ stat = miicv_setint(icv, MI_ICV_DO_NORM, 0); if (stat >= 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_inqdbl(icv, MI_ICV_DO_NORM, &dbl); if (stat < 0) { FUNC_ERROR("miicv_inqdbl"); } if (dbl != 1.0) { fprintf(stderr, "miicv_inqdbl: Bad value returned\n"); errors++; } stat = miicv_get(icv, coords, lengths, buf_ptr); if (stat < 0) { FUNC_ERROR("miicv_get"); } stat = miget_image_range(ip->fd, range); if (stat < 0) { FUNC_ERROR("miget_image_range"); } if (range[0] != -(XSIZE * 100000.0) || range[1] != (XSIZE * 100000.00)) { fprintf(stderr, "miget_image_range: bad result\n"); errors++; } stat = miget_valid_range(ip->fd, ip->imgid, range); if (stat < 0) { FUNC_ERROR("miget_valid_range"); } if (range[0] != -(XSIZE * 10000.0) || range[1] != (XSIZE * 10000.0)) { fprintf(stderr, "miget_valid_range: bad result\n"); errors++; } flt_ptr = (float *) buf_ptr; for (i = 0; i < dims[TST_X].length; i++) { for (j = 0; j < dims[TST_Y].length; j++) { for (k = 0; k < dims[TST_Z].length; k++) { float tmp = (i * 10000) + (j * 100) + k; if (*flt_ptr != (float) tmp * 10.0) { fprintf(stderr, "2. Data error at (%d,%d,%d) %f != %f\n", i,j,k, *flt_ptr, tmp); errors++; } flt_ptr++; } } } stat = miicv_detach(icv); if (stat < 0) { FUNC_ERROR("miicv_detach"); } /* Try it again, to make certain we fail gracefully. */ stat = miicv_detach(icv); if (stat < 0) { FUNC_ERROR("miicv_detach"); } /* Try to detach a completely random number. */ stat = miicv_detach(rand()); if (stat >= 0) { FUNC_ERROR("miicv_detach"); } stat = miicv_free(icv); if (stat < 0) { FUNC_ERROR("miicv_free"); } free(buf_ptr); return (0); } int test5(struct testinfo *ip, struct dimdef *dims, int ndims) { /* Get the same variable again, but this time use an ICV to scale it. */ size_t total; long coords[3]; long lengths[3]; void *buf_ptr; int *int_ptr; int i, j, k; int stat; int icv; total = 1; total *= dims[TST_X].length; total *= dims[TST_Y].length + YBOOST; total *= dims[TST_Z].length + ZBOOST; buf_ptr = malloc(total * sizeof (int)); if (buf_ptr == NULL) { fprintf(stderr, "Oops, malloc failed\n"); return (-1); } icv = miicv_create(); if (icv < 0) { FUNC_ERROR("miicv_create"); } /* Now set up a dimension conversion. */ stat = miicv_setint(icv, MI_ICV_DO_NORM, 0); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_DO_RANGE, 0); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_TYPE, NC_INT); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_YDIM_DIR, MI_ICV_NEGATIVE); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_ZDIM_DIR, MI_ICV_NEGATIVE); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_BDIM_SIZE, dims[TST_Y].length + YBOOST); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_ADIM_SIZE, dims[TST_Z].length + ZBOOST); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_DO_DIM_CONV, 1); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_attach(icv, ip->fd, ip->imgid); if (stat < 0) { FUNC_ERROR("miicv_attach"); } coords[TST_X] = 0; coords[TST_Y] = 0; coords[TST_Z] = 0; lengths[TST_X] = dims[TST_X].length; lengths[TST_Y] = dims[TST_Y].length + YBOOST; lengths[TST_Z] = dims[TST_Z].length + ZBOOST; stat = miicv_get(icv, coords, lengths, buf_ptr); if (stat < 0) { FUNC_ERROR("miicv_get"); } int_ptr = (int *) buf_ptr; for (i = 0; i < dims[TST_X].length; i++) { for (j = 0; j < dims[TST_Y].length + YBOOST; j++) { for (k = 0; k < dims[TST_Z].length + ZBOOST; k++, int_ptr++) { int x; int y; int z; int tmp; if (j < YBOOST/2 || j >= dims[TST_Y].length + YBOOST/2) continue; if (k < ZBOOST/2 || k >= dims[TST_Z].length + ZBOOST/2) continue; x = i; y = (YSIZE + YBOOST - 1) - j; z = (ZSIZE + ZBOOST - 1) - k; y -= YBOOST / 2; z -= ZBOOST / 2; tmp = (x * 10000) + (y * 100) + (z); if (*int_ptr != (int) tmp) { fprintf(stderr, "3. Data error at (%d,%d,%d) %d != %d\n", i,j,k, *int_ptr, tmp); errors++; } } } } stat = miicv_detach(icv); if (stat < 0) { FUNC_ERROR("miicv_detach"); } stat = miicv_free(icv); if (stat < 0) { FUNC_ERROR("miicv_free"); } free(buf_ptr); return (0); } int test6(struct testinfo *ip, struct dimdef *dims, int ndims) { size_t total; long coords[3]; long lengths[3]; void *buf_ptr; int *int_ptr; int i, j, k; int stat; int icv; total = 1; total *= dims[TST_X].length; total *= dims[TST_Y].length - YBOOST; total *= dims[TST_Z].length - ZBOOST; buf_ptr = malloc(total * sizeof (int)); if (buf_ptr == NULL) { fprintf(stderr, "Oops, malloc failed\n"); return (-1); } icv = miicv_create(); if (icv < 0) { FUNC_ERROR("miicv_create"); } /* Now try reading the image with reduced size. */ stat = miicv_setint(icv, MI_ICV_BDIM_SIZE, dims[TST_Y].length - YBOOST); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_ADIM_SIZE, dims[TST_Z].length - ZBOOST); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_DO_DIM_CONV, 1); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_attach(icv, ip->fd, ip->imgid); if (stat < 0) { FUNC_ERROR("miicv_attach"); } coords[TST_X] = 0; coords[TST_Y] = 0; coords[TST_Z] = 0; lengths[TST_X] = dims[TST_X].length; lengths[TST_Y] = dims[TST_Y].length - YBOOST; lengths[TST_Z] = dims[TST_Z].length - ZBOOST; stat = miicv_get(icv, coords, lengths, buf_ptr); if (stat < 0) { FUNC_ERROR("miicv_get"); } int_ptr = (int *) buf_ptr; for (i = 0; i < dims[TST_X].length; i++) { for (j = 0; j < dims[TST_Y].length - YBOOST; j++) { for (k = 0; k < dims[TST_Z].length - ZBOOST; k++, int_ptr++) { int tmp; tmp = (i * 10000) + (j * 100) + (k); if (*int_ptr != (int) tmp) { fprintf(stderr, "4. Data error at (%d,%d,%d) %d != %d\n", i,j,k, *int_ptr, tmp); errors++; } } } } stat = miicv_detach(icv); if (stat < 0) { FUNC_ERROR("miicv_detach"); } stat = miicv_free(icv); if (stat < 0) { FUNC_ERROR("miicv_free"); } free(buf_ptr); return (0); } int test7(struct testinfo *ip, struct dimdef *dims, int ndims) { size_t total; long coords[3]; long lengths[3]; void *buf_ptr; int *int_ptr; int i, j, k; int stat; int icv; total = 1; for (i = 0; i < ndims; i++) { total *= dims[i].length; } buf_ptr = malloc(total * sizeof (float)); if (buf_ptr == NULL) { fprintf(stderr, "Oops, malloc failed\n"); return (-1); } icv = miicv_create(); if (icv < 0) { FUNC_ERROR("miicv_create"); } /* Test range conversion. */ stat = miicv_setint(icv, MI_ICV_DO_DIM_CONV, 0); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_DO_RANGE, 1); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED); if (stat < 0) { FUNC_ERROR("miicv_setstr"); } stat = miicv_setint(icv, MI_ICV_TYPE, NC_INT); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_VALID_MAX, 1000); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_VALID_MIN, -1000); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_attach(icv, ip->fd, ip->imgid); if (stat < 0) { FUNC_ERROR("miicv_attach"); } coords[TST_X] = 0; coords[TST_Y] = 0; coords[TST_Z] = 0; lengths[TST_X] = dims[TST_X].length; lengths[TST_Y] = dims[TST_Y].length; lengths[TST_Z] = dims[TST_Z].length; stat = miicv_get(icv, coords, lengths, buf_ptr); if (stat < 0) { FUNC_ERROR("miicv_get"); } int_ptr = (int *) buf_ptr; for (i = 0; i < dims[TST_X].length; i++) { for (j = 0; j < dims[TST_Y].length; j++) { for (k = 0; k < dims[TST_Z].length; k++, int_ptr++) { int tmp = (i * 10000) + (j * 100) + (k); int rng = (XSIZE * 10000) / 1000; /* Round tmp properly. */ tmp = (tmp + (rng / 2)) / rng; if (*int_ptr != tmp) { fprintf(stderr, "5. Data error at (%d,%d,%d) %d != %d\n", i,j,k, *int_ptr, tmp); errors++; } } } } stat = miicv_detach(icv); if (stat < 0) { FUNC_ERROR("miicv_detach"); } /* Free the ICV */ stat = miicv_free(icv); if (stat < 0) { FUNC_ERROR("miicv_free"); } free(buf_ptr); return (0); } /* Test MINC API's */ int main(int argc, char **argv) { int stat; struct testinfo info; milog_init("mincapi"); /* Disable error messages completely. */ milog_set_verbosity(0); ncopts &= ~(NC_FATAL | NC_VERBOSE); test1(&info, dimtab1, 3); test2(&info, dimtab1, 3); test3(&info, dimtab1, 3); test4(&info, dimtab1, 3); test5(&info, dimtab1, 3); /* test6(&info, dimtab1, 3); */ test7(&info, dimtab1, 3); stat = miicv_free(rand()); if (stat >= 0) { FUNC_ERROR("miicv_free"); } if (miclose(info.fd) != MI_NOERROR) { FUNC_ERROR("miclose"); } if (miclose(info.fd) != MI_ERROR) { FUNC_ERROR("miclose"); } if (miclose(rand()) != MI_ERROR) { FUNC_ERROR("miclose"); } unlink(info.name); /* Delete the temporary file. */ free(info.name); /* Free the temporary filename */ icv_tests(); fprintf(stderr, "**** Tests completed with "); if (errors == 0) { fprintf(stderr, "no errors\n"); } else { fprintf(stderr, "%ld error%s\n", errors, (errors == 1) ? "" : "s"); } return (errors); } void icv_tests(void) { /* Some random ICV tests */ int icv; int stat; int i; double min, max; icv = miicv_create(); if (icv < 0) { FUNC_ERROR("miicv_create"); } for (i = NC_BYTE; i <= NC_DOUBLE; i++) { stat = miicv_setint(icv, MI_ICV_TYPE, i); if (stat < 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED); stat = miicv_inqdbl(icv, MI_ICV_VALID_MAX, &max); if (stat < 0) { FUNC_ERROR("miicv_inqdbl"); } stat = miicv_inqdbl(icv, MI_ICV_VALID_MIN, &min); if (stat < 0) { FUNC_ERROR("miicv_inqdbl"); } switch (i) { case NC_BYTE: if (min != 0 || max != UCHAR_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; case NC_SHORT: if (min != 0 || max != USHRT_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; case NC_INT: if (min != 0 || max != UINT_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; case NC_FLOAT: if (min != -FLT_MAX || max != FLT_MAX) { fprintf(stderr, "Type %d min %g max %g, header min %g max %g\n", i, min, max, FLT_MIN, FLT_MAX); errors++; } break; case NC_DOUBLE: if (min != -DBL_MAX || max != DBL_MAX) { fprintf(stderr, "Type %d min %g max %g, header min %g max %g\n", i, min, max, DBL_MIN, DBL_MAX); errors++; } break; } stat = miicv_setstr(icv, MI_ICV_SIGN, MI_SIGNED); if (stat < 0) { FUNC_ERROR("miicv_setstr"); } stat = miicv_inqdbl(icv, MI_ICV_VALID_MAX, &max); if (stat < 0) { FUNC_ERROR("miicv_inqdbl"); } stat = miicv_inqdbl(icv, MI_ICV_VALID_MIN, &min); if (stat < 0) { FUNC_ERROR("miicv_inqdbl"); } switch (i) { case NC_BYTE: if (min != SCHAR_MIN || max != SCHAR_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; case NC_SHORT: if (min != SHRT_MIN || max != SHRT_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; case NC_INT: if (min != INT_MIN || max != INT_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; case NC_FLOAT: if (min != -FLT_MAX || max != FLT_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; case NC_DOUBLE: if (min != -DBL_MAX || max != DBL_MAX) { fprintf(stderr, "Type %d min %g max %g\n", i, min, max); errors++; } break; } } #if 0 /* For some reason we're allowed to set MI_ICV_TYPE to an illegal value. */ stat = miicv_setint(icv, MI_ICV_TYPE, 1000); if (stat < 0) { FUNC_ERROR("miicv_setint"); } #endif stat = miicv_setint(icv, MI_ICV_NUM_IMGDIMS, MI_MAX_IMGDIMS + 1); if (stat >= 0) { FUNC_ERROR("miicv_setint"); } stat = miicv_setint(icv, MI_ICV_NUM_IMGDIMS, MI_MAX_IMGDIMS); if (stat < 0) { FUNC_ERROR("miicv_setint"); } miicv_free(icv); } minc-2.2.00/testdir/test_arg_parse.c0000644000265600003100000000157112027132663014271 00000000000000#include #include int const_a = 0; int const_b = 0; int int_a = 0; int int_b = 0; long long_a = 0; long long_b = 0; ArgvInfo argTable[] = { {"-const_a", ARGV_CONSTANT, (char *)1, (char *)&const_a, "const_a option"}, {"-const_b", ARGV_CONSTANT, (char *)1, (char *)&const_b, "const_b option"}, {"-int_a", ARGV_INT, (char *)1, (char *)&int_a, "int_a option"}, {"-int_b", ARGV_INT, (char *)1, (char *)&int_b, "int_b option"}, {"-long_a", ARGV_LONG, (char *)1, (char *)&long_a, "long_a option"}, {"-long_b", ARGV_LONG, (char *)1, (char *)&long_b, "long_b option"}, {NULL, ARGV_END, NULL, NULL, NULL} }; int main (int argc, char *argv[]) { ParseArgv(&argc, argv, argTable, 0); printf( "const_a:%d const_b:%d int_a:%d int_b:%d long_a:%ld long_b:%ld\n", const_a, const_b, int_a, int_b, long_a, long_b ); return(0); } minc-2.2.00/testdir/test_mconv.c0000644000265600003100000000164112027132663013446 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #ifndef NULL # define NULL ((void *) 0) #endif int main() { char *file = "test.mnc"; int cdfid; int dim[MAX_VAR_DIMS]; int imgid; cdfid=nccreate(file, NC_CLOBBER); dim[0]=ncdimdef(cdfid, MIzspace, 3L); dim[1]=ncdimdef(cdfid, MIyspace, 5L); dim[2]=ncdimdef(cdfid, MIxspace, 6L); imgid=micreate_std_variable(cdfid, MIimage, NC_SHORT, 3, dim); (void) micreate_std_variable(cdfid, MIimagemax, NC_DOUBLE, 1, dim); (void) micreate_std_variable(cdfid, MIimagemin, NC_DOUBLE, 1, dim); (void) micreate_std_variable(cdfid, MIzspace, NC_DOUBLE, 1, NULL); (void) micreate_std_variable(cdfid, MIzspace_width, NC_DOUBLE, 1, &dim[0]); (void) micreate_group_variable(cdfid, MIpatient); (void) micreate_group_variable(cdfid, MIstudy); (void) micreate_group_variable(cdfid, MIacquisition); (void) ncclose(cdfid); return 0; } minc-2.2.00/testdir/test_speed.c0000644000265600003100000001520612027132663013426 00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #define TRUE 1 #define FALSE 0 #define NORMAL_STATUS 0 #define ERROR_STATUS 1 char *nctypename(nc_type datatype) { switch (datatype) { case NC_BYTE: return "byte"; case NC_CHAR: return "char"; case NC_SHORT: return "short"; case NC_INT: return "int"; case NC_FLOAT: return "float"; case NC_DOUBLE: return "double"; } return "unknown"; } int test_icv_read(char *filename, int xsize, int ysize, double image_min, double image_max, nc_type datatype, char *signtype) { int icv, cdfid, img, ndims; static long coord[MAX_VAR_DIMS]; static long count[MAX_VAR_DIMS]; int dim[MAX_VAR_DIMS]; long dim_size; unsigned char *image; int i; double min, max; int n; min = DBL_MAX; max = -DBL_MAX; image = malloc(xsize * ysize * nctypelen(datatype)); if (image == NULL) { return (ERROR_STATUS); } /* Create the icv */ icv=miicv_create(); (void) miicv_setint(icv, MI_ICV_XDIM_DIR, MI_ICV_POSITIVE); (void) miicv_setint(icv, MI_ICV_YDIM_DIR, MI_ICV_POSITIVE); (void) miicv_setint(icv, MI_ICV_ZDIM_DIR, MI_ICV_POSITIVE); (void) miicv_setint(icv, MI_ICV_ADIM_SIZE, xsize); (void) miicv_setint(icv, MI_ICV_BDIM_SIZE, ysize); (void) miicv_setint(icv, MI_ICV_KEEP_ASPECT, FALSE); (void) miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE); (void) miicv_setint(icv, MI_ICV_TYPE, datatype); (void) miicv_setstr(icv, MI_ICV_SIGN, signtype); (void) miicv_setdbl(icv, MI_ICV_VALID_MAX, image_max); (void) miicv_setdbl(icv, MI_ICV_VALID_MIN, image_min); /* Open the file, attach the image variable */ cdfid=miopen(filename, NC_NOWRITE); /* Attach image variable */ img=ncvarid(cdfid, MIimage); (void) miicv_attach(icv, cdfid, img); /* Get the number of dimensions and modify count and coord */ (void) ncvarinq(cdfid, img, NULL, NULL, &ndims, dim, NULL); if (ndims!=3) { (void) fprintf(stderr, "File must have 3 dimensions\n"); return ERROR_STATUS; } (void) ncdiminq(cdfid, dim[0], NULL, &dim_size); count[0]=1; count[1]=ysize; count[2]=xsize; coord[1]=0; coord[2]=0; /* Get the data */ for (i=0; i max) { max = uc; } if (uc < min) { min = uc; } } } else { for (n = 0; n < xsize*ysize; n++) { signed char sc = *(((signed char *)image) + n); if (sc > max) { max = sc; } if (sc < min) { min = sc; } } } break; case NC_SHORT: if (!strcmp(signtype, MI_UNSIGNED)) { for (n = 0; n < xsize*ysize; n++) { unsigned short uc = *(((unsigned short *)image) + n); if (uc > max) { max = uc; } if (uc < min) { min = uc; } } } else { for (n = 0; n < xsize*ysize; n++) { signed short sc = *(((signed short *)image) + n); if (sc > max) { max = sc; } if (sc < min) { min = sc; } } } break; case NC_INT: if (!strcmp(signtype, MI_UNSIGNED)) { for (n = 0; n < xsize*ysize; n++) { unsigned int uc = *(((unsigned int *)image) + n); if (uc > max) { max = uc; } if (uc < min) { min = uc; } } } else { for (n = 0; n < xsize*ysize; n++) { signed int sc = *(((signed int *)image) + n); if (sc > max) { max = sc; } if (sc < min) { min = sc; } } } break; case NC_FLOAT: for (n = 0; n < xsize*ysize; n++) { float sc = *(((float *)image) + n); if (sc > max) { max = sc; } if (sc < min) { min = sc; } } break; case NC_DOUBLE: for (n = 0; n < xsize*ysize; n++) { double sc = *(((double *)image) + n); if (sc > max) { max = sc; } if (sc < min) { min = sc; } } break; } printf("%d %s %s %f %f\n", i, signtype, nctypename(datatype), min, max); } /* Close the file and free the icv */ (void) miclose(cdfid); (void) miicv_free(icv); free(image); return (NORMAL_STATUS); } main(int argc, char *argv[]) { int xsize, ysize; double image_max, image_min; char *pname, *filename; /* Parse the command line */ pname=argv[0]; if (argc!=6) { (void) fprintf(stderr, "Usage: %s \n", pname); return ERROR_STATUS; } filename=argv[1]; xsize=atoi(argv[2]); ysize=atoi(argv[3]); image_min=atof(argv[4]); image_max=atof(argv[5]); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_BYTE, MI_UNSIGNED); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_SHORT, MI_UNSIGNED); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_INT, MI_UNSIGNED); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_BYTE, MI_SIGNED); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_SHORT, MI_SIGNED); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_INT, MI_SIGNED); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_FLOAT, MI_SIGNED); test_icv_read(filename, xsize, ysize, image_min, image_max, NC_DOUBLE, MI_SIGNED); return NORMAL_STATUS; } minc-2.2.00/testdir/test_xfm.c0000644000265600003100000000350512027132663013117 00000000000000#define _GNU_SOURCE 1 #include #include #include Real tolerance = 1e-8; int is_equal_real( Real e, Real a ) { return fabs(e-a) < tolerance; } /* Args: expected, actual. */ void assert_equal_point( Real ex, Real ey, Real ez, Real ax, Real ay, Real az, const char* msg ) { if ( is_equal_real(ex,ax) && is_equal_real(ey,ay) && is_equal_real(ez,az) ) return; printf( "%s failure.\n" "Expected: %f %f %f\n" " Actual: %f %f %f\n", msg, ex,ey,ez, ax,ay,az ); exit(3); } int main( int ac, char* av[] ) { int N; General_transform xfm; if ( ac != 3 && ac != 4 ) { fprintf( stderr, "usage: %s N transform.xfm [tolerance]\n", av[0] ); return 1; } N = atoi( av[1] ); if ( input_transform_file( av[2], &xfm ) != OK ) { fprintf( stderr, "Failed to load transform '%s'\n", av[2] ); return 2; } if ( ac == 4 ) { tolerance = atof( av[3] ); printf( "Setting tolerance to %f.\n", tolerance ); } while (N-- > 0) { Real x = 500.0 * ( drand48() - 0.5 ); Real y = 500.0 * ( drand48() - 0.5 ); Real z = 500.0 * ( drand48() - 0.5 ); Real tx,ty,tz; Real a,b,c; general_transform_point( &xfm, x,y,z, &tx,&ty,&tz ); /* Check that general_inverse_transform_point() and invert_general_transform() behave sensibly. */ general_inverse_transform_point( &xfm, tx,ty,tz, &a,&b,&c ); assert_equal_point( x,y,z, a,b,c, "general_inverse_transform_point()" ); invert_general_transform( &xfm ); general_transform_point( &xfm, tx,ty,tz, &a,&b,&c ); assert_equal_point( x,y,z, a,b,c, "general_transform_point() / inverted xfm" ); general_inverse_transform_point( &xfm, x,y,z, &a,&b,&c ); assert_equal_point( tx,ty,tz, a,b,c, "general_inverse_transform_point() / inverted xfm" ); } return 0; } minc-2.2.00/testdir/run_test_arg_parse.sh0000755000265600003100000000357612027132663015357 00000000000000#! /bin/sh #set -e fail=no check() { #args expected out=`./test_arg_parse $1` leftovers=`echo $out | sed "/^$2\$/d"` test -z "$leftovers" && return echo "Args : $1" echo "Output : $out" echo "Expected: $2" fail=yes } check '' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:0 long_b:0' check '-const_a' 'const_a:1 const_b:0 int_a:0 int_b:0 long_a:0 long_b:0' check '-const_b' 'const_a:0 const_b:1 int_a:0 int_b:0 long_a:0 long_b:0' check '-const_a -const_b' 'const_a:1 const_b:1 int_a:0 int_b:0 long_a:0 long_b:0' check '-const_b -const_a' 'const_a:1 const_b:1 int_a:0 int_b:0 long_a:0 long_b:0' check '-int_a 33' 'const_a:0 const_b:0 int_a:33 int_b:0 long_a:0 long_b:0' check '-int_a -3' 'const_a:0 const_b:0 int_a:-3 int_b:0 long_a:0 long_b:0' check '-int_b 22' 'const_a:0 const_b:0 int_a:0 int_b:22 long_a:0 long_b:0' check '-int_b -2' 'const_a:0 const_b:0 int_a:0 int_b:-2 long_a:0 long_b:0' check '-int_a -1 -int_b 3' 'const_a:0 const_b:0 int_a:-1 int_b:3 long_a:0 long_b:0' check '-int_b -1 -int_a 3' 'const_a:0 const_b:0 int_a:3 int_b:-1 long_a:0 long_b:0' check '-long_a 12' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:12 long_b:0' check '-long_a -99' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:-99 long_b:0' check '-long_b -12' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:0 long_b:-12' check '-long_b 99' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:0 long_b:99' check '-long_a 3 -long_b -9' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:3 long_b:-9' check '-long_b 3 -long_a -9' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:-9 long_b:3' check '-long_a -99 -int_b 3 -const_b' 'const_a:0 const_b:1 int_a:0 int_b:3 long_a:-99 long_b:0' check '-nonsense' 'const_a:0 const_b:0 int_a:0 int_b:0 long_a:0 long_b:0' test $fail = yes && exit 1 exit 0 minc-2.2.00/testdir/run_tests.sh0000755000265600003100000000032112027132663013500 00000000000000#! /bin/sh set -e tests="minc_types icv_range icv icv_dim icv_dim1 icv_fillvalue" for test in $tests; do echo Testing $test ./$test > junk.out diff $srcdir/$test.out junk.out && rm junk.out done minc-2.2.00/testdir/run_test2.sh0000755000265600003100000000032512027132663013403 00000000000000#! /bin/sh set -e tests="minc_types icv_range icv icv_dim icv_dim1 icv_fillvalue" for test in $tests; do echo "Testing $test" ./$test -2 > junk.out diff $srcdir/$test.out junk.out && rm junk.out done minc-2.2.00/testdir/xfmconcat_01.sh0000755000265600003100000000066712027132663013751 00000000000000#! /bin/sh # # Test concatenation of grid transforms. set -e # Create volume to use as displacement grid. # dd if=/dev/zero | ../rawtominc -vector 3 -byte -clobber _grid.mnc 8 8 8 ./create_grid_xfm _grid.mnc _t1.xfm ./create_grid_xfm _grid.mnc _t2.xfm ../xfmconcat -clobber _t1.xfm _t2.xfm _t3.xfm # Make sure the displacement volumes have unique filenames. # test -n "`grep Displacement_Volume _t3.xfm |uniq -u`" || exit 1 exit 0 minc-2.2.00/testdir/xfmconcat_02.sh0000755000265600003100000000163112027132663013742 00000000000000#! /bin/sh # # Test application of concatenated transforms. set -e # _t1.xfm is linear transform. # _t2.xfm is inverse of _t1 # _t3.xfm is grid transform. # _t4.xfm is inverse of _t3 cp $srcdir/t1.xfm _t1.xfm ../xfminvert -clobber _t1.xfm _t2.xfm dd if=/dev/zero | ../rawtominc -vector 3 -byte -clobber _grid.mnc 8 8 8 ./create_grid_xfm _grid.mnc _t3.xfm ../xfminvert -clobber _t3.xfm _t4.xfm # Test primary transforms. # ./test_xfm 10000 _t1.xfm ./test_xfm 10000 _t2.xfm ./test_xfm 10000 _t3.xfm ./test_xfm 10000 _t4.xfm # Test concatenations. # ../xfmconcat -clobber _t1.xfm _t3.xfm _t5.xfm ./test_xfm 10000 _t5.xfm ../xfmconcat -clobber _t1.xfm _t4.xfm _t6.xfm ./test_xfm 10000 _t6.xfm ../xfmconcat -clobber _t5.xfm _t6.xfm _t7.xfm ./test_xfm 10000 _t7.xfm ../xfminvert -clobber _t7.xfm _t8.xfm ./test_xfm 10000 _t8.xfm ../xfmconcat -clobber _t8.xfm _t2.xfm _t4.xfm _t7.xfm _t9.xfm ./test_xfm 10000 _t9.xfm minc-2.2.00/testdir/run_test_progs.sh0000755000265600003100000000037412027132663014537 00000000000000#! /bin/sh set -e root=`pwd`/.. progs=${root}/progs PATH=${root}:${progs}/mincdiff::${progs}/mincpik:${progs}/mincheader:${progs}/minchistory:${progs}/mincview:${PATH} export PATH mincheader icv.mnc > /dev/null mincdiff icv.mnc icv.mnc > /dev/null minc-2.2.00/testdir/icv.out0000644000265600003100000000047012027132663012432 00000000000000 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143 145 147 149 211 213 215 217 219 221 223 225 227 229 231 233 235 237 239 241 243 245 247 249 311 313 315 317 319 321 323 325 327 329 331 333 335 337 339 341 343 345 347 349 minc-2.2.00/testdir/icv_dim.out0000644000265600003100000000062112027132663013261 00000000000000adim start = 23, step = -0.4 bdim start = 27.6, step = -2.4 norm : max = 200, min = -200 112 112 116 116 0 122 122 126 126 0 132 132 136 136 0 0 0 0 0 0 212 212 216 216 0 222 222 226 226 0 232 232 236 236 0 0 0 0 0 0 312 312 316 316 0 322 322 326 326 0 332 332 336 336 0 0 0 0 0 0 minc-2.2.00/testdir/icv_dim1.out0000644000265600003100000000062112027132663013342 00000000000000adim start = 23, step = -0.4 bdim start = 27.6, step = -2.4 norm : max = 200, min = -200 112 112 116 116 0 122 122 126 126 0 132 132 136 136 0 0 0 0 0 0 212 212 216 216 0 222 222 226 226 0 232 232 236 236 0 0 0 0 0 0 312 312 316 316 0 322 322 326 326 0 332 332 336 336 0 0 0 0 0 0 minc-2.2.00/testdir/icv_fillvalue.out0000644000265600003100000000055512027132663014501 00000000000000 No dimconv, default fillvalue: 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143 145 147 -32768 No dimconv, fillvalue=-32: 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143 145 147 -32 With dimconv, fillvalue=-32: 116 118 120 122 124 136 138 140 142 -32 32767 32767 32767 32767 32767 32767 32767 32767 32767 32767 minc-2.2.00/testdir/icv_range.out0000644000265600003100000000667712027132663013625 00000000000000in : short, out : short, norm : true, imgmax : true, valid : true file value = 24000 icv value = 12500 in : short, out : short, norm : true, imgmax : true, valid : false file value = 16383 icv value = 12500 in : short, out : short, norm : true, imgmax : false, valid : true file value = 20000 icv value = 12500 in : short, out : short, norm : true, imgmax : false, valid : false file value = 8191 icv value = 12500 in : short, out : double, norm : true, imgmax : true, valid : true file value = 0.2 icv value = 12500 in : short, out : double, norm : true, imgmax : true, valid : false file value = 0.2 icv value = 12500 in : short, out : double, norm : true, imgmax : false, valid : true file value = 20000 icv value = 12500 in : short, out : double, norm : true, imgmax : false, valid : false file value = 0.625 icv value = 12500 in : short, out : short, norm : false, imgmax : true, valid : true file value = 20000 icv value = 12500 in : short, out : short, norm : false, imgmax : true, valid : false file value = 8191 icv value = 12500 in : short, out : short, norm : false, imgmax : false, valid : true file value = 20000 icv value = 12500 in : short, out : short, norm : false, imgmax : false, valid : false file value = 8191 icv value = 12500 in : short, out : double, norm : false, imgmax : true, valid : true file value = 0.1 icv value = 12500 in : short, out : double, norm : false, imgmax : true, valid : false file value = 0.1 icv value = 12500 in : short, out : double, norm : false, imgmax : false, valid : true file value = 0.625 icv value = 12500 in : short, out : double, norm : false, imgmax : false, valid : false file value = 0.625 icv value = 12500 in : double, out : short, norm : true, imgmax : true, valid : true file value = 24000 icv value = 0.2 in : double, out : short, norm : true, imgmax : true, valid : false file value = 16383 icv value = 0.199997 in : double, out : short, norm : true, imgmax : false, valid : true file value = 6400 icv value = 0.2 in : double, out : short, norm : true, imgmax : false, valid : false file value = -19661 icv value = 0.2 in : double, out : double, norm : true, imgmax : true, valid : true file value = 0.2 icv value = 0.2 in : double, out : double, norm : true, imgmax : true, valid : false file value = 0.2 icv value = 0.2 in : double, out : double, norm : true, imgmax : false, valid : true file value = 0.2 icv value = 0.2 in : double, out : double, norm : true, imgmax : false, valid : false file value = 0.2 icv value = 0.2 in : double, out : short, norm : false, imgmax : true, valid : true file value = 24000 icv value = 0.2 in : double, out : short, norm : false, imgmax : true, valid : false file value = 16383 icv value = 0.199997 in : double, out : short, norm : false, imgmax : false, valid : true file value = 6400 icv value = 0.2 in : double, out : short, norm : false, imgmax : false, valid : false file value = -19661 icv value = 0.2 in : double, out : double, norm : false, imgmax : true, valid : true file value = 0.2 icv value = 0.2 in : double, out : double, norm : false, imgmax : true, valid : false file value = 0.2 icv value = 0.2 in : double, out : double, norm : false, imgmax : false, valid : true file value = 0.2 icv value = 0.2 in : double, out : double, norm : false, imgmax : false, valid : false file value = 0.2 icv value = 0.2 minc-2.2.00/testdir/minc_types.out0000644000265600003100000002521312027132663014025 00000000000000Image 1 : unsigned byte Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned byte Image 2 : signed__ byte image[0] = 10 image[1] = 0 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned byte Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned byte Image 2 : signed__ short image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned byte Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned byte Image 2 : signed__ int image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned byte Image 2 : signed__ float image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned byte Image 2 : signed__ double image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ byte Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ byte Image 2 : signed__ byte image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ byte Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ byte Image 2 : signed__ short image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ byte Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ byte Image 2 : signed__ int image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ byte Image 2 : signed__ float image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ byte Image 2 : signed__ double image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : unsigned short Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned short Image 2 : signed__ byte image[0] = 10 image[1] = 0 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned short Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned short Image 2 : signed__ short image[0] = 10 image[1] = 0 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned short Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned short Image 2 : signed__ int image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned short Image 2 : signed__ float image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned short Image 2 : signed__ double image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ short Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ short Image 2 : signed__ byte image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ short Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ short Image 2 : signed__ short image[0] = 10 image[1] = -32768 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ short Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ short Image 2 : signed__ int image[0] = 10 image[1] = -32768 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ short Image 2 : signed__ float image[0] = 10 image[1] = -32768 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ short Image 2 : signed__ double image[0] = 10 image[1] = -32768 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : unsigned int Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned int Image 2 : signed__ byte image[0] = 10 image[1] = 0 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned int Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned int Image 2 : signed__ short image[0] = 10 image[1] = 0 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned int Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 4.29497e+09 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned int Image 2 : signed__ int image[0] = 10 image[1] = 0 image[2] = 2.14748e+09 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned int Image 2 : signed__ float image[0] = 10 image[1] = 0 image[2] = 4.29497e+09 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : unsigned int Image 2 : signed__ double image[0] = 10 image[1] = 0 image[2] = 4.29497e+09 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ int Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ int Image 2 : signed__ byte image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ int Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ int Image 2 : signed__ short image[0] = 10 image[1] = -32768 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ int Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 2.14748e+09 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ int Image 2 : signed__ int image[0] = 10 image[1] = -2.14748e+09 image[2] = 2.14748e+09 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ int Image 2 : signed__ float image[0] = 10 image[1] = -2.14748e+09 image[2] = 2.14748e+09 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ int Image 2 : signed__ double image[0] = 10 image[1] = -2.14748e+09 image[2] = 2.14748e+09 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ float Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ float Image 2 : signed__ byte image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ float Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ float Image 2 : signed__ short image[0] = 10 image[1] = -32768 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ float Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 4.29497e+09 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ float Image 2 : signed__ int image[0] = 10 image[1] = -2.14748e+09 image[2] = 2.14748e+09 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ float Image 2 : signed__ float image[0] = 10 image[1] = -3.40282e+38 image[2] = 3.40282e+38 image[3] = 3.2 image[4] = 3.7 image[5] = -3.2 image[6] = -3.7 Image 1 : signed__ float Image 2 : signed__ double image[0] = 10 image[1] = -3.40282e+38 image[2] = 3.40282e+38 image[3] = 3.2 image[4] = 3.7 image[5] = -3.2 image[6] = -3.7 Image 1 : signed__ double Image 2 : unsigned byte image[0] = 10 image[1] = 0 image[2] = 255 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ double Image 2 : signed__ byte image[0] = 10 image[1] = -128 image[2] = 127 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ double Image 2 : unsigned short image[0] = 10 image[1] = 0 image[2] = 65535 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ double Image 2 : signed__ short image[0] = 10 image[1] = -32768 image[2] = 32767 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ double Image 2 : unsigned int image[0] = 10 image[1] = 0 image[2] = 4.29497e+09 image[3] = 3 image[4] = 4 image[5] = 0 image[6] = 0 Image 1 : signed__ double Image 2 : signed__ int image[0] = 10 image[1] = -2.14748e+09 image[2] = 2.14748e+09 image[3] = 3 image[4] = 4 image[5] = -3 image[6] = -4 Image 1 : signed__ double Image 2 : signed__ float image[0] = 10 image[1] = -3.40282e+38 image[2] = 3.40282e+38 image[3] = 3.2 image[4] = 3.7 image[5] = -3.2 image[6] = -3.7 Image 1 : signed__ double Image 2 : signed__ double image[0] = 10 image[1] = -6.80565e+38 image[2] = 6.80565e+38 image[3] = 3.2 image[4] = 3.7 image[5] = -3.2 image[6] = -3.7 minc-2.2.00/testdir/t1.xfm0000644000265600003100000000017712027132663012164 00000000000000MNI Transform File % Single linear transformation. Transform_Type = Linear; Linear_Transform = 1 0 0 10 0 1 0 20 0 0 1 30; minc-2.2.00/testdir/icv.mnc0000644000265600003100000000456012027132663012404 00000000000000CDF zspaceyspacexspace zspace varidMINC standard variablevartypedimension____versionMINC Version 1.0comments.Z increases from patient inferior to superiorspacing regular__ alignmentcentrestep?é™™™™™šstart@64yspace varidMINC standard variablevartypedimension____versionMINC Version 1.0comments/Y increases from patient posterior to anteriorspacing regular__ alignmentcentrestep?é™™™™™šstart@6<xspace varidMINC standard variablevartypedimension____versionMINC Version 1.0comments'X increases from patient left to rightspacing regular__ alignmentcentrestep?é™™™™™šstart@6Dimage parent rootvariablevaridMINC standard variablevartypegroup________versionMINC Version 1.0 valid_max@ßÿÀ valid_minÀà image-max--->image-max image-min--->image-minðL rootvariable varidMINC standard variablevartypegroup________versionMINC Version 1.0parentchildrenimage < image-max varidMINC standard variablevartypevar_attributeversionMINC Version 1.0 _FillValue?ðparentimage @ image-min varidMINC standard variablevartypevar_attributeversionMINC Version 1.0 _FillValueparentimage XGžGžGžoqsuwy{}ƒ…‡‰‹‘“•ÓÕ×ÙÛÝßáãåçéëíïñóõ÷ù79;=?ACEGIKMOQSUWY[]€@i@i@iÀiÀiÀiminc-2.2.00/doc/0000755000265600003100000000000012030114724010256 500000000000000minc-2.2.00/doc/Makefile.am0000644000265600003100000000061212027132661012237 00000000000000EXTRA_DIST = prog_guide.tex prog_ref.tex SUFFIXES = .tex .dvi .ps .PHONY: docs docs: prog_ref.ps prog_guide.ps .tex.dvi: latex $< latex $< prog_ref.ps: prog_ref.dvi dvips $? -o $@ prog_guide.ps: prog_guide.dvi dvips $? -o $@ CLEANFILES = \ prog_ref.aux prog_ref.dvi prog_ref.log prog_ref.ps prog_ref.toc \ prog_guide.aux prog_guide.dvi prog_guide.log prog_guide.ps prog_guide.toc minc-2.2.00/doc/Makefile.in0000644000265600003100000002275312030077514012261 00000000000000# Makefile.in generated by automake 1.10.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = doc DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mni_REQUIRE_LIB.m4 \ $(top_srcdir)/m4/smr_WITH_BUILD_PATH.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POD2MAN = @POD2MAN@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_F77 = @ac_ct_F77@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = prog_guide.tex prog_ref.tex SUFFIXES = .tex .dvi .ps CLEANFILES = \ prog_ref.aux prog_ref.dvi prog_ref.log prog_ref.ps prog_ref.toc \ prog_guide.aux prog_guide.dvi prog_guide.log prog_guide.ps prog_guide.toc all: all-am .SUFFIXES: .SUFFIXES: .tex .dvi .ps $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am .PHONY: docs docs: prog_ref.ps prog_guide.ps .tex.dvi: latex $< latex $< prog_ref.ps: prog_ref.dvi dvips $? -o $@ prog_guide.ps: prog_guide.dvi dvips $? -o $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: minc-2.2.00/doc/prog_guide.tex0000644000265600003100000010264512027132661013062 00000000000000% % Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, % Montreal Neurological Institute, McGill University. % Permission to use, copy, modify, and distribute this % software and its documentation for any purpose and without % fee is hereby granted, provided that the above copyright % notice appear in all copies. The author and McGill University % make no representations about the suitability of this % software for any purpose. It is provided "as is" without % express or implied warranty. % \documentclass{article} \title{MINC Programmer's Guide} \author{Peter Neelin} \date{May 14, 1993} \textwidth 6.0in \oddsidemargin 0.125in \textheight 8.5in \topmargin -0.75in \begin{document} \maketitle \tableofcontents \clearpage \section{Introduction} The MINC file format (Medical Image NetCDF) is based on the NetCDF file format (Network Common Data Form) distributed by the Unidata Program Center. NetCDF provides a software interface for storing named, multi-dimensional variables in files in a machine-independent way. This interface removes applications from the concerns of portability and file structure and encourages a self-describing form of data. Each NetCDF multi-dimensional variable in a file is described by a name, by its dimensions and by attributes. For example, an image stored in a file might be stored as byte data in a variable called ``\verb+image+'', with dimensions ``\verb+x+'' and ``\verb+y+'' (each of length 256) and with an attribute called ``\verb+long_name+'' which is a string describing the content of the image. Many variables can be stored in one file and each variable can have many attributes. Dimensions exist independently of variables and can subscript more than one variable. MINC provides three things on top of the NetCDF interface. It provides a standard for dimension, variable and attribute names suitable for medical imaging, it provides some convenience functions to complement the NetCDF interface (not specific to the MINC conventions) and it provides convenience functions for using MINC files. \section{An Introduction to NetCDF} (For a complete description, see the ``NetCDF User's Guide''). \subsection{The NetCDF file} It is useful to look at an example file while considering the NetCDF interface. Fortunately, the NetCDF package provides utilities (ncdump and ncgen) for converting the binary NetCDF files to an ascii format call CDL. A simple NetCDF file, converted to CDL notation by ncdump, is given below: \begin{verbatim} netcdf test { dimensions: ycoord = 3 ; xcoord = 4 ; variables: double image(ycoord, xcoord) ; image:long_name = "My favorite tiny image" ; double xcoord(xcoord) ; data: image = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ; xcoord = 100, 200, 300, 400 ; } \end{verbatim} The sample file stores a 3 by 4 image of double precision values. The first thing defined are the dimensions : \verb+xcoord+ and \verb+ycoord+. Dimensions can represent physical dimensions like x coordinate, y coordinate etc., or they can represent abstract things like lookup-table index. Each dimension has a name and a length and when joined with other dimensions defines the shape of a variable --- the variable image is subscripted by \verb+ycoord+ and \verb+xcoord+. Dimensions can also be used across variables, relating them to each other. For example, if the file contained another image also subscripted by \verb+ycoord+ and \verb+xcoord+, we would have the important information that the two variables were sampled on the same grid. Also, coordinate systems can be defined by creating variables by the same name as the dimension, like \verb+xcoord+ in the example above, giving the x coordinate of each point in the image. Variables are the next thing defined in the cdl file. Each variable has a name, data type and a shape specified by a list of dimensions (up to a maximum of \verb+MAX_VAR_DIMS+ = 32 dimensions per variable). The data types are \verb+NC_CHAR+, \verb+NC_BYTE+, \verb+NC_SHORT+, \verb+NC_INT+, \verb+NC_FLOAT+ and \verb+NC_DOUBLE+. Information about each variable is stored in attributes. The attribute ``\verb+long_name+'' gives a character string describing the variable ``\verb+image+''. Attributes are either scalars or vectors of one of the six types listed above (a character string is a vector of type \verb+NC_CHAR+). \subsection{Programming with NetCDF} Programming with NetCDF can be quite simple. The file listed above was produced by the following program: \begin{verbatim} #include #define THE_NAME "My favorite tiny image" static double vals[][4]={ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,10.0,11.0,12.0 }; static int ysize=sizeof(vals)/sizeof(vals[0]); static int xsize=sizeof(vals[0])/sizeof(vals[0][0]); static double xcoord[]={100.,200.,300.,400.}; main() { int cdf, img, xvar; int dim[MAX_VAR_DIMS]; long count[MAX_VAR_DIMS], start[MAX_VAR_DIMS]; /* Create the file */ cdf=nccreate("test.cdf",NC_CLOBBER); /* Define the dimensions */ dim[0]=ncdimdef(cdf, "ycoord", ysize); dim[1]=ncdimdef(cdf, "xcoord", xsize); /* Define the variables */ img=ncvardef(cdf, "image", NC_DOUBLE, 2, dim); xvar=ncvardef(cdf,"xcoord", NC_DOUBLE, 1, &dim[1]); /* Add an attribute */ ncattput(cdf, img, "long_name", NC_CHAR, strlen(THE_NAME)+1, THE_NAME); /* End definition mode */ ncendef(cdf); /* Write the variable values */ start[0]=start[1]=0; count[0]=ysize; count[1]=xsize; ncvarput(cdf, img, start, count, vals); ncvarput(cdf, xvar, &start[1], &count[1], xcoord); ncclose(cdf); } \end{verbatim} The first executable line of the program creates a new NetCDF file. An open file is either in ``define'' mode or in ``data'' mode. In define mode, dimensions, variables and attributes can be defined, but data cannot be written to or read from variables. In data mode, variable values can be written or read, but no changes to dimensions or variables can be made and attributes can only be written if they exist already and will not get larger with the write. Newly created files are automatically in define mode. The lines following the call to nccreate define the dimensions and variables in the file. Notice that the NetCDF file, dimensions and variables are all identified by an integer returned when they are created. These id's are subsequently used to refer to each object. The attribute ``\verb+long_name+'' for the image variable is identified only by its name. Once everything is defined, ncendef puts the file into data mode and values are written. The values to write are defined by a vector of starting indices and a vector of the number of values to write in each dimension. This defines a multi-dimensional rectangle within the variable called a hyperslab. In the C interface, the first element of the vector refers to the slowest varying index of the variable, so in this example, the array vals has the \verb+xcoord+ varying fastest. In the FORTRAN interface, the convention has the first subscript varying fastest. These conventions follow the language conventions for multi-dimensional arrays. \section{The MINC format} It is possible to build MINC format files using only NetCDF function calls, however a C include file is provided to facilitate (and help ensure) adherence to the standard. This file defines useful constants, standard dimension, variable and attribute names and some attribute values. It also declares the functions defined in a library of minc convenience functions, designed to make an application programmer's life easier. \subsection{The MINC standard} Various requirements for file formats have been put forward. One such list is as follows: A protocol should be: 1) simple, 2) self describing, 3) maintainable, 4) extensible, 5) N dimensional, and 6) have a universal data structure. The NetCDF format meets all of these requirements, suggesting that it is a good place to start. I would, however, add some more requirements to the list. Implied in the above list is the requirement that there be a standard for accessing data (how do I get the patient name) --- this is not provided by NetCDF. Furthermore, a useful format should come with a software interface that makes it easy to use, particularly in a development environment. Finally, a format that stores many associated pieces of information should also provide some data organization. The MINC format attempts to add these things to the NetCDF format. \subsubsection{MINC variable types} Medical imaging tends to produce files with a large amount of ancillary data (patient information, image information, acquisition information, etc.). To organise this information in a useful fashion, MINC uses variables to group together related attributes. The variable itself may or may not contain useful data. For example, the variable \verb+MIimage+ contains the image data and has attributes relevant to this data. The variable \verb+MIpatient+ has no relevant variable data, but serves to group together all attributes describing the patient (name, birthdate, etc.). This sort of variable is called a group variable. Variables that correspond to dimensions are called dimension variables and describe the coordinate system corresponding to the dimension. An example is MIxspace --- both a dimension and a variable describing the x coordinate of other variables. The NetCDF conventions allow for these dimension variables to specify the coordinate at each point, but there is nothing to describe the width of the sample at that point. MINC provides the convention of dimension width variables, e.g. \verb+MIxspace_width+, to give this information. Finally, it is possible to have attributes that vary over some of the dimensions of the variable. For example, if we have a volume of image data, varying over \verb+MIxspace+, \verb+MIyspace+ and \verb+MIzspace+, we may want an attribute giving the maximum value of the each image, varying over \verb+MIzspace+. To achieve this we use a variable, called a variable attribute, pointed to by an attribute of the image variable. Thus MINC introduces a number of types of variables: group variables, dimension variables, dimension width variables and variable attributes. \subsubsection{Data organization} MINC attempts to provide some level of data organization through a hierarchy of group variables. As mentioned above, attributes are grouped according to type in group variables. Each group variable can have an \verb+MIparent+ and an \verb+MIchildren+ attribute --- the former specifying the name of another variable that is above this one in the hierarchy, the latter specifying a newline-separated list of variables that come below this one in the hierarchy. At the root of the hierarchy is the \verb+MIrootvariable+ variable, with no parent. Although it is not necessary to make use of this structure, it can provide a mechanism for ordering large amounts of information. \subsubsection{MINC dimension, variable and attribute names} The NetCDF format says nothing about variable and dimension naming conventions and little about attribute names. It does provide a few standards, such as the attribute ``\verb+long_name+'' for describing a variable, which have been adopted by the MINC standard. MINC defines a set of standard names for commonly used entities and the include file defines constants specifying these names. These are described at length in the MINC reference manual. The most interesting of these is \verb+MIimage+, the name of the variable used for storing the actual image data in the file. \subsubsection{Image dimensions} The MINC standard gives some special status to the concept of an image. There is nothing inherent in NetCDF that suggests any special status for particular dimensions, but it can be convenient to place limitations on what can vary over which dimensions in an imaging context. For example, the requirement that the variables that specify how to rescale images (see later section on pixel values) not vary with image dimensions means that we can treat the image as a simple unit. In the simplest case, the image dimensions are simply the two fastest varying dimensions of the \verb+MIimage+ variable. It can also be helpful to allow for vector fields --- images or image volumes that have a vector of values at each point. A simple example of a vector field is an RGB image. At each point in space, there are three values: red, green and blue. The dimension \verb+MIvector_dimension+ is used for the components of the vector and it should be the fastest varying dimension in the \verb+MIimage+ variable. If it is present, then the three fastest varying dimensions of \verb+MIimage+ are the image dimensions. \subsubsection{MINC coordinate system} The MINC standard defines how spatial coordinates should be oriented relative to patients. Files are free to have data stored in the desired direction, but positive world coordinates are given a definite meaning in the medical imaging context. The standard is that the positive x axis points from the patient's left to right, the positive y axis points from posterior to anterior and the positive z axis points from inferior to superior. The conversion of element index to world coordinates is done using the dimension variable attributes \verb+MIdirection_cosines+, \verb+MIstep+ and \verb+MIstart+. If the direction cosines are ${\bf c}=(c_x, c_y, c_z)$, then the vector between adjacent elements along an axis is $step\times {\bf c}$. If $start(i)$ and ${\bf c}(i)$ are the \verb+MIstart+ and \verb+MIdirection_cosines+ attributes for dimension $i$ (one of \verb+MIxspace+, \verb+MIyspace+ and \verb+MIzspace+), then the first element of the image variable is at world coordinate $ \sum_i start(i) {\bf c}(i) $. If the direction cosines are not present, then they are assumed to be $(1,0,0)$ for \verb+MIxspace+, $(0,1,0)$ for \verb+MIyspace+ and $(0,0,1)$ for \verb+MIzspace+. Direction cosines are unit vectors and should be normalized. As well, the step attribute should carry the information about axis flipping (negative or positive) rather than the direction cosine. \subsubsection{Pixel values and real values} In medical imaging, pixel values are frequently stored as bytes or shorts, but there is a generally a real value associated with each pixel as well. This real value is obtained by a scale factor and offset associated with each image or image volume. The MINC standard indicates how pixel values should be interpreted. Image data in the \verb+MIimage+ variable can be stored as bytes, shorts, ints (32-bit), floats or doubles. NetCDF conventions use the attributes \verb+MIvalid_range+ or \verb+MIvalid_max+ and \verb+MIvalid_min+ to indicate the range of values that can be found in the variable. For short values, for example, we might have a valid range of 0 to 32000. To convert these integers to real values, we could use a scale and offset. However, these values would have to change if the data where converted to bytes in the range 23 to 228. If we specify an image maximum and minimum to which \verb+MIvalid_max+ and \verb+MIvalid_min+ should be mapped by an appropriate scale and offset, then we can convert type and valid range without having to change the real maximum and minimum. To allow the maximum dynamic range in an image, we use the variables \verb+MIimagemax+ and \verb+MIimagemin+ to store the real maximum and minimum --- these can vary over any of the non-image dimensions of \verb+MIimage+. \subsection{General convenience functions} MINC provides a number of convenience functions that have nothing to do with medical imaging, but that make the use of NetCDF files a little easier. One of the drawbacks of the NetCDF format is that data can come in any form (byte, short, int, float, double) and the calling program must handle the general case. Rather than restrict this, MINC provides functions to convert types. The first set of convenience functions are for type conversion. A list follows : \begin{itemize} \item {\bf \verb+miattget+} - reads an attribute vector, specifying the numeric type desired and the maximum number of values to read. \item {\bf \verb+miattget1+} - reads one attribute value of the specified type. \item {\bf \verb+miattgetstr+} - read a character attribute of a specified maximum length. \item {\bf \verb+miattputdbl+} - write a double precision attribute. \item {\bf \verb+miattputstr+} - write a string attribute. \item {\bf \verb+mivarget+} - get a hyperslab of values of the specified type. \item {\bf \verb+mivarget1+} - get a single value of the specified type. \item {\bf \verb+mivarput+} - put a hyperslab of values of the specified type. \item {\bf \verb+mivarput1+} - put a single value of the specified type. \end{itemize} Next we have some functions for handling coordinate vectors : \begin{itemize} \item {\bf \verb+miset_coords+} - set a vector of coordinates to a single value. \item {\bf \verb+mitranslate_coords+} - translate the coordinates for one variable to a vector for subscripting another variable. \end{itemize} Finally, there are functions for dealing with variables as groups of attributes, making it easier to modify a file while keeping ancillary information : \begin{itemize} \item {\bf \verb+micopy_all_atts+} - copy all of the attributes of one variable to another (possibly across files). \item {\bf \verb+micopy_var_def+} - copy a variable definition (including attributes) from one file to another. \item {\bf \verb+micopy_var_vals+} - copy a variable's values from one variable to another (possibly across files). \item {\bf \verb+micopy_all_var_defs+} - copy all variable definitions from one file to another, excluding a list of variables. \item {\bf \verb+micopy_all_var_vals+} - copy all variable values from one file to another, excluding a list of variables. \end{itemize} \subsection{MINC specific convenience functions} A few routines are provided to deal with some of the minc structures. \verb+miattput_pointer+ and \verb+miattget_pointer+ put/get a pointer to a variable attribute. \verb+miadd_child+ helps maintain the hierarchy of variables by handling the \verb+MIparent+ and \verb+MIchildren+ attributes of two variables. Finally \verb+micreate_std_variable+ and \verb+micreate_group_variable+ create some of the standard variables and fill in a few of the default attributes. \subsection{Image conversion variables} One of the requirements for file formats mentioned earlier was a software interface to make the interface easy to use. The biggest difficulty in using a flexible format is that the application must handle many possibilities. Where images are concerned, this means various data types and scale factors, and images of differing sizes. The image conversion variable functions of MINC attempt to remove this complication for the programmer. An image conversion variable (icv) is essentially a specification of what the program wants images to look like, in type, scale and dimension. When an MINC image is read through an icv, it is converted for the calling program to a standard format regardless of how data is stored in the file. There are two categories of conversion: Type and range conversions change the datatype (and sign) of image values and optionally scale them for proper normalization. Dimension conversions allow programs to specify image dimension size and image axis orientation (should \verb+MIxspace+ coordinates be increasing or decreasing? should the patient's left side appear on the left or right of the image?). \subsubsection{ICV routines} Accessing a file through an icv is a straight-forward process. Create the icv with \verb+miicv_create+, set properties (like desired datatype) with the \verb+miicv_set+ routines, attach the icv to a NetCDF variable with \verb+miicv_attach+ and access the data with \verb+miicv_get+ or \verb+miicv_put+. The icv can be detached from a NetCDF variable with \verb+miicv_detach+ and can be freed with \verb+miicv_free+. Icv properties are strings, integers, long integers or doubles. For example, \verb+MI_ICV_SIGN+ (the sign of variable values) is a string, while \verb+MI_ICV_IMAGE_MAX+ (image maximum) is a double precision value. Four functions --- \verb+miicv_setint+, \verb+miicv_setlong+, \verb+miicv_setdbl+ and \verb+miicv_setstr+ --- are provided to simplify the setting of property values. Programs can inquire about property values with \verb+miicv_inqint+, \verb+miicv_inqlong+, \verb+miicv_inqdbl+ and \verb+miicv_inqstr+. \subsubsection{Type and range conversion} Pixel values are converted for type and sign by specifying values for the properties \verb+MI_ICV_TYPE+ and \verb+MI_ICV_SIGN+ (they default to \verb+NC_SHORT+ and \verb+MI_SIGNED+). Values can also be converted for valid range and for normalization. These conversions are enabled by setting \verb+MI_ICV_DO_RANGE+ to \verb+TRUE+ (the default). If \verb+MI_ICV_DO_NORM+ is \verb+FALSE+ (the default) then only conversions for valid range are made. This means that if the input file has shorts in the range 0 to 4095, then they can be converted to bytes in the range 64 to 248 (for example). The real image maximum and minimum (\verb+MIimagemax+ and \verb+MIimagemin+) are ignored. The valid range is specified by the properties \verb+MI_ICV_VALID_MAX+ and \verb+MI_ICV_VALID_MIN+, which default to the legal range for the type and sign. We may want to scale values so that they are normalized either to all values in the \verb+MIimage+ variable or to some user-defined range. To do normalization, set \verb+MI_ICV_DO_NORM+ to \verb+TRUE+. Setting \verb+MI_ICV_USER_NORM+ to \verb+FALSE+ (the default) causes normalization to the real maximum and minimum of the variable (the maximum of \verb+MIimagemax+ and the minimum of \verb+MIimagemin+). If \verb+MI_ICV_USER_NORM+ is true then the values of \verb+MI_ICV_IMAGE_MAX+ and \verb+MI_ICV_IMAGE_MIN+ are used (defaulting to 1.0 and 0.0). When either \verb+MI_ICV_TYPE+ or the file type is floating-point, then the conversion to and from real values is always done using the real image maximum and minimum information. If the internal type is integer and \verb+MI_ICV_DO_NORM+ is \verb+FALSE+, then the rescaling is done so that the slice maximum maps to the valid range of the internal values. Note that when converting to integer types, values are rounded to the nearest integer and limited to be within the legal range for the data type. The above transformations are simple enough, but the use of floating-point values adds to the complexity, since in general we do not want to rescale these values to get the real values. The various possibilities are described in greater detail below. \subsubsection{The details of pixel value conversion} The easiest way to think about the rescaling is through four ranges (maximum-minimum pairs). In the file variable, values have a valid range \verb+var_vrange+ and these correspond to real values \verb+var_imgrange+. The user/application wants to convert real values \verb+usr_imgrange+ to a useful valid range \verb+usr_vrange+. From \verb+var_vrange+, \verb+var_imgrange+, \verb+usr_imgrange+ and \verb+usr_vrange+, we can determine a scale and offset for converting pixel values: Input values are scaled to real values by \verb+var_vrange+ to \verb+var_imgrange+ and then scaled again to user values by \verb+usr_imgrange+ to \verb+usr_vrange+. If either of the \verb+vrange+ variables are not specified, they default to maximum possible range for integer types. For floating point types, \verb+usr_vrange+ is set equal to \verb+usr_imgrange+ so that no conversion of real values is done. If normalization is not being done, then for integer types \verb+var_imgrange+ and \verb+usr_imgrange+ are set to [0,1] (scale down to [0,1] and scale up again). When normalizibng, \verb+usr_imgrange+ is set to either the full range of the variable ([0,1] if not found) or the user's requested range. If the variable values are floating point, then \verb+var_imgrange+ is set to \verb+var_vrange+ (no scaling to real values), otherwise \verb+var_imgrange+ is read for each image (again, [0,1] if not found). What this means for reading and writing images is discussed below. \subsubsection{Reading with pixel conversion} When reading into internal floating point values, normalization has no effect. When reading integers without normalization, each image is scaled to full range. With normalization they are scaled to the specified range and slices can be compared. When the input file is missing either \verb+MIimagemax+/\verb+MIimagemin+ (\verb+var_imgrange+ information) or \verb+MIvalid_range+, the routines try to provide sensible defaults, but funny things can still happen. The biggest problem is the absence of \verb+MIvalid_range+ if the defaults are not correct (full range for integer values and [0,1] for floating point). When converting floating point values to an integer type, there will be overflows if values are outside the range [0,1]. \subsubsection{Writing with pixel conversion} The conversion routines can be used for writing values. This can be useful for data compression --- e.g. converting internal floats to byte values in the file, or converting internal shorts to bytes. When doing this with normalization (to rescale bytes to the slice maximum, for example) it is important to write the slice maximum and minimum in \verb+MIimagemax+ and \verb+MIimagemin+ before writing the slice. The other concern is that \verb+MIvalid_range+ or \verb+MIvalid_max+ and \verb+MIvalid_min+ be written properly (especially if the defaults are not correct). When writing floating point values, \verb+MIvalid_range+ should be set to the full range of values in the variable. In this case, the attribute does not have to be set correctly before writing the variable, but if it exists, the values should be reasonable (maximum greater than minimum and values not likely to cause overflow). These will be set automatically if the routine \verb+micreate_std_variable+ is used with \verb+NC_FILL+ mode on (the default). \subsubsection{Example: Reading values} Read an image without normalization: \begin{verbatim} /* Create the icv */ icv=miicv_create(); (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT); (void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED); (void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000); (void) miicv_setint(icv, MI_ICV_VALID_MIN, 0); /* Open the file, attach the image variable */ cdfid=ncopen(filename, NC_NOWRITE); /* Attach image variable */ img=ncvarid(cdfid, MIimage); (void) miicv_attach(icv, cdfid, img); /* Get the data - we assume that coord and count are set properly */ (void) miicv_get(icv, coord, count, image); /* Close the file and free the icv */ (void) ncclose(cdfid); (void) miicv_free(icv); \end{verbatim} Read an integer image with normalization: \begin{verbatim} /* Create the icv */ icv=miicv_create(); (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT); (void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED); (void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000); (void) miicv_setint(icv, MI_ICV_VALID_MIN, 0); (void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(icv, MI_ICV_USER_NORM, TRUE); (void) miicv_setdbl(icv, MI_ICV_IMAGE_MAX, 1.83); (void) miicv_setdbl(icv, MI_ICV_IMAGE_MIN, -0.57); ... \end{verbatim} Read a floating point image : \begin{verbatim} /* Create the icv. We don't have to set MI_ICV_USER_NORM to TRUE, but doing so ensures that the conversion is done properly without looking at file values (the defaults for MI_ICV_IMAGE_MAX and MI_ICV_IMAGE_MIN are 1 and 0) */ icv=miicv_create(); (void) miicv_setint(icv, MI_ICV_TYPE, NC_FLOAT); (void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE); (void) miicv_setint(icv, MI_ICV_USER_NORM, TRUE); ... \end{verbatim} \subsubsection{Example: Writing values} Writing from floating point to byte values : \begin{verbatim} /* Create the icv */ icv=miicv_create(); (void) miicv_setint(icv, MI_ICV_TYPE, NC_FLOAT); (void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE); /* Create the file */ cdf=nccreate(filename, NC_CLOBBER); /* Define the dimensions */ dim[0]=ncdimdef(cdf, MIyspace, ysize); dim[1]=ncdimdef(cdf, MIxspace, xsize); /* Define the variables */ img=micreate_std_variable(cdf, MIimage, NC_BYTE, 2, dim); (void) miattputstr(cdf, img, MIsigntype, MI_UNSIGNED); vrange[0]=0; vrange[1]=200; (void) ncattput(cdf, img, MIvalid_range, NC_DOUBLE, 2, vrange); max=micreate_std_variable(cdf, MIimagemax, NC_DOUBLE, 0, NULL); min=micreate_std_variable(cdf, MIimagemin, NC_DOUBLE, 0, NULL); /* End definition mode */ ncendef(cdf); /* Attach image variable */ (void) miicv_attach(icv, cdf, img); /* Write the image max and min */ ncvarput1(cdf, max, NULL, &image_maximum); ncvarput1(cdf, min, NULL, &image_minimum); /* Write the image */ start[0]=start[1]=0; count[0]=ysize; count[1]=xsize; miicv_put(icv, start, count, vals); /* Close the file and free the icv */ (void) ncclose(cdf); (void) miicv_free(icv); \end{verbatim} If we were writing a floating point image, the only difference (apart from changing \verb+NC_BYTE+ to \verb+NC_FLOAT+) would be that we would rewrite \verb+MIvalid_range+ at the end of the file with the full range of floating point values. \subsubsection{Dimension conversion} One of the problems of arbitrary dimensioned images is that it becomes necessary for software to handle the general case. It is easier to write application software if it is known in advance that all images will have a specific size (e.g. $256\times 256$) and a specific orientation (e.g. the first pixel is at the patient's anterior, right side). By setting the icv property \verb+MI_ICV_DO_DIM_CONV+ to \verb+TRUE+ these conversions can be done automatically. The orientation of spatial axes is determined by the properties \verb+MI_ICV_XDIM_DIR+, \verb+MI_ICV_YDIM_DIR+ and \verb+MI_ICV_ZDIM_DIR+. These affect any image dimensions that are \verb+MI?space+ or \verb+MI?frequency+ where \verb+?+ corresponds to \verb+x+, \verb+y+ or \verb+z+. These properties can have values \verb+MI_ICV_POSITIVE+, \verb+MI_ICV_NEGATIVE+ or \verb+MI_ICV_ANYDIR+. The last of these will prevent flipping of the dimension. The first two will flip the dimension if necessary so that the attribute \verb+MIstep+ of the dimension variable will have the correct sign. The two image dimensions are referred to as dimensions A and B. Dimension A is the fastest varying dimension of the two. Setting properties \verb+MI_ICV_ADIM_SIZE+ and \verb+MI_ICV_BDIM_SIZE+ specify the desired size for the image dimension. Dimensions are resized so that the file image will fit entirely in the calling program's image, and is centred in the image. The size \verb+MI_ICV_ANYSIZE+ allows one of the dimensions to have a variable size. If property \verb+MI_ICV_KEEP_ASPECT+ is set to \verb+TRUE+, then the two dimensions are rescaled by the same amount. It is possible to inquire about the new step and start, corresponding to attributes \verb+MIstep+ and \verb+MIstart+ (where pixel position = ipixel*step + start, with ipixel counting from zero). The properties \verb+MI_ICV_?DIM_STEP+ and \verb+MI_ICV_?DIM_START+ (\verb+?+ = \verb+A+ or \verb+B+) are set automatically and can be inquired but not set. Although vector images are allowed, many applications would rather only deal with scalar images (one intensity value at each point). Setting \verb+MI_ICV_DO_SCALAR+ to \verb+TRUE+ (the default) will cause vector images to be converted to scalar images by averaging the components. (Thus, RGB images are automatically converted to gray-scale images in this simple way). It can sometimes be useful for a program to perform dimension conversions on three (or perhaps more) dimensions, not just the two standard image dimensions. To perform dimension flipping and/or resizing on dimensions beyond the usual two, the property \verb+MI_ICV_NUM_IMGDIMS+ can be set to an integer value between one and \verb+MI_MAX_IMGDIMS+. To set the size of a dimension, set the property \verb+MI_ICV_DIM_SIZE+ (analogous to \verb+MI_ICV_ADIM_SIZE+). To specify the dimension to be set, add the dimension to the property (adding zero corresponds to the fastest varying dimension --- add zero for the ``A'' dimension, one for the ``B'' dimension, etc.). Voxel separation and location can be inquired about through the properties \verb+MI_ICV_DIM_STEP+ and \verb+MI_ICV_DIM_START+ (analogous to \verb+MI_ICV_ADIM_STEP+ and \verb+MI_ICV_ADIM_START+), again adding the dimension number to the property. \subsubsection{Example: Reading with dimension conversion} Reading a $256 \times 256$ image with the first pixel at the patient's inferior, posterior, left side as short values between 0 and 32000: \begin{verbatim} /* Create the icv */ icv=miicv_create(); (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT); (void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED); (void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000); (void) miicv_setint(icv, MI_ICV_VALID_MIN, 0); (void) miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE); (void) miicv_setint(icv, MI_ICV_ADIM_SIZE, 256); (void) miicv_setint(icv, MI_ICV_BDIM_SIZE, 256); (void) miicv_setint(icv, MI_ICV_KEEP_ASPECT, TRUE); (void) miicv_setint(icv, MI_ICV_XDIM_DIR, MI_POSITIVE); (void) miicv_setint(icv, MI_ICV_YDIM_DIR, MI_POSITIVE); (void) miicv_setint(icv, MI_ICV_ZDIM_DIR, MI_POSITIVE); /* Open the file, attach the image variable */ cdfid=ncopen(filename, NC_NOWRITE); /* Attach image variable */ img=ncvarid(cdfid, MIimage); (void) miicv_attach(icv, cdfid, img); /* Get the data - we assume that coord and count are set properly */ (void) miicv_get(icv, coord, count, image); /* Close the file and free the icv */ (void) ncclose(cdfid); (void) miicv_free(icv); \end{verbatim} \end{document} minc-2.2.00/doc/prog_ref.tex0000644000265600003100000013353112027132661012537 00000000000000% % Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, % Montreal Neurological Institute, McGill University. % Permission to use, copy, modify, and distribute this % software and its documentation for any purpose and without % fee is hereby granted, provided that the above copyright % notice appear in all copies. The author and McGill University % make no representations about the suitability of this % software for any purpose. It is provided "as is" without % express or implied warranty. % \documentclass{article} \title{MINC Programmer's Reference Manual} \author{Peter Neelin} \date{November 3, 1993} \textwidth 6.0in \oddsidemargin 0.125in \textheight 8.5in \topmargin -0.75in \parindent 0in \begin{document} \def\code#1{{\tt #1}} \maketitle \tableofcontents \clearpage \section{Dimension, variable and attribute names} Of all of the variables, dimensions and attributes described here, only the variable \code{MIimage} and its dimensions are required to be present in a MINC file. Additional variables, dimensions and attributes may be present in the file --- unrecognised variables and attributes should be ignored. A word on attribute conventions. All numeric values should be stored in one of the numeric types (\code{NC\_BYTE}, \code{NC\_SHORT}, \code{NC\_INT}, \code{NC\_FLOAT} or \code{NC\_DOUBLE}). Some numeric attributes must be specified in a definite unit --- time attributes (such as \code{MIrepetition\_time} and \code{MIradionuclide\_halflife}) are given in seconds. Other attributes have an associated attribute that gives the unit --- e.g. \code{MIinjection\_dose} and \code{MIdose\_units}. \subsection{NetCDF standard attributes} These attributes can be used with any variable. Fuller descriptions can be obtained from the NetCDF user's guide. \begin{description} \item [\code{MIunits}] Specifies the units of the variable values as a string --- units should be compatible with the udunits library. \item [\code{MIlong\_name}] A string giving a textual description of the variable for human consumption. \item [\code{MIvalid\_range}] A vector of two numbers specifying the minimum and maximum valid values in the variable. For the MINC routines the order is not important. For the \code{MIimage} variable, this attribute (or \code{MIvalid\_max} and \code{MIvalid\_min}) should always be present unless the defaults of full range for integer types and [0.0,1.0] for floating point types is correct. \item [\code{MIvalid\_max}] A number giving the valid maximum for the variable. \item [\code{MIvalid\_min}] A number giving the valid minimum for the variable. \item [\code{MI\_FillValue}] Number to be used for filling in values in the variable that are not explicitly written. \item [\code{MItitle}] A global string that provides a description of what is in the file. \item [\code{MIhistory}] A global string that should store one line for each program that has modified the file. Each line should contain the program name and arguments. \end{description} \subsection{MINC general attributes} These attributes apply to any variable in the file. \begin{description} \item [\code{MIvartype}] A string identifying the type of variable. Should be one of \code{MI\_GROUP}, \code{MI\_DIMENSION}, \code{MI\_DIM\_WIDTH} or \code{MI\_VARATT}. \item [\code{MIvarid}] A string that identifies the origin of the variable. All standard MINC variables should have this attribute with value \code{MI\_STDVAR}. Variables created by users should have a distinctive name that will not be the same as the names used by other applications. \item [\code{MIsigntype}] The NetCDF format does not need to know the sign of variables since it does not interpret values --- it is left up to the invoking program to worry about the signs of integers. Because the MINC interface translates variables, it must have this information. \code{MIsigntype} is a string with value \code{MI\_SIGNED} or \code{MI\_UNSIGNED}. The default values are \code{MI\_UNSIGNED} for bytes and \code{MI\_SIGNED} for all other types. \item [\code{MIparent}] A string identifying by name the parent variable of this variable (either in the data hierarchy or as the parent of this variable attribute). \item [\code{MIchildren}] A newline-separated list of the children of this variable (in the data hierarchy). \item [\code{MIcomments}] Any text that should be included with this variable. \item [\code{MIversion}] A string identifying the file version. The current version is \code{MI\_CURRENT\_VERSION}. Each version can be identified by a constant of the form \code{MI\_VERSION\_1\_0}. \end{description} The constants \code{MI\_TRUE} and \code{MI\_FALSE} are provided for boolean attributes. \subsection{Dimensions and dimension variables} The following are the names of dimensions and their corresponding dimension variables. Only \code{MIvector\_dimension} does not have a corresponding dimension variable. \begin{description} \item [\code{MIxspace}] Dimension and coordinate variable for x axis. \item [\code{MIyspace}] Dimension and coordinate variable for y axis. \item [\code{MIzspace}] Dimension and coordinate variable for z axis. \item [\code{MItime}] Dimension and coordinate for variable time axis. \item [\code{MItfrequency}] Dimension and coordinate variable for temporal frequency. \item [\code{MIxfrequency}] Dimension and coordinate variable for spatial frequency along the x axis. \item [\code{MIyfrequency}] Dimension and coordinate variable for spatial frequency along the y axis. \item [\code{MIzfrequency}] Dimension and coordinate variable for spatial frequency along the z axis. \item [\code{MIvector\_dimension}] Dimension only for components of a vector field. \end{description} In addition to dimension variables, we can have dimension width variables that specify the FWHM width of the sample at each point. \begin{description} \item [\code{MIxspace\_width}] Width of samples along x axis. \item [\code{MIyspace\_width}] Width of samples along y axis. \item [\code{MIzspace\_width}] Width of samples along z axis. \item [\code{MItime\_width}] Width of samples along time axis. \item [\code{MItfrequency\_width}] Width of samples along temporal frequency axis. \item [\code{MIxfrequency\_width}] Width of samples along x spatial frequency axis. \item [\code{MIyfrequency\_width}] Width of samples along y spatial frequency axis. \item [\code{MIzfrequency\_width}] Width of samples along z spatial frequency axis. \end{description} The attributes associated with dimension and dimension width variables are given below: \begin{description} \item [\code{MIspacing}] A string with value \code{MI\_REGULAR} (for a regularly spaced grid) or \code{MI\_IRREGULAR} (for irregular spacing of samples). If the value is \code{MI\_REGULAR}, then the variable is permitted to be a scalar instead of a vector varying with the dimension of the same name. Can be used for both dimension and dimension width variables. \item [\code{MIstep}] A number indicating the step between samples for regular spacing. This value may be negative to indicate orientation (to specify that \code{MIxspace} runs from patient right to left, for example). If the spacing is irregular, then the value can be an average step size. Applies only to dimension variables. \item [\code{MIstart}] The coordinate of the index 0 of the dimension. Applies only to dimension variables. \item [\code{MIspacetype}] A string identifying the type of coordinate space. Currently one of \code{MI\_NATIVE} (the coordinate system of the scanner), \code{MI\_TALAIRACH} (a standardized coordinate system), or \code{MI\_CALLOSAL} (another standardized coordinate system). Applies only to dimension variables. \item [\code{MIalignment}] A string indicating the position of the coordinates relative to each sample (remembering that each sample has a width). Can be one of \code{MI\_START}, \code{MI\_CENTRE} or \code{MI\_END}. Applies only to dimension variables. \item [\code{MIdirection\_cosines}] A vector with \code{MI\_NUM\_SPACE\_DIMS}(=3) elements giving the direction cosines of the axes. Although axes are labelled x, y and z, they may in fact have a signficantly different direction --- this attribute allows the direction relative to the true axes to be specified exactly. Applies only to dimension variables. Note that the dot product of the direction cosine with the corresponding axis ($(1,0,0)$, $(0,1,0)$ or $(0,0,1)$) should be positive so that the sign of the attribute \code{MIstep} contains the orientation information. \item [\code{MIwidth}] For regularly dimension widths, this numeric attribute gives the FWHM width of all samples. It can be used for irregular widths to specify the average width. Applies only to dimension width variables. \item [\code{MIfiltertype}] A string specifying the shape of the convolving filter. Currently, can be one of \code{MI\_SQUARE}, \code{MI\_GAUSSIAN} or \code{MI\_TRIANGULAR}. Applies only to dimension width variables. \end{description} \subsection{Root variable} The variable \code{MIrootvariable} is used as the root of the data hierarchy, with its \code{MIchildren} attribute pointing to the first level of group variables (including all of the MINC group variables), and with its \code{MIparent} attribute an empty string. \subsection{Image variable} The variable \code{MIimage} is used to store the image data. \begin{description} \item [\code{MIimagemax}] A variable attribute (ie. an attribute pointing to a variable of the same name) that stores the real value maximum for the image. This variable should not vary over the image dimensions of MIimage. The units of this variable define the units of the image. \item [\code{MIimagemin}] Like \code{MIimagemax}, but stores the real value minimum for the image. \code{MIimagemax} should not be present without \code{MIimagemin} and vice-versa. \item [\code{MIcomplete}] A boolean attribute (with values \code{MI\_TRUE} or \code{MI\_FALSE}) that indicates whether the variable has been written in its entirety. This can be used to detect program failure when writing out images as they are processed : \code{MIcomplete} is set to \code{MI\_FALSE} at the beginning and changed to \code{MI\_TRUE} at the end of processing. \end{description} \subsection{Patient variable} The variable \code{MIpatient} is a group variable with no dimensions and no useful value. It serves only to group together information about the patient. Attributes are modelled after ACR-NEMA conventions. \begin{description} \item [\code{MIfull\_name}] A string specifying the full name of the patient. \item [\code{MIother\_names}] A string giving other names for the patient. \item [\code{MIidentification}] A string specifying identification information for the patient. \item [\code{MIother\_ids}] A string giving other id's. \item [\code{MIbirthdate}] A string specifying the patient's birthdate. \item [\code{MIsex}] A string specifying the patient's sex: \code{MI\_MALE}, \code{MI\_FEMALE} or \code{MI\_OTHER}. \item [\code{MIage}] A number giving the patient's age. \item [\code{MIweight}] The patient's weight in kilograms. \item [\code{MIsize}] The patient's height or length in metres. \item [\code{MIaddress}] A string giving the patient's address. \item [\code{MIinsurance\_id}] A string giving the patient's insurance plan id. \end{description} \subsection{Study variable} Information about the study is grouped together in the \code{MIstudy} variable which has no dimensions or values. Attributes are modelled after ACR-NEMA conventions. \begin{description} \item [\code{MIstart\_time}] String giving time (and date) of start of the study. \item [\code{MIstart\_year}] Integer giving year of start. \item [\code{MIstart\_month}] Integer giving month (1-12) of start. \item [\code{MIstart\_day}] Integer giving day (1-31) of start. \item [\code{MIstart\_hour}] Integer giving hour (0-23) of start. \item [\code{MIstart\_minute}] Integer giving minute (0-59) of start. \item [\code{MIstart\_seconds}] Floating-point value giving seconds of start. \item [\code{MImodality}] Imaging modality : one of \code{MI\_PET}, \code{MI\_SPECT}, \code{MI\_GAMMA}, \code{MI\_MRI}, \code{MI\_MRS}, \code{MI\_MRA}, \code{MI\_CT}, \code{MI\_DSA}, \code{MI\_DR}. \item [\code{MImanufacturer}] String giving name of device manufacturer. \item [\code{MIdevice\_model}] String identifying device model. \item [\code{MIinstitution}] String identifying institution. \item [\code{MIdepartment}] String identifying department. \item [\code{MIstation\_id}] String identifying machine that generated the images. \item [\code{MIreferring\_physician}] Name of patient's primary physician. \item [\code{MIattending\_physician}] Physician administering the examination. \item [\code{MIradiologist}] Radiologist interpreting the examination. \item [\code{MIoperator}] Name of technologist operating scanner. \item [\code{MIadmitting\_diagnosis}] String description of admitting diagnosis. \item [\code{MIprocedure}] String description of the procedure employed. \item [\code{MIstudy\_id}] String identifying study. \end{description} \subsection{Acquisition variable} Information about the acquisition itself is stored as attributes of the \code{MIacquisition} variable (again, no dimensions and no values). \begin{description} \item [\code{MIprotocol}] String description of the protocol for image acquisition. \item [\code{MIscanning\_sequence}] String description of type of data taken (eg. for MR --- IR, SE, PS, etc.). \item [\code{MIrepetition\_time}] Time in seconds between pulse sequences. \item [\code{MIecho\_time}] Time in seconds between the middle of a 90 degree pulse and the middle of spin echo production. \item [\code{MIinversion\_time}] Time in seconds after the middle of the inverting RF pulse to the middle of the 90 degree pulse to detect the amount of longitudinal magnetization. \item [\code{MInum\_averages}] Number of times a given pulse sequence is repeated before any parameter is changed. \item [\code{MIimaging\_frequency}] Precession frequency in Hz of the imaged nucleus. \item [\code{MIimaged\_nucleus}] String specifying the nucleus that is resonant at the imaging frequency. \item [\code{MIradionuclide}] String specifying the isotope administered. \item [\code{MIcontrast\_agent}] String identifying the contrast or bolus agent. \item [\code{MIradionuclide\_halflife}] Half-life of radionuclide in seconds. \item [\code{MItracer}] String identifying tracer labelled with radionuclide that was injected. \item [\code{MIinjection\_time}] String giving time (and date) of injection. \item [\code{MIinjection\_year}] Integer giving year of injection. \item [\code{MIinjection\_month}] Integer giving month (1-12) of injection. \item [\code{MIinjection\_day}] Integer giving day (1-31) of injection. \item [\code{MIinjection\_hour}] Integer giving hour (0-23) of injection. \item [\code{MIinjection\_minute}] Integer giving minute (0-59) of injection. \item [\code{MIinjection\_seconds}] Floating-point value giving seconds of injection. \item [\code{MIinjection\_length}] Length of time of injection (in seconds). \item [\code{MIinjection\_dose}] Total dose of radionuclide or contrast agent injected (in units specified by \code{MIdose\_units}). \item [\code{MIdose\_units}] String giving units of dose. \item [\code{MIinjection\_volume}] Volume of injection in mL. \item [\code{MIinjection\_route}] String identifying administration route of injection. \end{description} \section{NetCDF routines} Because it is necessary to use NetCDF routines to access MINC files, a brief description of all NetCDF routines is provided here. For more information, see the NetCDF User's Guide. Note that the header file netcdf.h is automatically included by the header file minc.h. \subsection{Error handling} If an error occurs, the default behaviour is to print an error message and exit. It is possible to change this behaviour by modifying the value of the global variable ncopts. The default setting is \begin{verbatim} ncopts = NC_VERBOSE | NC_FATAL; \end{verbatim} which means print error messages and exit when an error occurs. To get error messages without having fatal errors, set \begin{verbatim} ncopts = NC_VERBOSE; \end{verbatim} For neither error messages nor fatal errors, set \begin{verbatim} ncopts = 0; \end{verbatim} In these last two cases, the calling routine should check the function value returned by each call to a NetCDF function. All routines return an integer value. If the value is $-1$ (\code{MI\_ERROR}), then an error has occurred. The value of the global variable \code{ncerr} gives more information on the type of error (see file \code{netcdf.h} for error codes). \subsection{NetCDF file operations} \begin{itemize} \item \code{nccreate} : Create the file specified by \code{path}. The argument \code{cmode} must have a value of either \code{NC\_CLOBBER} or \code{NC\_NOCLOBBER}. The return value is an identifier for the NetCDF file and is used by subsequent NetCDF function calls. \begin{verbatim} int nccreate(char* path,int cmode); \end{verbatim} \item \code{ncopen} : Open the file specified by \code{path}. \code{mode} must have value \code{NC\_NOWRITE} or \code{NC\_WRITE}. The return value is a NetCDF file identifier. \begin{verbatim} int ncopen(char* path,int mode); \end{verbatim} \item \code{ncredef} : Put an open file into define mode. \begin{verbatim} int ncredef(int cdfid); \end{verbatim} \item \code{ncendef} : Put file into data mode. \begin{verbatim} int ncendef(int cdfid); \end{verbatim} \item \code{ncclose} : Close a NetCDF file. \begin{verbatim} int ncclose(int cdfid); \end{verbatim} \item \code{ncinquire} : Inquire about the number of dimensions in a file, the number of variables, the number of global attributes or the id of the unlimited record dimension. Passing a NULL value for any of the pointers means do not return the associated value. \begin{verbatim} int ncinquire(int cdfid,int* ndims,int* nvars,int* natts,int* recdim); \end{verbatim} \item \code{ncsync} : Synchronize an open file to disk. \begin{verbatim} int ncsync(int cdfid); \end{verbatim} \item \code{ncabort} : Abort any changes to the file if it is in define mode. \begin{verbatim} int ncabort(int cdfid); \end{verbatim} \item \code{ncsetfill} : When \code{ncendef} is called, all variables are filled with a fill value by default. To turn this off, call this routine with \code{fillmode} set to \code{NC\_NOFILL} (to turn it back on, use \code{NC\_FILL}). \begin{verbatim} int ncsetfill(int cdfid,int fillmode); \end{verbatim} \end{itemize} \subsection{Dimension operations} \begin{itemize} \item \code{ncdimdef} : Define a dimension with a name and a length. The return value is a dimension id to be used in subsequent calls. \begin{verbatim} int ncdimdef(int cdfid,char* name,long length); \end{verbatim} \item \code{ncdimid} : Get a dimension id from a name. \begin{verbatim} int ncdimid(int cdfid,char* name); \end{verbatim} \item \code{ncdiminq} : Inquire about a dimension (name or length). \begin{verbatim} int ncdiminq(int cdfid,int dimid,char* name,long* length); \end{verbatim} \item \code{ncdimrename} : Rename a dimension. \begin{verbatim} int ncdimrename(int cdfid,int dimid,char* name); \end{verbatim} \end{itemize} \subsection{Variable operations} \begin{itemize} \item \code{ncvardef} : Define a variable by name, giving its datatype, number of dimensions and the dimension id's that subscript the variable. Returns a variable id to be used in subsequent calls. \begin{verbatim} int ncvardef(int cdfid,char* name,nc_type datatype,int ndims,int dim[]); \end{verbatim} \item \code{ncvarid} : Get a variable id from a name. \begin{verbatim} int ncvarid(int cdfid,char* name); \end{verbatim} \item \code{ncvarinq} : Inquire about a variable. Any NULL pointers mean do not return the associated value. It is possible to get the variable name, type, number of dimensions, dimension id's and number of attributes. \begin{verbatim} int ncvarinq(int cdfid,int varid,char* name,nc_type* datatype,int* ndims, int dim[],int* natts); \end{verbatim} \item \code{ncvarput1} : Store a single value at the coordinate specified by \code{coords}. \code{value} must be of the correct data type. \begin{verbatim} int ncvarput1(int cdfid,int varid,long coords[],void* value); \end{verbatim} \item \code{ncvarget1} : Get a single value from the coordinate specified by coords. \begin{verbatim} int ncvarget1(int cdfid,int varid,long coords[],void* value); \end{verbatim} \item \code{ncvarput} : Put a hyperslab (multi-dimensional rectangle) of values starting at \code{start} with edge lengths given by \code{count}. For the C interface, the last dimension varies fastest. Values must be of the correct type. \begin{verbatim} int ncvarput(int cdfid,int varid,long start[],long count[],void* value); \end{verbatim} \item \code{ncvarget} : Get a hyperslab (multi-dimensional rectangle) of values starting at \code{start} with edge lengths given by \code{count}. For the C interface, the last dimension varies fastest. Values must be of the correct type. \begin{verbatim} int ncvarget(int cdfid,int varid,long start[],long count[],void* value); \end{verbatim} \item \code{ncvarrename} : Rename a variable. \begin{verbatim} int ncvarrename(int cdfid,int varid,char* name); \end{verbatim} \item \code{nctypelen} : Get the length (in bytes) of a data type. \begin{verbatim} int nctypelen(nc_type datatype); \end{verbatim} \end{itemize} \subsection{Attribute operations} \begin{itemize} \item \code{ncattput} : Store an attribute by name with variable \code{varid}. The type and length of the attribute must be specified. \begin{verbatim} int ncattput(int cdfid,int varid,char* name,nc_type datatype,int len, void* value); \end{verbatim} \item \code{ncattinq} : Inquire about an attribute by name. Can get either type or length. \begin{verbatim} int ncattinq(int cdfid,int varid,char* name,nc_type* datatype,int* len); \end{verbatim} \item \code{ncattget} : Get an attribute's value by name. \begin{verbatim} int ncattget(int cdfid,int varid,char* name,void* value); \end{verbatim} \item \code{ncattcopy} : Copy an attribute from one variable to another. \begin{verbatim} int ncattcopy(int incdf,int invar,char* name,int outcdf,int outvar); \end{verbatim} \item \code{ncattname} : Get the name of an attribute from its number. The number is not an id, but can change as the number of attributes associated with a variable changes. Attribute numbers run from 0 to natts-1. \begin{verbatim} int ncattname(int cdfid,int varid,int attnum,char* name); \end{verbatim} \item \code{ncattrename} : Rename an attribute. \begin{verbatim} int ncattrename(int cdfid,int varid,char* name,char* newname); \end{verbatim} \item \code{ncattdel} : Delete an attribute. \begin{verbatim} int ncattdel(int cdfid,int varid,char* name); \end{verbatim} \end{itemize} \section{MINC routines} Error handling for MINC routines is the same as for NetCDF functions, with the exception that routines returning pointers will return \code{NULL} instead of \code{MI\_ERROR} when an error occurs. Error codes (returned in \code{ncerr}) can be found in the header file minc.h. \subsection{General convenience functions} \begin{itemize} \item \code{miexpand\_file} : Routine to expand a minc file that has been compressed with compress, pack, gzip or zip (using gunzip, zcat or pcat). The name of the temporary minc file is returned --- this string must be freed by the caller. If the file specified by \code{path} is not compressed, then its name is returned. \code{*create\_tempfile} is set to TRUE if a temporary file is created (and the caller needs to delete the file), FALSE if the original file name is returned. If tempfile is NULL, then the routine generates its own temporary file name, otherwise, the user provided name is used. If \code{header\_only} is TRUE, then the routine will expand only enough of the file to read the header. \begin{verbatim} public char *miexpand_file(char *path, char *tempfile, int header_only, int *created_tempfile); \end{verbatim} \item \code{miopen} : Like \code{ncopen}, but will temporarily uncompress files (compress, pack, gzip, zip) opened with mode \code{NC\_NOWRITE}. \begin{verbatim} public int miopen(char *path, int mode); \end{verbatim} \item \code{micreate} : Like \code{nccreate}. May be enhanced in the future. \begin{verbatim} public int micreate(char *path, int cmode); \end{verbatim} \item \code{miclose} : Like \code{ncclose}, but finishes up for \code{miopen} and \code{micreate}. \begin{verbatim} public int miclose(int cdfid); \end{verbatim} \item \code{miattget} : Like \code{ncattget}, but the caller specifies the desired numeric type and maximum number of values to get. Type is specified with \code{datatype} (the sign is the default for the type: \code{MI\_UNSIGNED} for \code{NC\_BYTE} and \code{MI\_SIGNED} otherwise). \code{max\_length} gives the maximum number of values to get and \code{att\_length} returns the number of values actually read. An error will occur if the attribute type is not numeric. \begin{verbatim} public int miattget(int cdfid, int varid, char *name, nc_type datatype, int max_length, void *value, int *att_length); \end{verbatim} \item \code{miattget1} : Like \code{miattget}, but only one value is returned. If there is more than one value, an error occurs. \begin{verbatim} public int miattget1(int cdfid, int varid, char *name, nc_type datatype, void *value); \end{verbatim} \item \code{miattgetstr} : Gets a string value from an attribute. \code{maxlen} gives the maximum number of characters to be returned (including the terminating \verb+'\0'+). The string is written to the array specified by value and a pointer to the string is returned. \begin{verbatim} public char *miattgetstr(int cdfid, int varid, char *name, int maxlen, char *value); \end{verbatim} \item \code{miattputint} : Write an integer attribute. \begin{verbatim} public int miattputint(int cdfid, int varid, char *name, int value); \end{verbatim} \item \code{miattputdbl} : Write a double precision attribute. \begin{verbatim} public int miattputdbl(int cdfid, int varid, char *name, double value); \end{verbatim} \item \code{miattputstr} : Write a string attribute. \begin{verbatim} public int miattputstr(int cdfid, int varid, char *name, char *value); \end{verbatim} \item \code{mivarget} : Like \code{ncvarget}, but the caller specifies the desired numeric type and sign (either \code{MI\_SIGNED} or \code{MI\_UNSIGNED}). \begin{verbatim} public int mivarget(int cdfid, int varid, long start[], long count[], nc_type datatype, char *sign, void *values); \end{verbatim} \item \code{mivarget1} : Like \code{ncvarget1}, but the caller specifies the desired numeric type and sign. \begin{verbatim} public int mivarget1(int cdfid, int varid, long mindex[], nc_type datatype, char *sign, void *value); \end{verbatim} \item \code{mivarput} : Like \code{ncvarput}, but the caller specifies the numeric type and sign of the values being passed. \begin{verbatim} public int mivarput(int cdfid, int varid, long start[], long count[], nc_type datatype, char *sign, void *values); \end{verbatim} \item \code{mivarput1} : Like \code{ncvarput1}, but the caller specifies the numeric type and sign of the values being passed. \begin{verbatim} public int mivarput1(int cdfid, int varid, long mindex[], nc_type datatype, char *sign, void *value); \end{verbatim} \item \code{miset\_coords} : Set \code{nvals} values of the coordinate vector \code{coords} to \code{value}. A pointer to \code{coords} is returned. \begin{verbatim} public long *miset_coords(int nvals, long value, long coords[]); \end{verbatim} \item \code{mitranslate\_coords} : Translates the coordinate vector \code{incoords} for subscripting variable \code{invar} of file \code{cdfid} to vector \code{outcoords} for subscripting variable \code{outvar}. This is useful when two variables have similar dimensions, but not necessarily the same order of dimensions. If \code{invar} has a dimension that is not in \code{outvar}, then the corresponding coordinate is ignored. If \code{outvar} has a dimension that is not in \code{invar}, then the corresponding coordinate is not modified. A pointer to \code{outcoords} is returned. \begin{verbatim} public long *mitranslate_coords(int cdfid, int invar, long incoords[], int outvar, long outcoords[]); \end{verbatim} \item \code{micopy\_all\_atts} : Copy all of the attributes of one variable to another (possibly across files). \begin{verbatim} public int micopy_all_atts(int incdfid, int invarid, int outcdfid, int outvarid); \end{verbatim} \item \code{micopy\_var\_def} : Copy a variable definition (including attributes) from one file to another. \code{outcdfid} must be in define mode. The id of the newly created variable is returned. \begin{verbatim} public int micopy_var_def(int incdfid, int invarid, int outcdfid); \end{verbatim} \item \code{micopy\_var\_values} : Copy a variable's values from one file to another. \code{incdfid} and \code{outcdfid} must be in data mode. \begin{verbatim} public int micopy_var_values(int incdfid, int invarid, int outcdfid, int outvarid); \end{verbatim} \item \code{micopy\_all\_var\_defs} : Copy all variable definitions from one file to another, excluding a list of variables. The list of \code{nexclude} variable id's is given in \code{excluded\_vars}. \code{outcdfid} must be in define mode. \begin{verbatim} public int micopy_all_var_defs(int incdfid, int outcdfid, int nexclude, int excluded_vars[]); \end{verbatim} \item \code{micopy\_all\_var\_values} : Copy all variable values from one file to another, excluding a list of variables. The list of \code{nexclude} variable id's is given in \code{excluded\_vars}. \code{outcdfid} must be in data mode. \begin{verbatim} public int micopy_all_var_values(int incdfid, int outcdfid, int nexclude, int excluded_vars[]); \end{verbatim} \end{itemize} \subsection{MINC-specific convenience functions} \begin{itemize} \item \code{miget\_datatype} : Get the type and sign information for an image variable. Signed data is indicated by setting \code{is\_signed} to \code{TRUE}; unsigned by \code{FALSE}. \begin{verbatim} public int miget_datatype(int cdfid, int imgid, nc_type *datatype, int *is_signed); \end{verbatim} \item \code{miget\_default\_range} : Returns the default range for a specified type and sign. \begin{verbatim} public int miget_default_range(nc_type datatype, int is_signed, double default_range[]); \end{verbatim} \item \code{miget\_valid\_range} : Gets the valid range information for an image variable. This function handles potential type differences between the \code{valid\_range} attribute and the image data. These differences (particularly float images with double \code{valid\_range}) could otherwise lead to problems in properly identifying invalid data. \begin{verbatim} public int miget_valid_range(int cdfid, int imgid, double valid_range[]); \end{verbatim} \item \code{miset\_valid\_range} : Sets the valid range information for an image variable. This function follows the NetCDF convention of having both variable data and \code{valid\_range} attribute with the same type. \begin{verbatim} public int miset_valid_range(int cdfid, int imgid, double valid_range[]); \end{verbatim} \item \code{miget\_image\_range} : Gets the maximum real range of the image data based on the image-min and image-max variables. \begin{verbatim} public int miget_image_range(int cdfid, double image_range[]); \end{verbatim} \item \code{mivar\_exists} : Tests for the existence of a variable. Returns true if the variable exists. \begin{verbatim} public int mivar_exists(int cdfid, char *varname); \end{verbatim} \item \code{miattput\_pointer} : Create an attribute \code{name} in the variable \code{varid} that points to the variable \code{ptrvarid}. \begin{verbatim} public int miattput_pointer(int cdfid, int varid, char *name, int ptrvarid); \end{verbatim} \item \code{miattget\_pointer} : Returns the variable id pointed to by attribute \code{name} of variable \code{varid}. \begin{verbatim} public int miattget_pointer(int cdfid, int varid, char *name); \end{verbatim} \item \code{miadd\_child} : Add the name of variable \code{child\_varid} to the \code{MIchildren} attribute of variable \code{parent\_varid} and set the \code{MIparent} attribute of variable \code{child\_varid} to the name of variable \code{parent\_varid}. If the attributes do not exist, they are created. The names in the attribute \code{MIchildren} are separated by newlines. \begin{verbatim} public int miadd_child(int cdfid, int parent_varid, int child_varid); \end{verbatim} \item \code{micreate\_std\_variable} : Create any of the standard MINC variables and set some attributes. Called in the manner of \code{ncvardef}. The id of the newly created variable is returned. For all variables, attributes \code{MIvarid}, \code{MIvartype} and \code{MIversion} are all set. For dimension and dimension width variables, \code{MIspacing} is set to \code{MI\_REGULAR} if the number of dimensions is zero and \code{MI\_IRREGULAR} otherwise. For dimension variables, \code{MIalignment} is set to \code{MI\_CENTRE} unless the variable is \code{MItime}, then it is set to \code{MI\_START}. As well, MIcomments is set to a string describing the direction of the world coordinates of spatial dimensions. For dimension width variables, \code{MIfiltertype} is set to \code{MI\_SQUARE}. For \code{MIimage} and for \code{MIimagemax} and \code{MIimagemin}, dimensions are checked to ensure that the last two do not vary over image dimensions and attribute pointers from \code{MIimage} are created to point to the other two. \begin{verbatim} public int micreate_std_variable(int cdfid, char *name, nc_type datatype, int ndims, int dim[]); \end{verbatim} \item \code{micreate\_group\_variable} : Like \code{micreate\_std\_variable}, but \code{ndims} is always set to zero and the datatype is \code{NC\_INT}. The id of the newly created variable is returned. \begin{verbatim} public int micreate_group_variable(int cdfid, char *name); \end{verbatim} \end{itemize} \subsection{Image conversion variable functions} \begin{itemize} \item \code{miicv\_create} : Create an image conversion variable and set the defaults --- an icv identifier is returned for later use (or \code{MI\_ERROR} if an error occurs). The old limit of \code{MI\_MAX\_NUM\_ICV} icv's that can exist at one time has been removed, although the definition remains. \begin{verbatim} public int miicv_create(); \end{verbatim} \item \code{miicv\_free} : Free an image conversion variable. \begin{verbatim} public int miicv_free(int icvid); \end{verbatim} \item \code{miicv\_setdbl} : Set a numeric icv property to a double value. \begin{verbatim} public int miicv_setdbl(int icvid, int icv_property, double value); \end{verbatim} \item \code{miicv\_setint} : Set a numeric icv property to an integer value. \begin{verbatim} public int miicv_setint(int icvid, int icv_property, int value); \end{verbatim} \item \code{miicv\_setlong} : Set a numeric icv property to a long integer value. \begin{verbatim} public int miicv_setlong(int icvid, int icv_property, long value); \end{verbatim} \item \code{miicv\_setstr} : Set a string icv property. \begin{verbatim} public int miicv_set(int icvid, int icv_property, char *value); \end{verbatim} \item \code{miicv\_inqdbl} : Inquire about a numeric icv property. \code{value} points to the double precision variable in which the value should be returned. \begin{verbatim} public int miicv_inqdbl(int icvid, int icv_property, double *value); \end{verbatim} \item \code{miicv\_inqint} : Inquire about a numeric icv property. \code{value} points to the integer variable in which the value should be returned. \begin{verbatim} public int miicv_inqint(int icvid, int icv_property, int *value); \end{verbatim} \item \code{miicv\_inqlong} : Inquire about a numeric icv property. \code{value} points to the long integer variable in which the value should be returned. \begin{verbatim} public int miicv_inqlong(int icvid, int icv_property, long *value); \end{verbatim} \item \code{miicv\_inqstr} : Inquire about a string icv property. \code{value} points to the character array in which the value should be returned. The calling routine must allocate enough space for the return string. \begin{verbatim} public int miicv_inqstr(int icvid, int icv_property, char *value); \end{verbatim} \item \code{miicv\_attach} : Attach a MINC file and image variable to an icv. Note that icv properties cannot be modified while a variable is attached to the icv. If a variable is already attached to the icv, then it is automatically detached. The file \code{icvid} must be in data mode. \begin{verbatim} public int miicv_attach(int icvid, int cdfid, int varid); \end{verbatim} \item \code{miicv\_ndattach} : Like \code{miicv\_attach} but no dimension conversion facilities are available (much like setting \code{MI\_ICV\_DO\_DIM\_CONV} to \code{FALSE}). This avoids linking in all of the dimension conversion routines when they are not needed (for machines where memory may be a concern). \begin{verbatim} public int miicv_ndattach(int icvid, int cdfid, int varid); \end{verbatim} \item \code{miicv\_detach} : Detach a variable from an icv. \begin{verbatim} public int miicv_detach(int icvid); \end{verbatim} \item \code{miicv\_get} : Get a hyperslab of values from a variable through an icv. \begin{verbatim} public int miicv_get(int icvid, long start[], long count[], void *values); \end{verbatim} \item \code{miicv\_put} : Put a hyperslab of values to a variable through an icv. \begin{verbatim} public int miicv_put(int icvid, long start[], long count[], void *values); \end{verbatim} \end{itemize} \section{Image conversion variable properties} \begin{itemize} \item \code{MI\_ICV\_TYPE} (type \code{nc\_type}) : Specifies the type of values that the user wants. Modifying this property automatically causes \code{MI\_ICV\_VALID\_MAX} and \code{MI\_ICV\_VALID\_MIN} to be set to their default values. Default = \code{NC\_SHORT}. \item \code{MI\_ICV\_SIGN} (type \code{char *}) : Specifies the sign of values that the user wants (irrelevant for floating point types). Modifying this property automatically causes \code{MI\_ICV\_VALID\_MAX} and \code{MI\_ICV\_VALID\_MIN} to be set to their default values. Default = \code{MI\_SIGNED}. \item \code{MI\_ICV\_DO\_RANGE} (type \code{int}) : When \code{TRUE}, range conversions (for valid max and min and for value normalization) are done. When \code{FALSE}, values are not modified. Default = \code{TRUE}. \item \code{MI\_ICV\_VALID\_MAX} (type \code{double}) : Valid maximum value (ignored for floating point types). Default = maximum legal value for type and sign (1.0 for floating point types). \item \code{MI\_ICV\_VALID\_MIN} (type \code{double}) : Valid minimum value (ignored for floating point types). Default = minimum legal value for type and sign (1.0 for floating point types). \item \code{MI\_ICV\_DO\_NORM} (type \code{int}) : If \code{TRUE}, then normalization of values is done (see user guide for details of normalization). Default = \code{FALSE}. \item \code{MI\_ICV\_USER\_NORM} (type \code{int}) : If \code{TRUE}, then the user specifies the normalization maximum and minimum. If \code{FALSE}, values are taken as maximum and minimum for whole image variable. Default = \code{FALSE}. \item \code{MI\_ICV\_IMAGE\_MAX} (type \code{double}) : Image maximum for user normalization. Default = 1.0. \item \code{MI\_ICV\_IMAGE\_MIN} (type \code{double}) : Image minimum for user normalization. Default = 0.0. \item \code{MI\_ICV\_NORM\_MAX} (type \code{double}) : Read-only value giving the user image maximum when doing normalization (either the maximum in the variable or the user specified maximum). \item \code{MI\_ICV\_NORM\_MIN} (type \code{double}) : Read-only value giving the user image minimum when doing normalization (either the minimum in the variable or the user specified minimum). \item \code{MI\_ICV\_DO\_FILLVALUE} (type \code{int}) : If set to \code{TRUE}, then range checking is done on input and values that are out of range (value in the file less than \code{MIvalid\_min} or greater than \code{MIvalid\_max}) are set to the value of \code{MI\_ICV\_FILLVALUE}. Default = \code{FALSE}. \item \code{MI\_ICV\_FILLVALUE} (type \code{double}) : Value to use when pixels are out of range (on input only). This value is written to user's buffer directly without any scaling. Default = \code{-DBL\_MAX}. \item \code{MI\_ICV\_DO\_DIM\_CONV} (type \code{int}) : If set to \code{TRUE}, then dimension conversions may be done. Default = \code{FALSE}. \item \code{MI\_ICV\_DO\_SCALAR} (type \code{int}) : If \code{TRUE}, then if \code{MIvector\_dimension} is the fastest varying dimension of the variable, elements are averaged and the icv behaves as though this dimension did not exist. Default = \code{TRUE}. \item \code{MI\_ICV\_XDIM\_DIR} (type \code{int}) : Indicates the desired orientation of the x image dimensions (\code{MIxspace} and \code{MIxfrequency}). Values can be one of \code{MI\_ICV\_POSITIVE}, \code{MI\_ICV\_NEGATIVE} or \code{MI\_ICV\_ANYDIR}. A positive orientation means that the \code{MIstep} attribute of the dimension is positive. \code{MI\_ICV\_ANYDIR} means that no flipping is done. Default = \code{MI\_ICV\_POSITIVE}. \item \code{MI\_ICV\_YDIM\_DIR} (type \code{int}) : Indicates the desired orientation of the y image dimensions. Default = \code{MI\_ICV\_POSITIVE}. \item \code{MI\_ICV\_ZDIM\_DIR} (type \code{int}) : Indicates the desired orientation of the z image dimensions. Default = \code{MI\_ICV\_POSITIVE}. \item \code{MI\_ICV\_ADIM\_SIZE} (type \code{long}) : Specifies the desired size of the fastest varying image dimension. A value of \code{MI\_ICV\_ANYSIZE} means that the actual size of the dimension should be used. Default = \code{MI\_ICV\_ANYSIZE}. \item \code{MI\_ICV\_BDIM\_SIZE} (type \code{long}) : Specifies the desired size of the second image dimension. Default = \code{MI\_ICV\_ANYSIZE}. \item \code{MI\_ICV\_KEEP\_ASPECT} (type \code{int}) : If \code{TRUE}, then image dimensions are resized by the same amount so that aspect ratio is maintained. Default = \code{TRUE}. \item \code{MI\_ICV\_ADIM\_STEP} (type \code{double}) : Read-only property that gives the equivalent of attribute \code{MIstep} for the first (fastest varying) image dimension after dimension conversion. \item \code{MI\_ICV\_BDIM\_STEP} (type \code{double}) : Read-only property that gives the equivalent of attribute \code{MIstep} for the second image dimension after dimension conversion. \item \code{MI\_ICV\_ADIM\_START} (type \code{double}) : Read-only property that gives the equivalent of attribute \code{MIstart} for the first (fastest varying) image dimension after dimension conversion. \item \code{MI\_ICV\_BDIM\_START} (type \code{double}) : Read-only property that gives the equivalent of attribute \code{MIstart} for the second image dimension after dimension conversion. \item \code{MI\_ICV\_NUM\_IMGDIMS} (type \code{int}) : Specifies the number of image dimensions used in dimension conversions. Default = 2. \item \code{MI\_ICV\_DIM\_SIZE} (type \code{long}) : Specifies the desired size of an image dimension. The number of the dimension to be changed should be added to the property (adding zero corresponds to the fastest varying dimension). Default = \code{MI\_ICV\_ANYSIZE}. \item \code{MI\_ICV\_DIM\_STEP} (type \code{double}) : Read-only property that gives the equivalent of attribute \code{MIstep} for the an image dimension after dimension conversion. The number of the dimension to be queried should be added to the property (adding zero corresponds to the fastest varying dimension). \item \code{MI\_ICV\_DIM\_START} (type \code{double}) : Read-only property that gives the equivalent of attribute \code{MIstart} for an image dimension after dimension conversion. The number of the dimension to be queried should be added to the property (adding zero corresponds to the fastest varying dimension). \item \code{MI\_ICV\_NUM\_DIMS} (type \code{int}) : Read-only property that gives the number of dimensions of the image variable, taking into account the conversion of vector images into scalar images. \item \code{MI\_ICV\_CDFID} (type \code{int}) : Read-only property that gives the id of the currently attached NetCDF file, or \code{MI\_ERROR} if no file is attached. \item \code{MI\_ICV\_VARID} (type \code{int}) : Read-only property that gives the id of the currently attached NetCDF variable, or \code{MI\_ERROR} if no variable is attached. \item \code{MI\_ICV\_MAXVAR} (type \code{char *}) : String property specifying the name of the variable that gives the image maximum. Default = \code{MIimagemax}. \item \code{MI\_ICV\_MINVAR} (type \code{char *}) : String property specifying the name of the variable that gives the image minimum. Default = \code{MIimagemin}. \end{itemize} \section{Known bugs} \begin{itemize} \item For dimension conversion with image conversion variables, the values of \code{MI\_ICV\_DIM\_START}, \code{MI\_ICV\_ADIM\_START} and \code{MI\_ICV\_BDIM\_START} are computed assuming that \code{MIalignment} is equal to \code{MI\_CENTRE}. \end{itemize} \end{document}